Channel
目录
channel
channel 是Go语言中用于Goroutine之间通信的工具,它相当于一个管道,有往channel里发送数据的发送方,也有从channel里读取数据的
消费方。发送和消费channel中的数据都是使用 <-
这个符号,但是它的位置放在左边还是右边就代表着不同的意思,箭头指向谁,数据
就往那个方向流动:
v := <-myChan
就说明数据是从myChan
里读取出来,流动到v
这个变量里myChan <- v
则说明数据是从v流动到myChan
里
初始化channel要使用 make
关键字,例如:
package main
import (
"fmt"
"time"
)
func main() {
x := make(chan int)
go func() {
fmt.Println(<-x)
}()
time.Sleep(time.Second * time.Duration(1))
x <- 1
time.Sleep(time.Second * time.Duration(1))
}
channel
有三种形式,双向、只读、只写:
package main
import (
"fmt"
)
func main() {
x := make(chan int)
y := make(chan<- int)
z := make(<-chan int)
fmt.Printf("%T, %T, %T\n", x, y, z)
}
注意上面的例子里,make(chan<- int)
创建出来的channel只能写入数据,make(<-chan int)
创建出来的channel只能读取数据,他们都是
单向channel。
select
读取channel中的数据是会被阻塞住的,那么我们要怎么才能实现如果channel中没有数据就继续执行呢?答案是使用 select
:
package main
import (
"fmt"
"time"
)
func main() {
x := make(chan int)
go func() {
// 这里要睡10s,但是主Goroutine没有睡10s,因此这里是执行不到的,从而主Goroutine会在select里跳到default里
time.Sleep(time.Second * time.Duration(10))
x <- 1
}()
select {
case i := <-x:
fmt.Printf("从x中接收到%d\n", i)
default:
fmt.Printf("其他分支都阻塞了,所以轮到我执行\n")
}
fmt.Println("退出")
}
select
语句在形式上与 switch...case...
是一样的,不过 select
用于从多个阻塞的 goroutine
里监听,哪个分支
最先唤醒,就执行那个分支,当然,也有 default
分支,用于当所有 case
都阻塞时,跳过这个 select
。
更多文章
本站热门
- socks5 协议详解
- zerotier简明教程
- 搞定面试中的系统设计题
- 用peewee代替SQLAlchemy
- frp 源码阅读与分析(一):流程和概念
- Golang(Go语言)中实现典型的fork调用
- DNSCrypt简明教程
- 一个Gunicorn worker数量引发的血案
- Golang validator使用教程
- Docker组件介绍(一):runc和containerd
- Docker组件介绍(二):shim, docker-init和docker-proxy
- 使用Go语言实现一个异步任务框架
- 协程(coroutine)简介 - 什么是协程?
- SQLAlchemy简明教程
- Go Module 简明教程