channel
go中的channel是一种内置的复杂数据类型,和map、slice相似。它是一种队列结构,遵循FIFO(先进先出)原则。它主要应用于goroutine之间的通信。
向channel中存储数据
// 声明一个名为ch的chan,ch中存储的数据类型是string
var ch chan string
// 初始化ch
ch = make(chan string)
// 将"hello world"存入ch
ch <-"hello world"
将channel中的数据取出
// 将ch中的数据取出并赋值给x
x := <- ch
tip
- channel必须初始化后才能使用。
- 在使用make()进行初始化时,可以指定初始容量,也可以不指定,当不指定初始容量时,需要先有接收者(receiver)才能向ch中存储数据,否则会报错(goroutine死锁)。
- 当ch中的数据全部被取出时,再取的话会返回对应数据类型的零值。
- 可以通过v, ok := <-ch来取出ch中的数据,如果有数据,则将数据赋值给v,ok为true,否则v为对应数据类型的零值,ok为false,以此来判断ch中的数据是否被取完了。
只写channel
var ch chan<- string
表示ch是一个只写channel,即只能向ch中存储数据,不能从ch中取出数据。
只读channel
var ch <-chan string
表示ch是一个只读channel,即只能从ch中读取数据,不能向ch中存储数据。
select
适用于对多个channel做处理
var (
ch chan string
wg sync.WaitGroup
)
func main() {
ch = make(chan string, 1)
wg.Add(2)
go slt()
// 消耗一点时间,方便看出效果
for i := 0; i < 1000000; i++ {
}
go sender()
wg.Wait()
}
// 发送者
func sender() {
ch <- "hello"
ch <- "world"
wg.Done()
}
// select
func slt() {
loop:
for {
select {
// 可从ch中读出数据
case <-ch:
{
fmt.Println("接收到ch中的数据,跳出循环")
wg.Done()
break loop
}
// 所有case都不通的话就走default
default:
fmt.Println("未接收到ch中的数据,继续循环")
}
}
}
end
文章仅做个人学习交流,也许并不完全正确,欢迎指正;