初次学习go chan思路整理过程,当然也不免会碰到些低级错误
代码
package mainimport "fmt"func main() {
ch := make(chan int) ch <- 20
ch <- 21 value := <-ch
fmt.Printf("%s\n",value) value = https://www.it610.com/article/<-ch
fmt.Printf("%s\n",value)
}
运行结果
fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan send]:
main.main()
/Users/arno/go/src/go_study/goroutine/channel/channel1.go:9 +0x59
解释 chan是协程之间的数据传输的通道,但是这里只有一个主协程(main函数),所以会出现上面的错误。
说到协程这里也简单说明一下:
协程比线程更轻量级。协程也是宿主在线程中,一个线程可以包含多个协程。协程是非抢占式的,协程的所有权是主动交出的,所以它在切换时只需要记录点,而不会像线程那样要快照很多数据。
解决思路 加个协程试试,看代码
package mainimport "fmt"var ch1 chan int
func HelloChan(){
ch1 <- 20
ch1 <- 21
}func main() {
ch1 = make(chan int) go HelloChan() value := <-ch1
fmt.Printf("%d\n",value) value = https://www.it610.com/article/<-ch1
fmt.Printf("%d\n",value)
}
运行结果:
20
21
疑问:两个协程是怎么样配合的呢?
我稍改造代码试了一下,上代码:
package mainimport (
"fmt"
"time"
)var ch1 chan int
func HelloChan(){
ch1 <- 20
fmt.Println("inner helloChan position 1")
time.Sleep(time.Second*2)
fmt.Println("间隔2秒后输出 :\n")
fmt.Println("inner helloChan position 2")
ch1 <- 21
fmt.Println("inner helloChan position 3")
}func main() {
ch1 = make(chan int) go HelloChan() value := <-ch1
fmt.Printf("%d\n",value) a:=0
a++
a++
fmt.Println("other code ",a) value = https://www.it610.com/article/<-ch1
fmt.Printf("%d\n",value)
}
运行结果:
inner helloChan position 1
20
other code2
间隔2秒后输出 :inner helloChan position 2
inner helloChan position 3
21
根据结果分析运行流程:
文章图片
总结: 通篇说明了两个关键点:
1、chan是两个协程间通讯的,否则会报错,所以要注意某协程会提前结束导致报错
2、当协程读取chan时一定要读取到的,否则会被阻塞在这里
3、当协程向chan写入数据时,要等待被其它线程读取,否则也会阻塞。(关于这点我未加在上面的代码中,但我自己是实验过的,为了示例的简洁性,没加那么多复杂的逻辑进来)
篇外: 当有chan的交互时协程被阻塞,但是没有chan交互时协程间是相互不受影响的,来看一下代码:
package main
import (
"fmt"
"time"
)func worker1(){
time.Sleep(time.Second*1)
fmt.Println("worker1 :1 \n")
time.Sleep(time.Second*1)
fmt.Println("worker1 :2 \n")
time.Sleep(time.Second*1)
fmt.Println("worker1 :3 \n")
time.Sleep(time.Second*1)
fmt.Println("worker1 :4 \n")
}func worker2(){
time.Sleep(time.Second*2)
fmt.Println("worker2 :1 \n")
time.Sleep(time.Second*2)
fmt.Println("worker2 :2 \n")
}func main() {
go worker1()
go worker2() time.Sleep(5*time.Second)
}
【GO chan思绪整理(非缓冲chan)】运行结果:
worker1 :1
worker2 :1
worker1 :2
worker1 :3
worker2 :2
worker1 :4
推荐阅读
- 【golang】leetcode中级-字母异位词分组&无重复字符的最长子串
- 彻底理解Golang Map
- kratos线上开源年会它来啦~
- 深入浅出 Golang 资源嵌入方案(go-bindata篇)
- 深入浅出 Golang 资源嵌入方案(前篇)
- golang 经典案例总结
- Go实战 | 基于有向无环图的并发执行流的实现
- Golang 数组和切片
- Go JSON编码与解码()
- golang map基础知识