package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for v := range c {
fmt.Println("out:", time.Now())
fmt.Println(v)
}
}
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i :=0; i < n; i++ {
c <- x
fmt.Println("in:",time.Now())
time.Sleep(100)
x, y = y, x+y
}
close(c)
}
2180Go 并发
更好的展示边入边出概念:
2179Go 并发
我们单独写一个 say2 函数来跑 goroutine,并且 Sleep 时间设置长一点,150 毫秒,看看会发生什么:
输出结果:
问题来了,say2 只执行了 3 次,而不是设想的 5 次,为什么呢?
原来,在 goroutine 还没来得及跑完 5 次的时候,主函数已经退出了。
我们要想办法阻止主函数的结束,要等待 goroutine 执行完成之后,再退出主函数:
我们引入一个信道,默认的,信道的存消息和取消息都是阻塞的,在 goroutine 中执行完成后给信道一个值 0,则主函数会一直等待信道中的值,一旦信道有值,主函数才会结束。
2178Go 并发
goroutine 是 golang 中在语言级别实现的轻量级线程,仅仅利用 go 就能立刻起一个新线程。多线程会引入线程之间的同步问题,在 golang 中可以使用 channel 作为同步的工具。
通过 channel 可以实现两个 goroutine 之间的通信。
创建一个 channel, make(chan TYPE {, NUM}) TYPE 指的是 channel 中传输的数据类型,第二个参数是可选的,指的是 channel 的容量大小。
向 channel 传入数据, CHAN <- DATA , CHAN 指的是目的 channel 即收集数据的一方, DATA 则是要传的数据。
从 channel 读取数据, DATA := <-CHAN ,和向 channel 传入数据相反,在数据输送箭头的右侧的是 channel,形象地展现了数据从隧道流出到变量里。
2177Go 错误处理
个人多次试验,总结几点 panic,defer 和 recover。
代码执行的结果:
2176Go 错误处理
fmt.Println 打印结构体的时候,会把其中的 error 的返回的信息打印出来。
结果: