您的位置 首页 golang

Golang channel

golang channel 分为有缓冲与无缓冲两种类型,最大的区别是阻塞问题。

c1:=make(chan int) 无缓冲,channel在读和写是都会阻塞

c2:=make(chan int,10) 有缓冲

Go Channel的基本操作语法如下:

c := make(chan bool) //创建一个无缓冲的bool型Channel

c <- x //向一个Channel发送一个值

<- c //从一个Channel中接收一个值

x = <- c //从Channel c接收一个值并将其存储到x中

x, ok = <- c //从Channel接收一个值,如果channel关闭了或没有数据,那么ok将被置为false

不带缓冲的Channel兼具通信和同步两种特性,颇受青睐。

close():

close主要用来关闭channel通道其用法为close(channel),并且只在生产者的地方关闭channel,而不是在消费者的地方关闭.并且关闭channel后,便不可再向channel中继续存入数据,但是可以继续从channel中读取数据.从一个已关闭的channel中读数据,不会panic,会读到channel对应类型的0值,比如int为0, bool 就为false,但是这样无法确定读取到的是否是正确的数据,所以一般会使用channel返回的第二个可选参数来判断channel是否关闭。

chan <- struct {}{} (常用)

语义为将一个空数据传递给channel.因为struct{}{}占用的内存非常小,而且我们对数据内容也不关心,通常用来做信号量来处理.

for循环读取channel:

for i := range ch { // ch关闭时,for循环会自动结束

println(i)

}

范例1:等待一个事件,通过close一个Channel实现

import “fmt”

func main() {

fmt.Println(“Begin doing something!”)

c := make(chan bool)

go func() {

fmt.Println(“Doing something…”)

close(c) //换成 c <-true 更好理解

}()

<-c //栅栏,等同读到false

fmt.Println(“Done!”)

}

这里main goroutine通过”<-c”来等待sub goroutine中的“完成事件”,sub goroutine通过close channel促发这一事件。

结果:

Begin doing something!

Doing something…

Done!

范例2:close channel还可以用于协同多个Goroutines

import “fmt”

func worker(start chan bool, index int) {

<-start

fmt.Println(“This is Worker:”, index)

}

func main() {

start := make(chan bool)

for i := 1; i <= 100; i++ {

go worker(start, i)

}

close(start)

select {} //deadlock we expected

}

select:

要从多个channel读取数据,需要配合select关键词使用。

在go中使用select – case 可以在多个channel上监听读写事件,某个case产生了读写事件时,则执行相应case中的代码。

select{

case :

/*…*/

default:

/*…*/

}

如果有default case的话,其他case没收到消息的话,会马上走default case,然后整个select语句结束.

范例3:

import (

“fmt”

“time”

)

func main() {

c := make(chan int)

o := make(chan bool)

go func() {

for {

select {

case i := <-c:

fmt.Println(i)

case <-time.After(time.Duration(3) * time.Second): //设置超时时间为3s,如果channel 3s钟没有响应,一直阻塞,则报告超时,进行超时处理.

fmt.Println(“timeout”)

o <- true

break

}

}

}()

<-o

}

结果:

timeout

for … select

LOOP:

for{

select{

case ….:

break LOOP //@A 跳到标志位

}

}

注意上面@A的地方

两个重要的使用方式:

1、超时机制Timeout

带超时机制的select是常规的tip,下面是示例代码,实现30s的超时select:

func worker(start chan bool) {

timeout := time.After(30 * time.Second) //说明time.After()的返回值是一个 chan 类型。

for {

select {

// … do some stuff

case <- timeout:

return

}

}

}

2、心跳HeartBeart

与timeout实现类似,下面是一个简单的心跳select实现:

func worker(start chan bool) {

heartbeat := time.Tick(30 * time.Second)

for {

select {

// … do some stuff

case <- heartbeat:

//… do heartbeat stuff

}

}

}

技术关键字推荐:golang 编程 技术 channel time

文章来源:智云一二三科技

文章标题:Golang channel

文章地址:https://www.zhihuclub.com/97128.shtml

关于作者: 智云科技

热门文章

网站地图