golang chan用法

2023-05-16 14:05:26 用法 Golang chan

golang是一种强类型语言,以其高并发性和简洁的语法而闻名。其中,chan是Golang中常见的通信方式之一,也是实现并发编程的重要组成部分。在本文中,我们将深入了解Golang中chan的用法和基本原理。

一、chan的概念和作用

chan是Golang中实现goroutine间通信的重要方式,简称管道。它是一种线程安全数据结构,用于在Golang程序中传递信息。chan可以实现单向通信和双向通信,可以用于发送和接收数据,也可以用于同步goroutine。

二、chan的类型和使用方式

Golang中的chan是一个类型,可以使用make函数来创建。语法如下:

ch := make(chan int)

其中int表示管道里传递数据的类型。使用chan时需要注意以下几点:

  1. chan是阻塞式的

发送和接收操作都是阻塞式的,即如果没有发送和接收操作匹配,那么goroutine会一直阻塞在这个操作上。例如:

ch := make(chan int)

// 发送操作
go func() {
   ch <- 1
}()

// 接收操作
a := <- ch

在这个例子中,我们创建了一个int类型的管道,分别进行了发送和接收操作。在发送操作中,我们向管道中发送了一个值1;在接收操作中,我们从管道中取出了值并赋值给了变量a。由于发送和接收操作都是阻塞式的,所以这个程序会一直等待直到发送和接收操作匹配,才能正常结束。

  1. 关闭chan

可以使用close函数来关闭管道,关闭后的管道不能再次进行发送操作。例如:

ch := make(chan int)

// 发送操作
go func() {
   ch <- 1
   close(ch)
}()

// 循环接收操作
for {
   if val, ok := <-ch; ok {
      fmt.Println(val)
   } else {
      break
   }
}

在这个例子中,我们在发送操作之后调用了close函数,然后使用for循环对管道进行接收操作。接收操作中,使用了ok来判断管道是否已经关闭,防止出现死现象。

  1. 单向chan

通过设置管道的方向,可以创建单向chan。例如:

ch := make(chan int) // 双向chan

// 定义只能发送的单向chan
sendCh := make(chan <- int)

// 定义只能接收的单向chan
recvCh := make(<- chan int)

// 发送操作时可以使用单向chan
go func() {
   sendCh <- 1
}()

// 接收操作时也可以使用单向chan
a := <-recvCh

在这个例子中,我们通过make函数创建了一个双向chan,然后通过make函数分别创建了只能发送和只能接收的单向chan。在发送操作和接收操作中,我们分别使用了sendCh和recvCh。

  1. select语句

select语句可以同时监听多个管道的状态,可以用于管道的并发读取和写入操作。例如:

ch1 := make(chan int)
ch2 := make(chan int)

// 发送操作
go func() {
   ch1 <- 1
}()

// 使用select语句并发监听多个管道
select {
case a := <- ch1:
   fmt.Println(a)
case b := <- ch2:
   fmt.Println(b)
}

在这个例子中,我们创建了两个管道ch1和ch2,并在一个goroutine中向ch1中发送了值1。此后,我们使用select语句监听了两个管道,优先执行收到第一个值的case语句。

三、chan的基本原理

在Golang中,chan是基于特殊的数据结构实现的。当我们使用make函数创建chan时,实际上创建了一个值为nil、长度为0的切片,称之为channel。

我们可以通过以下方式来理解chan的原理:

  1. 发送操作

在进行发送操作时,会将待发送的数据附加到channel底层的切片中。如果channel的长度为0,那么添加的元素的下标为0。如果channel的长度不为0,那么添加的元素的下标为channel的长度。

如果channel的长度已经达到了其容量上限,那么会在内存中新建一个更大的切片,并将原来的切片中的元素拷贝到新的切片中。因此,在进行发送操作时,会使用到内存管理和拷贝的机制。

  1. 接收操作

在进行接收操作时,会从channel底层的切片中取出最先被附加进去的元素。如果切片中没有元素,那么会一直等待,直到有元素可取;如果channel已经被关闭,那么接收操作会立即返回一个零值。

  1. 阻塞

当进行发送或接收操作时,如果channel的切片长度已经达到其容量上限,或者channel中已有数据等待被接收,那么发送或接收操作会一直处于阻塞状态,直到有足够的空间或数据可用。

  1. 关闭操作

在关闭channel时,会将channel的状态设置为已关闭,并不能再进行发送数据。如果channel中有未被接收的数据,那么可以继续进行接收操作,直到channel中没有数据为止。

总结

Golang中的chan是一种实现goroutine间通信的重要方式,从语法上看也非常简洁。掌握chan的基本用法和原理对于并发编程是非常重要的。

以上就是golang chan用法的详细内容,更多请关注其它相关文章!

相关文章