searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

GO语言学习笔记之Channel

2023-05-29 02:45:27
7
0

一、Channel是什么

        Channel是goroutine之间通信的管道,用于让一个goroutine发送特定值到另一个goroutine。

        在Go语言中Channel是一种特殊的类型,总是遵循先入先出的策略来保证传输数据的顺序。并且Channel 在多并发操作里是属于协程安全的。

二、Channel的使用

2.1、Channel类型

        Channel是一种引用类型,空值是nil。每一个Channel都是一个具体类型的管道,需要在生命是指定元素类型。声明一个管道的语句如下:

var 变量名 chan 元素类型

        例如:  

var ch1 chan int  //声明一个传递整型的管道
var ch2 chan string  //声明一个传递字符串的管道

2.2、Channel的创建

        通道声明后需要使用make()函数进行初始化。创建Channel的格式如下:

make(chan 元素类型,[缓冲大小])

        其中缓冲大小是可选参数,若传入该参数,则代表创建一个有缓冲的管道,不传则代表创建无缓冲的管道。例如:

ch2 := make(chan bool)  //创建一个无缓冲的布尔型管道
ch3 := make(chan []int , 3)  //创建一个有缓冲的int切片型管道

2.3、Channel的基本操作

        Channel有发送、接收和关闭三种操作。发送和接收都使用“<-”符号操作:    

ch := make(chan int)  //创建一个int管道
ch <- 10	  //将数字10放入管道
a := <- ch  //从管道中接收值并赋值给变量a
<- ch  //从管道中接收值并忽略

        当Channel不再使用之后可以使用close() 函数来关闭:

             

close(ch)

        要注意的是:

        1.向关闭的通道再发送值就会导致panic。

        2.对关闭的通道可以继续取值直到通道为空。

        3.对已经关闭的空通道取值会得到对应类型的零值。

        4.关闭一个已经关闭的通道会导致panic。

2.4、无缓冲的Channel

        向一个无缓存Channel发送数据将导致发送者goroutine阻塞,直到另一个goroutine在相同的channel上执行接收操作,在该条数据传输成功之后,两个goroutine可以继续执行后面的语句。同样的,如果接收数据的操作先发生,那么接收者goroutine也将阻塞,直到有另一个goroutine在相同的Channels上执行发送操作。例如:

        示例1:

     

func main() {
    		ch := make(chan int)
    		ch <- 10  //发送goroutine阻塞,直至其他goroutine将数据接收
    		fmt.Println("发送成功")
}

              示例2:

func recv(c chan int) {
    			ret := <-c
    			fmt.Println("接收成功", ret)
}

func main() {
    			ch := make(chan int)
    			go recv(ch)   // 启用goroutine接收值,该goroutine阻塞
    			ch <- 10    // 向管道中发送值,接收goroutine阻塞解除
    			fmt.Println("发送成功")
}

        使用无缓冲管道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也称为同步通道。

2.5、有缓冲的Channel

        有缓存的channel内部有一个元素队列。队列的最大容量是在调用make函数创建channel时通过第二个参数指定的。例如:

ch = make(chan string, 3)  // 创建一个可以缓存3个字符串的管道

        向有缓存channel执行发送操作就是向内部缓存队列的尾部插入元素,接收操作则是从队列的头部删除元素。如果内部缓存队列是满的,那么发送操作将阻塞直到另一个goroutine执行接收操作而释放了新的队列空间。同样,如果channel是空的,接收操作将阻塞直到有另一个goroutine执行发送操作而向队列插入元素。

        可以使用内置的len函数获取通道内元素的数量,使用cap函数获取通道的容量。

三、Channel的其他操作

3.1、判断Channel是否关闭

	if v, ok := <-ch; !ok {
 	fmt.Println("channel 已关闭,读取不到数据")
 	}

3.2、循环获取

for data := range ch {

  doSomething()

       }

3.3、select

              当与多个 goroutine 通信时,可以使用 select 来管理多个 channel 的通信数据:

           

for {
    select {
  		case <-ch1:
   			doSomething1()
  		case <-ch2:
   			doSomething2()
  		}
 }

作者:燕雨洁  部门:混合产品线

0条评论
作者已关闭评论
燕****洁
2文章数
0粉丝数
燕****洁
2 文章 | 0 粉丝
燕****洁
2文章数
0粉丝数
燕****洁
2 文章 | 0 粉丝
原创

