初次学习go chan思路整理过程,当然也不免会碰到些低级错误
代码
package main
import "fmt"
func main() {
ch := make(chan int)
ch <- 20
ch <- 21
value := <-ch
fmt.Printf("%s\n",value)
value = <-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 main
import "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 = <-ch1
fmt.Printf("%d\n",value)
}
运行结果:
20
21
疑问:两个协程是怎么样配合的呢?
我稍改造代码试了一下,上代码:
package main
import (
"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 = <-ch1
fmt.Printf("%d\n",value)
}
运行结果:
inner helloChan position 1
20
other code 2
间隔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)
}
运行结果:
worker1 :1
worker2 :1
worker1 :2
worker1 :3
worker2 :2
worker1 :4