上一篇: [1438938175118]
ToC
- Go 边看边练 -《Go 学习笔记》系列(一)- 变量、常量
- Go 边看边练 -《Go 学习笔记》系列(二)- 类型、字符串
- Go 边看边练 -《Go 学习笔记》系列(三)- 指针
- Go 边看边练 -《Go 学习笔记》系列(四)- 控制流 1
- Go 边看边练 -《Go 学习笔记》系列(五)- 控制流 2
- Go 边看边练 -《Go 学习笔记》系列(六)- 函数
- Go 边看边练 -《Go 学习笔记》系列(七)- 错误处理
- Go 边看边练 -《Go 学习笔记》系列(八)- 数组、切片
- Go 边看边练 -《Go 学习笔记》系列(九)- Map、结构体
- Go 边看边练 -《Go 学习笔记》系列(十)- 方法
- Go 边看边练 -《Go 学习笔记》系列(十一)- 表达式
- Go 边看边练 -《Go 学习笔记》系列(十二)- 接口
- Go 边看边练 -《Go 学习笔记》系列(十三)- Goroutine
- Go 边看边练 -《Go 学习笔记》系列(十四)- Channel
7.2.1 单向
可以将 channel
隐式转换为单向队列,只收或只发。
1c := make(chan int, 3)
2var send chan<- int = c // send-only
3var recv <-chan int = c // receive-only
4send <- 1
5// <-send // Error: receive from send-only type chan<- int
6<-recv
7// recv <- 2 // Error: send to receive-only type <-chan int
不能将单向 channel
转换为普通 channel
。
1d := (chan int)(send) // Error: cannot convert type chan<- int to type chan int
2d := (chan int)(recv) // Error: cannot convert type <-chan int to type chan int
7.2.2 选择
如果需要同时处理多个 channel
,可使用 select
语句。它随机选择一个可用 channel
做收发操作,或执行 default case
。
在循环中使用 select default case
需要小心,避免形成洪水。
7.2.3 模式
用简单工厂模式打包并发任务和 channel
。
1func NewTest() chan int {
2 c := make(chan int)
3 rand.Seed(time.Now().UnixNano())
4
5 go func() {
6 time.Sleep(time.Second)
7 c <- rand.Int()
8 }()
9
10 return c
11}
12
13func main() {
14 t := NewTest()
15 println(<-t) // 等待 goroutine 结束返回。
16}
用 channel
实现信号量 (semaphore)。
用 closed channel
发出退出通知。
用 select
实现超时 (timeout)。
1func main() {
2 w := make(chan bool)
3 c := make(chan int, 2)
4
5 go func() {
6 select {
7 case v := <-c: fmt.Println(v)
8 case <-time.After(time.Second * 3): fmt.Println("timeout.")
9 }
10
11 w <- true
12 }()
13
14 // c <- 1 // 注释掉,引发 timeout。
15 <-w
16}
channel
是第一类对象,可传参 (内部实现为指针) 或者作为结构成员。
1type Request struct {
2 data []int
3 ret chan int
4}
5
6func NewRequest(data ...int) *Request {
7 return &Request{ data, make(chan int, 1) }
8}
9
10func Process(req *Request) {
11 x := 0
12 for _, i := range req.data {
13 x += i
14 }
15
16 req.ret <- x
17}
18
19func main() {
20 req := NewRequest(10, 20, 30)
21 Process(req)
22 fmt.Println(<-req.ret)
23}
全系列完
- 本系列是基于雨痕的《Go 学习笔记》(第四版)整理汇编而成,非常感谢雨痕的辛勤付出与分享!
- 转载请注明:文章转载自:黑客与画家的社区 [http://symphony.b3log.org]
- 如果你觉得本章节做得不错,请在下面打赏一下吧~
社区小贴士
- 关注标签 [golang] 可以方便查看 Go 相关帖子
- 关注标签 [Go 学习笔记] 可以方便查看本系列
- 关注作者后如有新帖将会收到通知
该文章同步自 黑客派