Go study notes - channel supplement

Go study notes - channel supplement


1. Timeout processing

Timeouts are very important for a program that connects to external resources, or some other operation that takes time to execute.

In the Go language, timeout operations can be handled concisely and elegantly through channeland .select

c1Implement an external call through an anonymous function, and return its execution result through the channel after 2 seconds .

func main(){
    
    
	c1 := make(chan string,1)
    go func(){
    
    
        //设置通道返回结果的时间
		time.Sleep(time.Second * 2)
		c1 <- "result 1"
	}()
}

Through the channel selector select, handle the timeout operation.

func main(){
    
    
    select {
    
    
	case res := <-c1:
        //不超时直接返回结果
		fmt.Println(res)
	case <- time.After(time.Second * 1):
        //超时返回下面结果
		fmt.Println("timeout 1")
	}
}

//timeout 1

Similarly, set the channel to return the result after 2 seconds, but set the timeout period to 3 seconds, and the value in the channel can be returned normally.

func main(){
    
    
    c2 := make(chan string,1)
	go func(){
    
    
		time.Sleep(time.Second * 2)
		c2 <- "result 2"
	}()

	select {
    
    
	case res := <-c2:
		fmt.Println(res)
	case <- time.After(time.Second * 3):
		fmt.Println("timeout 2")
	}
}

//result 2

2. Non-blocking channel operation

Regular use of channels to send and receive data is blocking.

Using statements with defaultclauses selectenables non-blocking send and receive, and even non-blocking multiplex select.

In the example, if messagesthere is a value in , selectput this value into <- messages case, otherwise defaultexecute it directly in the clause.

func main(){
    
    
    messages := make(chan string)
    //singals := make(chan bool)

    select {
    
    
    case msg := <-messages:
        fmt.Println("received message",msg)
    default:
        fmt.Println("no message received")
    }
}

As you can see by example, defaultclauses can provide output to the user when no values ​​are received in the channel.

Ensure that after the channel is defined, the console will not report an error if it is not used to transmit data.

func main(){
    
    
    messages := make(chan string)
    
    msg := "hi"

    //go func() {
    
    
    //    messages <- msg
    //}()

    select {
    
    
    case messages <- msg:
        fmt.Println("sent message",msg)
    //case val := <- messages:
    //  	fmt.Println("received message",val)
    default :
      	fmt.Println("no message sent")
    }
}

//no message sent

3. Closing of the channel

After closing a channel, data can no longer be transmitted to this channel.

Closing a channel can be used to transmit information that work has been completed to the receiver of the channel.

func main(){
    
    
    jobs := make(chan int,5)
    done := make(chan bool)

    //发送数据
    for j:=1;j<=3;j++{
    
    
       jobs <- j
       fmt.Println("sent job",j)
    }
    close(jobs)
    fmt.Println("sent all jobs")
    
    //接收数据
    go func(){
    
    
        time.Sleep(time.Second * 1)
        for {
    
    
            j,more := <-jobs
            if more{
    
    
                fmt.Println("received job",j)
            }else{
    
    
                fmt.Println("received all jobs")
                done <- true
                return
            }
        }
    }()
    
    //通道同步的方法等待任务结束
    <-done
}

We'll use a jobschannel to communicate main()the end of task execution in a goroutine to a worker goroutine. closeWe channel this when we have no redundant tasks for this worker goroutine jobs.

Receive data from using j, more := <- jobsa loop . jobsOf the values ​​received in this particular binary form, if jobshas been closed and all values ​​in the channel have been received, then morethe value of will be false. doneWe will use this feature to be notified via the channel when we have completed all tasks .

4. Channel traversal

From the channel closure, it can be seen that after the channel is closed, the values ​​in the channel can still be traversed.

A non-empty channel can be closed, but the remaining values ​​in the channel can still be received.

func main(){
    
    
    queue := make(chan string,2)
    queue <- "on"
    queue <- "sky"
    close(queue)

    for elem := range queue{
    
    
        fmt.Println(elem)
    }
}

To for...range...traverse the channel usage, you only need to define a variable to store the value.

Guess you like

Origin blog.csdn.net/weixin_46435420/article/details/119698590