2021-09-04 the simplest Golang timer application and the simplest introduction to collaboration

Keywords: Go

package main

import (
	"fmt"
	"time"
)

type Timer struct {
	Interval int     //  set time interval
	Tick     func()	 //  When the time is up, which program will be called?
}

func (t Timer) Enabled() chan bool {
	channel := make(chan bool) // Create a channel
	ticker := time.NewTicker(time.Duration(t.Interval) * time.Millisecond)
	// A ticker is generated. When the time specified by Intervar is reached, Tick() is executed, and the unit is milliseconds
	go func() { // Start a collaborative process
		for {	// The coroutine is an endless loop. It will not exit until the content of the channel is detected
			select {
			case <-channel:	// It is detected that there is content from the channel. No matter what the content is, stop ticker directly
				ticker.Stop()
				return
			case <-ticker.C: // . C is a built-in member of ticker, which sends the current time into the ticker channel
				t.Tick()     // After detecting the contents of the ticker channel, execute the Tick() function
			}
		}
	}() // The following () means to execute immediately
	return channel // Returns the value of the channel
}

func main() {
// The usage is as follows:
	tick1 := func() { // First, define two functions to be executed after the timer expires: ticke1 and ticke2
		fmt.Println(" C&C ")
	}

	tick2 := func() {
		fmt.Println(" KKND ")
	}

	timer1 := new(Timer)
	timer1.Interval = 500		// Execute the tick1 function once every 500ms
	timer1.Tick = tick1			
	ch1 := timer1.Enabled()	    // Start timer 1 and return the channel value

	timer2 := new(Timer)
	timer2.Interval = 1000
	timer2.Tick = tick2
	ch2 := timer2.Enabled()

// main loop (dead)
	for {
		var cmds string
		fmt.Scanln(&cmds) // Detect user input
		if cmds == "1" {  // If you enter 1, timer1 is turned off
			ch1 <- false  // Note: the closing method is a little strange. This line means to pass a value to the ch1 channel,
						  // In fact, both true and false are the same here. The key is to send the value to the channel, and do not care about the value.
		}
		if cmds == "2" {
			ch2 <- true
		}
	}
}

I feel that the comments have been made very clear. If you know a little about the Go collaboration process, the above code is still very simple. I won't repeat it any more. I'll just say it briefly. What needs to be understood most is the concept of Golang collaborative process:

  • channel := make(chan bool)
    Indicates to create a channel named channel, and the type is Boolean. chan is a special type, which is used for variable interaction between main program and coroutine. v: = < - channel means: get the variables of the channel and store them in v. note: the pipeline itself is not the value of the variable, but the value of the variable can be transmitted through the pipeline. One end of the pipeline is connected to the main program and the other end is connected to the protocol. For example, on the main program side, we enter: channel < - true, which means that the value of true is sent to the pipeline. Then on the collaborative process side, we pass v: = channel, and v is true at this time.
  • What is a select case?
    Each channel can be managed through it. Vernacular: how to deal with new things in each channel?
  • What the hell is ticker.C?
    It is the current time. The Go timer automatically generates a channel at time.NewTicker and sends the current time to this channel according to the specified time interval (such as 500 milliseconds). If our business requirements do not pay attention to the current time, this value can be ignored. It can only be regarded as a signal of "time is up".
  • Why are there two for {} loops?
    The go language starts the cooperation process with the "go" keyword + function name, or the anonymous function go func() {}. In particular, if the anonymous function is not followed by a pair of parentheses (), the program will not be executed immediately. Therefore, what we see in the example is:
go func() {
Program content...
} ()

It means to start a process and execute it immediately.
After the collaboration is started, it has nothing to do with the main program, but we can make them contact each other through the channel (for example, the main program sends a variable to the collaboration through the channel, makes it exit, and so on). We can see that there is a for {} loop inside the collaboration, which has been scanning the changes on the channel through select case {}.

The second for {} loop in the main function is easier to understand. There must be a mechanism to ensure that the program will not exit naturally. It is for this purpose.

Posted by gordonrp on Fri, 03 Sep 2021 19:07:01 -0700