package main import ( "fmt" "time" ) // State represents the current state of our machine. type State string const ( StateIdle State = "Idle" StateProcessing State = "Processing" StateError State = "Error" StateFinished State = "Finished" ) // Event represents an input that can trigger a state transition. type Event string const ( EventStartProcess Event = "StartProcess" EventProcessDone Event = "ProcessDone" EventProcessError Event = "ProcessError" EventReset Event = "Reset" EventQuit Event = "Quit" ) // stateMachineGoroutine manages the state based on incoming events. func stateMachineGoroutine(events <-chan Event, status chan<- State) { currentState := StateIdle status <- currentState // Report initial state for { select { case event := <-events: switch currentState { case StateIdle: switch event { case EventStartProcess: currentState = StateProcessing fmt.Printf("State Machine: Transitioned to %s ", currentState) case EventQuit: fmt.Println("State Machine: Quitting from Idle.") return default: fmt.Printf("State Machine: Invalid event %s for state %s ", event, currentState) } case StateProcessing: switch event { case EventProcessDone: currentState = StateFinished fmt.Printf("State Machine: Transitioned to %s ", currentState) case EventProcessError: currentState = StateError fmt.Printf("State Machine: Transitioned to %s ", currentState) case EventQuit: fmt.Println("State Machine: Quitting from Processing.") return default: fmt.Printf("State Machine: Invalid event %s for state %s ", event, currentState) } case StateError, StateFinished: switch event { case EventReset: currentState = StateIdle fmt.Printf("State Machine: Transitioned to %s ", currentState) case EventQuit: fmt.Println("State Machine: Quitting from Error/Finished.") return default: fmt.Printf("State Machine: Invalid event %s for state %s ", event, currentState) } } status <- currentState // Report new state } } } func main() { eventCh := make(chan Event) statusCh := make(chan State) go stateMachineGoroutine(eventCh, statusCh) // Wait for initial state fmt.Printf("Main: Initial state: %s ", <-statusCh) // Simulate events eventCh <- EventStartProcess fmt.Printf("Main: Current state: %s ", <-statusCh) time.Sleep(100 * time.Millisecond) // Simulate some work eventCh <- EventProcessDone fmt.Printf("Main: Current state: %s ", <-statusCh) eventCh <- EventReset fmt.Printf("Main: Current state: %s ", <-statusCh) eventCh <- EventStartProcess fmt.Printf("Main: Current state: %s ", <-statusCh) eventCh <- EventProcessError fmt.Printf("Main: Current state: %s ", <-statusCh) eventCh <- EventQuit // Signal the state machine to quit time.Sleep(50 * time.Millisecond) // Give it a moment to exit fmt.Println("Main: Application finished.") }