go语言通道

注意:通道首先要通过make函数来初始化,初始化之后才可以执行写入和读取操作。此外还分为【有缓存通道】和【无缓存通道】,make函数第二个参数大于1,表示有缓存;make函数的第二个参数的类型为整型,在使用make函数初始化通道时,缓存必须大于1。不可以是0。

首先看一下通道在一个协程中的例子

发送操作阻塞

package main

func main() {
	var ch chan struct{}
	//ch = make(chan struct{}, 1)
	ch <- struct{}{}
	<-ch
}

运行结果

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send (nil chan)]:
main.main()

发送(写入)操作阻塞,此外通道没有初始化,nil chan表示通道没有初始化。

接收操作阻塞

package main

func main() {
	var ch chan struct{}
	ch = make(chan struct{}, 1)
	<-ch //程序到这一行直接阻塞,即使有缓存也不行,因为通道为空,读不到数据。
	ch <- struct{}{}
}

运行结果

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()

读取(接收)操作阻塞,即使有缓存也会继续阻塞,因为通道为空,读取不到数据,后面的代码不会执行了。

编译通过

package main

func main() {
	var ch chan struct{}
	ch = make(chan struct{}, 1)
	ch <- struct{}{}
	<-ch
}

因为有缓存,所以可以往通道里写入数据,即使把最后一行注释掉,程序也可以正常运行,不会阻塞。

分别在两个协程中进行读取(接收)和写入(发送),一边读取,一边写入

读取写入均阻塞

package main

func main() {
	var ch chan struct{}
	go func() {
		ch <- struct{}{}
	}()
	<-ch
}

运行结果

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive (nil chan)]:
main.main()

goroutine 4 [chan send (nil chan)]:
main.main.func1(0x0)
created by main.main

虽然程序可以一直执行到最后一行,但是因为通道没有初始化,所以两边都阻塞。

接收操作阻塞

package main

func main() {
	var ch chan struct{}
	ch = make(chan struct{})
	<-ch
	go func() {
		ch <- struct{}{}
	}()
}

运行结果

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()

主函数接收操作首先阻塞,后面的代码不会执行了,即使通道有缓存也会阻塞,因为通道为空,读取不到数据。

发送和接收均阻塞

package main

func main() {
	var ch chan struct{}
	go func() {
		<-ch
	}()
	ch <- struct{}{} //程序一直可以执行到这一行,但是通道没有初始化,所以两边都阻塞。
}

运行结果

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send (nil chan)]:
main.main()

goroutine 17 [chan receive (nil chan)]:
main.main.func1(0x0)
created by main.main

虽然程序一直可以执行到最后一行,但是因为通道没有初始化,所以两边都阻塞,这个例子是主函数里边写入,子协程里边读取,与上一个两边均阻塞的正好反过来。

发送操作阻塞

package main

func main() {
	var ch chan struct{}
	ch = make(chan struct{})
	ch <- struct{}{} //函数执行到这一行直接阻塞,不管有无缓存,都会阻塞
	go func() {
		<-ch
	}()
}

运行结果

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()

主函数发送(写入)操作先阻塞了,后面的代码不会执行了,不管通道有无缓存,程序都已经阻塞不会再继续往下执行了。

另一个协程准备好了接收数据

package main

func main() {
	var ch chan struct{}
	ch = make(chan struct{})
	go func() {
		<-ch
	}()
	ch <- struct{}{} //因为另一个协程已经准备好了接收,所以通道无缓存,程序也可以运行
}

因为另一个协程准备好了读取数据,所以即使通道无缓存也可以正常运行。

另一个协程往通道中写入了数据

package main

func main() {
	var ch chan struct{}
	ch = make(chan struct{})
	go func() {
		ch <- struct{}{}
	}()
	<-ch //程序一直可以执行到这一行,而另一个协程准备好了往通道里写入了数据,所以即使通道无缓存,也可以正常运行。
}

因为另一个协程已经准备好了往通道里写入数据,所以通道无缓存也不会阻塞。

猜你喜欢

转载自blog.csdn.net/Charliewolf/article/details/84961182