单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。
虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态问题。为了保证数据交换的正确性,必须使用互斥量对内存进行加锁,这种做法势必造成性能问题。
Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而
不是通过共享内存而实现通信。如果说goroutine是Go程序并发的执行体,channel就是它们之间的连接。channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制。
Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出
(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也
就是声明channel的时候需要为其指定元素类型。
- package main
-
- import "fmt"
-
- // 类似于pipe[]管道
- func main() {
- //ch := make(chan int, 10) //有缓冲大小的管道
- //ch <- 12
- //var x int
- //x = <-ch
- //fmt.Println(x)
- //c := make(chan int) //开辟的空间 cap是3,长度
- //
- //go func() {
- // defer println("go 程关闭")
- // fmt.Println("go 程运行正在向chan写入数据")
- // c <- 666 //由于是无缓冲的,所以必须得立刻接收,不然一直阻塞
- //}()
- //num := <-c
- //fmt.Println("主程序接受管道 值为:", (num))
- //fmt.Println(len(c), cap(c))
-
- //ch := make(chan int)
- //go func() {
- // defer close(ch) //延迟关闭通道
- // for i := 0; i < 5; i++ {
- // ch <- i
- // }
- //}()
- //for {
- // if data, ok := <-ch; ok {
- // fmt.Println(data)
- // } else {
- // break
- // }
- //}
-
- /*
- c := make(chan int)
- go func() {
- for i := 0; i < 5; i++ {
- c <- i
- time.Sleep(1 * time.Second)
- }
- close(c)
- }()
- //迭代,会自动阻塞
- for data := range c {
- fmt.Println(data)
- }*/
-
- // select 多路复用
- c := make(chan int)
- quit := make(chan int)
-
- go func() {
- for i := 0; i < 5; i++ {
- fmt.Println(<-c)
- }
- quit <- 0
- }()
- fibonace(c, quit)
-
- }
-
- func fibonace(c, quit chan int) {
- x, y := 1, 1
- for {
- select {
- case c <- x: //如果c可写 ,x就会进来
- x, y = y, x+y
- case <-quit:
- fmt.Println("quit")
- return
- }
-
- }
- }