GO语言学习笔记之Channel

2023-05-29 02:45:27
7
0

一、Channel是什么

        Channel是goroutine之间通信的管道,用于让一个goroutine发送特定值到另一个goroutine。

        在Go语言中Channel是一种特殊的类型,总是遵循先入先出的策略来保证传输数据的顺序。并且Channel 在多并发操作里是属于协程安全的。

二、Channel的使用

2.1、Channel类型

        Channel是一种引用类型,空值是nil。每一个Channel都是一个具体类型的管道,需要在生命是指定元素类型。声明一个管道的语句如下:

var 变量名 chan 元素类型

        例如:  

var ch1 chan int  //声明一个传递整型的管道
var ch2 chan string  //声明一个传递字符串的管道

2.2、Channel的创建

        通道声明后需要使用make()函数进行初始化。创建Channel的格式如下:

make(chan 元素类型,[缓冲大小])

        其中缓冲大小是可选参数,若传入该参数,则代表创建一个有缓冲的管道,不传则代表创建无缓冲的管道。例如:

ch2 := make(chan bool)  //创建一个无缓冲的布尔型管道
ch3 := make(chan []int , 3)  //创建一个有缓冲的int切片型管道

2.3、Channel的基本操作

        Channel有发送、接收和关闭三种操作。发送和接收都使用“<-”符号操作:    

ch := make(chan int)  //创建一个int管道
ch <- 10	  //将数字10放入管道
a := <- ch  //从管道中接收值并赋值给变量a
<- ch  //从管道中接收值并忽略

        当Channel不再使用之后可以使用close() 函数来关闭:

             

close(ch)

        要注意的是:

        1.向关闭的通道再发送值就会导致panic。

        2.对关闭的通道可以继续取值直到通道为空。

        3.对已经关闭的空通道取值会得到对应类型的零值。

        4.关闭一个已经关闭的通道会导致panic。

2.4、无缓冲的Channel

        向一个无缓存Channel发送数据将导致发送者goroutine阻塞,直到另一个goroutine在相同的channel上执行接收操作,在该条数据传输成功之后,两个goroutine可以继续执行后面的语句。同样的,如果接收数据的操作先发生,那么接收者goroutine也将阻塞,直到有另一个goroutine在相同的Channels上执行发送操作。例如:

        示例1:

     

func main() {
    		ch := make(chan int)
    		ch <- 10  //发送goroutine阻塞,直至其他goroutine将数据接收
    		fmt.Println("发送成功")
}

              示例2:

func recv(c chan int) {
    			ret := <-c
    			fmt.Println("接收成功", ret)
}

func main() {
    			ch := make(chan int)
    			go recv(ch)   // 启用goroutine接收值,该goroutine阻塞
    			ch <- 10    // 向管道中发送值,接收goroutine阻塞解除
    			fmt.Println("发送成功")
}

        使用无缓冲管道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也称为同步通道。

2.5、有缓冲的Channel

        有缓存的channel内部有一个元素队列。队列的最大容量是在调用make函数创建channel时通过第二个参数指定的。例如:

ch = make(chan string, 3)  // 创建一个可以缓存3个字符串的管道

        向有缓存channel执行发送操作就是向内部缓存队列的尾部插入元素,接收操作则是从队列的头部删除元素。如果内部缓存队列是满的,那么发送操作将阻塞直到另一个goroutine执行接收操作而释放了新的队列空间。同样,如果channel是空的,接收操作将阻塞直到有另一个goroutine执行发送操作而向队列插入元素。

        可以使用内置的len函数获取通道内元素的数量,使用cap函数获取通道的容量。

三、Channel的其他操作

3.1、判断Channel是否关闭

	if v, ok := <-ch; !ok {
 	fmt.Println("channel 已关闭,读取不到数据")
 	}

3.2、循环获取

for data := range ch {

  doSomething()

       }

3.3、select

              当与多个 goroutine 通信时,可以使用 select 来管理多个 channel 的通信数据:

           

for {
    select {
  		case <-ch1:
   			doSomething1()
  		case <-ch2:
   			doSomething2()
  		}
 }

作者:燕雨洁  部门:混合产品线

文章来自个人专栏
文章 | 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0