美文网首页
Go channel-1

Go channel-1

作者: 来到了没有知识的荒原 | 来源:发表于2020-07-18 17:37 被阅读0次

不要以共享内存的方式去通信,而是以通信的方式共享内存

  • sync
  • 鼓励使用channel

channel的声明

var 通道名 chan 数据类型
通道名 = make(chan 数据类型)
package main

import "fmt"

func main() {
    var a chan int
    fmt.Printf("%T,%v\n",a,a)
}

初始化后是nil

channel

data := <-a  //read from channel a
a <- data // write to channel a

阻塞

发送数据:chan<-data,阻塞的,直到另一条goroutine,读取数据来解除阻塞
读取数据:data<-chan,也是阻塞的。直到另一条goroutine,写出数据解除阻塞。

channel本身就是同步的,意味着在同一时间只能有一个goroutine使用同一个channel

如果只有读channel会报错deadlock死锁

package main

import (
    "fmt"
)

func main() {
    var ch1 chan bool
    ch1=make(chan bool)

    go func(){
        for i:=0;i<10;i++{
            fmt.Println("goroutine..",i)
        }
        ch1<-true
        fmt.Println("goroutine...over...")
    }()

    // 没有写入ch1的时候,读ch1的操作是阻塞的
    data:= <-ch1
    fmt.Println("main...data:",data)
    fmt.Println("main...over...")
}

close

close(ch)关闭channel后,可以用v,ok := <-ch的ok是否为false来判断是否已经读取完毕了,前提是,写的一方一定要close掉channel

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go sendData(ch)
    for {
        time.Sleep(1 * time.Second)
        v, ok := <-ch

        if !ok {
            fmt.Println("已经读取完毕...", ok)
            break
        }
        fmt.Println("读入...", v, ok)
    }
}

func sendData(ch chan int) {
    for i := 0; i < 10; i++ {
        fmt.Println("写入...", i)
        ch <- i
    }
    close(ch)
}

结果有个很有趣的现象:应该是读入完才能写入,应该阻塞在写入的,为什么会出现两次写入?

因为fmt.Println("写入...", 1)后,ch<-1执行
到了下一个for,执行了fmt.Println("写入...", 2),阻塞是阻塞在ch<-2
所以打印出来了不代表真就写进channel了

for range的写法

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int)
    go sendData(ch)
    for v:=range(ch){
        fmt.Println("读入",v)
    }
    fmt.Println("main...over...")
}

func sendData(ch chan int) {
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
}

相关文章

网友评论

      本文标题:Go channel-1

      本文链接:https://www.haomeiwen.com/subject/rdsfkktx.html