Go语言通道

一.基础内容

        1.声明通道的两种方式

1.变量方式

var ch chan int //声明一个存放int类型数据的通道

通过这种方式声明的通道,值为nil.

2.使用内置函数make

ch1 := make(chan int) //声明一个无缓冲的通道

ch2 := make(chan int , 5) //声明一个带有缓冲的通道

2.管道的数据读写

        

ch := make(chan int , 5)
//向通道内写数据
ch <- 10
//从通道中读数据
a := <- ch

管道默认是双向读写的,但是可以声明单向通道,设置为只读或者只写

func main() {
	ch := make(chan int, 5)
	//写入数据
	onlyWrite(ch)
	//读数据
	onlyRead(ch)
}

// 只能写数据的通道
func onlyWrite(write chan<- int) {
	write <- 1
	write <- 2
}

// 只能读数据的通道
func onlyRead(read <-chan int) {
	a := <-read
	b := <-read
	fmt.Println(a, b) //1 2
}

注意事项:

        1.管道如果没有缓冲区,向管道写入数据会造成阻塞,直到有协程从管道内读数据.同理,从没有缓冲区的管道读数据也会造成阻塞,直到有协程向管道内写数据.从这个特性来看无缓冲通道,也可以被称为同步通道.

        

func main() {
	ch := make(chan int)
	//开启协程 , 从管道内读数据
	go read(ch) //协程会被阻塞,直到向管道内写数据
	//向管道写数据
	ch <- 1
}

func read(ch chan int) {
	fmt.Println("开始读取数据")
	a := <-ch
	fmt.Println(a)
}

        2.管道如果有缓冲区,但是没有数据,从管道读数据也会造成阻塞.如果缓冲区已满,向管道写数据同样会造成阻塞.

        3.对于值为nil的通道,无论是读写都会造成阻塞,而且是永久阻塞

//两个协程无法结束,永久阻塞
var sg sync.WaitGroup

func main() {
	var ch chan int
	sg.Add(2)
	go write(ch)
	go read(ch)
	sg.Wait()
	fmt.Println("结束")
}

func write(ch chan int) {
	fmt.Println("写数据")
	ch <- 1
	fmt.Println("写数据结束")
}

func read(ch chan int) {
	fmt.Println("开始读取数据")
	a := <-ch
	fmt.Println(a)
}

        4.对于一个已经被关闭,但是还有数据的通道,是可以读取数据的.但是不能向被关闭的通道写数据.

        

二. 原理

        1.环形队列

        2.等待队列

                2.2.1 等待读队列(recvq).

从管道内读取数据时,如果管道没有缓冲区,或者缓冲区为空,当前协程会被加入到等待读队列.

                2.2.2 等待写队列(sendq)

向管道内写数据时,如果管道缓冲区已满,则将当前协程加入到等待写队列.进入睡眠并等待被读协程唤醒.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值