持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 17 天,点击查看活动详情
当chan传输完成的时候,要及时关闭chan,注意有发送方和接收方,即生产者和消费者。
在生产端关闭!消费端不要关闭chan。而是用 v,ok := <-ch 读取chan。对已关闭的chan。
- 读:不断返回该chan类型的零值,int为0,string为"",结构体的零值为空结构体,布尔类型,零值是 false,指针的零值为nil、零值是nil的还有:error, map, chan, slice, interface{}
- 写:panic
- 再次关闭:panic
package groutine
import (
"fmt"
"testing"
"time"
)
func service() string { // 快
time.Sleep(time.Millisecond*50)
return "Done"
}
func otherTask() { // 慢
fmt.Println("working on something else")
time.Sleep(time.Millisecond*100)
fmt.Println("Task is Done.")
}
func AsyncService() chan string {
retCh := make(chan string)
go func() {
ret := service() // Done
fmt.Println("returned result.")
retCh <- ret // 一直阻塞,直到Done传入这里面。
// 这个channel的作用就是一直阻塞,直到service执行完。
fmt.Println("service exited.")
// 主进程一直在阻塞,所以这里是最后才执行
}()
return retCh
}
func TestChan(t *testing.T) {
retCh := AsyncService() // 执行一个异步的操作。异步返回结果。
otherTask() // 而由于AsyncService()函数中,并没有阻塞所以先会执行其他任务。
fmt.Println(<-retCh) // 一直阻塞,直到从retCh中读出信息,即service()函数执行完毕。
}
虽然otherTask后执行,但是先输出,就是chan起到了阻塞的作用。
- 无缓冲 result make(chan string) result
working on something else
returned result.
Task is Done.
Done
service exited.
无缓冲,AsyncService阻塞,直到最后才service执行完之后才结束。比主进程后执行完成。
- 有缓冲 result make(chan string,1) result
working on something else
returned result.
service exited.
Task is Done.
Done
有缓冲的状态下,这个AsyncService不会阻塞。 这个异步任务也就马上结束并返回。 比主进程先执行完成。
此外chan可以作为多渠道的选择
select {
case ret := <- retCh1:
t.Logf("result: %s",ret)
case ret := <- retCh2:
t.Logf("result: %s",ret)
default:
t.Error("Nothing Return")
}
超时的控制
select {
case ret := <- retCh1:
t.Logf("result: %s",ret)
case <-time.After(time.Second*1):
t.Error("Time Out")
}
当这个函数超过这个时间,之后便会返回错误