go time package timer and breaker

Posted by mattyj10 on Thu, 29 Aug 2019 03:28:53 +0200

Original Link: https://www.kancloud.cn/digest/batu-go/153534

timer

There are two functions in the time package that can help us initialize time.Timer

time.Newtimer function
Initialize a timer that expires at an interval of 3 hours and 30 minutes

t := time.Newtimer(3*time.Hour + 30*time.Minute)

Note that the variable t here is of type *time.NewTimer, and the collection of methods of this pointer type contains two methods

  • Rest
    For resetting the timer
    This method returns a bool-type value
  • Stop
    To stop the timer
    The method returns a bool-type value that, if false, indicates that the timer has expired or stopped before, and vice versa, returns true.

The timer field C lets us know in time that the event that the timer expires is coming. C is a chan time.Time type buffer channel. Once the expiration time is touched, the timer sends its own C field an element value of type time.Time

Example 1: A simple timer

package main

import (
    "fmt"
    "time"
)

func main(){
    //Initialization timer
    t := time.NewTimer(2 * time.Second)
    //current time
    now := time.Now()
    fmt.Printf("Now time : %v.\n", now)

    expire := <- t.C
    fmt.Printf("Expiration time: %v.\n", expire)
}
Now time : 2015-10-31 01:19:07.210771347 +0800 CST.
Expiration time: 2015-10-31 01:19:09.215489592 +0800 CST.

Example 2: The simple timeout we did before the transformation

package main

import (
    "fmt"
    "time"
)
func main(){
    //Initialize Channel
    ch11 := make(chan int, 1000)
    sign := make(chan byte, 1)

    //Write data to ch11 channel
    for i := 0; i < 1000; i++ {
        ch11 <- i
    }

    //select from a single Goroutine
    go func(){
        var e int
        ok := true
        //First declare a value of type *time.Timer, then reuse it as much as possible in anonymous functions declared after the associated case
        var timer *time.Timer

        for{
            select {
                case e = <- ch11:
                    fmt.Printf("ch11 -> %d\n",e)
                case <- func() <-chan time.Time {
                    if timer == nil{
                        //Initialize a timer with an expiration time of 1 ms
                        timer = time.NewTimer(time.Millisecond)
                    }else {
                        //Reuse, reset timer by Reset method
                        timer.Reset(time.Millisecond)
                    }
                    //Return the result when you know the timer expiration event is coming
                    return timer.C
                }():
                    fmt.Println("Timeout.")
                    ok = false
                    break
            }
            //End for loop
            if !ok {
                sign <- 0
                break
            }
        }

    }()

    //Used technique to read sign channel data in order to wait for Goroutine to select to execute.
    <- sign
}

time.After function
The time.After function, which indicates how long after, but does not block until the channel content is removed, and subsequent programs can continue executing

Because of the After feature, it is often used to handle timeout problems

package main

import (
    "fmt"
    "time"
)

func main(){
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)

    select {
        case e1 := <-ch1:
        //If the ch1 channel successfully reads data, execute the case processing statement
            fmt.Printf("1th case is selected. e1=%v",e1)
        case e2 := <-ch2:
        //If the ch2 channel successfully reads the data, execute the case processing statement
            fmt.Printf("2th case is selected. e2=%v",e2)
        case <- time.After(2 * time.Second):
            fmt.Println("Timed out")
    }
}

time.Sleep function
Indicates how long to sleep, is blocked while hibernating, and subsequent programs cannot be executed.

time.Afterfunc function
Example 3: Custom timer

package main

import (
    "fmt"
    "time"
)
func main(){
    var t *time.Timer

    f := func(){
        fmt.Printf("Expiration time : %v.\n", time.Now())
        fmt.Printf("C`s len: %d\n", len(t.C))
    }

    t = time.AfterFunc(1*time.Second, f)
    //Sleep the current Goroutine for 2s to make sure it is more complete than the content
    //This is done because the call to time.AfterFunc will not be blocked.It will execute our custom function f in one way at the expiration event.
    time.Sleep(2 * time.Second)
}
Expiration time : 2015-10-31 01:04:42.579988801 +0800 CST.
C`s len: 0

The second line shows that field C of the timer does not buffer any element values.This also means that, given a custom function, the default processing method (sending an element value to C representing the absolute expiration time) will not be executed.

Interruptor

The structure type time.Ticker represents the static structure of the breaker.
It is the device that periodically transmits the expiration time.The device behaves somewhat like a clock with only a second hand, except that the interval may not be 1s.
Initialize a Breaker

var ticker *timeTicker = time.NewTicker(time.Second)
//Example 1: Stop ticke using time control
package main

import (
    "fmt"
    "time"
)

func main(){
    //Initialize the breaker at 2s intervals
    var ticker *time.Ticker = time.NewTicker(1 * time.Second)

    go func() {
        for t := range ticker.C {
            fmt.Println("Tick at", t)
        }
    }()

    time.Sleep(time.Second * 5)   //Blocked, sleep time/ticker time of sleep execution
    ticker.Stop()     
    fmt.Println("Ticker stopped")
}
Tick at 2015-10-31 01:29:34.41859284 +0800 CST
Tick at 2015-10-31 01:29:35.420131668 +0800 CST
Tick at 2015-10-31 01:29:36.420565647 +0800 CST
Tick at 2015-10-31 01:29:37.421038416 +0800 CST
Tick at 2015-10-31 01:29:38.41944582 +0800 CST
Ticker stopped

Example 2: Stop ticker using channel control

package main

import (
    "fmt"
    "time"
)

func main(){
    //Initialize the breaker at 2s intervals
    var ticker *time.Ticker = time.NewTicker(100 * time.Millisecond)

    //num is the specified number of executions
    num := 2
    c := make(chan int, num) 
    go func() {
        for t := range ticker.C {
            c <- 1
            fmt.Println("Tick at", t)
        }
    }()

    time.Sleep(time.Millisecond * 1500)
    ticker.Stop()     
    fmt.Println("Ticker stopped")
}

Topics: REST