Channels 通道 - Go 学习记录
Go Channels
基本语法和需要注意的点
- 语法定义
var channel chan [type]
- 使用
<-
传递数据 chan <- data
发送数据到通道,向通道中写数据data <- chan
获取通道中的数据,从通道中读取数据
- 使用
- 注意的点
- 它是用于
goroutine
之间进行传递消息的 - 每个
channel
都有相关联的数据类型,nil chan
不能使用 channel
是在goroutine
之间链接,数据接收和发送必须处于不同的goroutine
中- 非缓冲通道发送数据和读取数据都是阻塞的,直到另一条
goroutine
执行读取或写完数据才会解除阻塞 channel
是同步的,就意味着同一时间,只能有一条goroutine
来操作- 不要忘记
close(channel)
关闭通道
- 它是用于
代码实现:
package main
import (
"fmt"
"strconv"
)
func main() {
// 创建通道
var channel chan int
fmt.Printf("%T,%v\n", channel, channel) // chan int,<nil>
channel = make(chan int)
fmt.Printf("%T,%v\n", channel, channel) // chan int,0xc00008c060
// 通道内写入数据
go setData(channel)
// 读取通道内的数据
for v := range channel {
fmt.Println("读取的数据: ", v) // 读取的数据:0,1,2,3,4
}
// 非缓冲通道
var ch1 chan int
ch1 = make(chan int)
go func() {
for i := 0; i < 5; i++ {
fmt.Println("子的 goroutine 中,i", i) // 子的 goroutine 中,i 0,1,2,3,4
}
// 循环结束后向通道中写数据,表示结束了。
ch1 <- 1
fmt.Println("结束")
}()
data := <-ch1
fmt.Println("main data --> ", data)
/**
缓冲通道(固定大小)
接收:缓冲区数据空了会阻塞
写入:缓冲区数据满了会阻塞
*/
ch2 := make(chan int, 3)
fmt.Println(len(ch2), cap(ch2)) // 0 ,3
ch2 <- 1
ch2 <- 2
ch2 <- 3
fmt.Println(len(ch2), cap(ch2)) // 3,3
// 缓冲区满了,如果需要继续写入数据,需要有其他的 goroutine 进行读取(队列的结构来读取)
// ch2 <- 4
ch3 := make(chan string, 3)
fmt.Println(len(ch3), cap(ch3)) // 0 ,3
go setStringData(ch3, 3)
for {
v, ok := <-ch3
if !ok {
fmt.Println("读取完毕", ok) // 读取完毕 false
break
}
fmt.Println("读取的数据是:", v) // 读取的数据是: 0,1,2
}
/**
双向通道
chan ch
chan <- data 写入数据
data <- chan 读取数据
*/
ch4 := make(chan string)
isDone := make(chan bool)
go SendString(ch4, isDone)
data1 := <-ch4 // 读取
fmt.Println(data1) // golang
ch4 <- "learn golang" // 发送
<-isDone // 判断这个来看主程序结束
/**
单向通道:定向
chan <- Write 只支持写
<- chan Read 只能读
*/
singleChanWrite := make(chan<- int) // 只能写,不能读
singleChanRead := make(<-chan int) // 只能读,不能写
fmt.Println("main over")
}
func setData(ch chan int) {
for i := 0; i < 5; i++ {
ch <- i
}
close(ch) // 通知对方,通道关闭
}
func setStringData(ch chan string, number int) {
for i := 0; i < number; i++ {
ch <- strconv.Itoa(i)
}
close(ch) // 通知对方,通道关闭
}
func SendString(ch chan string, isDone chan bool) {
ch <- "golang" // 发送
data2 := <-ch // 读取数据
fmt.Println("main goroutine 传来: ", data2) // main goroutine 传来: learn golang
isDone <- true // 限制主程序过快的结束执行
}
*/
如想看学习记录同步的练习代码移步 GitHub
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: