1. 程式人生 > >go語言通道

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 //程式一直可以執行到這一行,而另一個協程準備好了往通道里寫入了資料,所以即使通道無快取,也可以正常執行。
}

因為另一個協程已經準備好了往通道里寫入資料,所以通道無快取也不會阻塞。