golang chan用法
时间:2023-05-17 01:08
Golang是一种强类型语言,以其高并发性和简洁的语法而闻名。其中,chan是Golang中常见的通信方式之一,也是实现并发编程的重要组成部分。在本文中,我们将深入了解Golang中chan的用法和基本原理。 一、chan的概念和作用 chan是Golang中实现goroutine间通信的重要方式,简称管道。它是一种线程安全的数据结构,用于在Golang程序中传递信息。chan可以实现单向通信和双向通信,可以用于发送和接收数据,也可以用于同步goroutine。 二、chan的类型和使用方式 Golang中的chan是一个类型,可以使用make函数来创建。语法如下: 其中int表示管道里传递数据的类型。使用chan时需要注意以下几点: 发送和接收操作都是阻塞式的,即如果没有发送和接收操作匹配,那么goroutine会一直阻塞在这个操作上。例如: 在这个例子中,我们创建了一个int类型的管道,分别进行了发送和接收操作。在发送操作中,我们向管道中发送了一个值1;在接收操作中,我们从管道中取出了值并赋值给了变量a。由于发送和接收操作都是阻塞式的,所以这个程序会一直等待直到发送和接收操作匹配,才能正常结束。 可以使用close函数来关闭管道,关闭后的管道不能再次进行发送操作。例如: 在这个例子中,我们在发送操作之后调用了close函数,然后使用for循环对管道进行接收操作。接收操作中,使用了ok来判断管道是否已经关闭,防止出现死锁现象。 通过设置管道的方向,可以创建单向chan。例如: 在这个例子中,我们通过make函数创建了一个双向chan,然后通过make函数分别创建了只能发送和只能接收的单向chan。在发送操作和接收操作中,我们分别使用了sendCh和recvCh。 select语句可以同时监听多个管道的状态,可以用于管道的并发读取和写入操作。例如: 在这个例子中,我们创建了两个管道ch1和ch2,并在一个goroutine中向ch1中发送了值1。此后,我们使用select语句监听了两个管道,优先执行收到第一个值的case语句。 三、chan的基本原理 在Golang中,chan是基于特殊的数据结构实现的。当我们使用make函数创建chan时,实际上创建了一个值为nil、长度为0的切片,称之为channel。 我们可以通过以下方式来理解chan的原理: 在进行发送操作时,会将待发送的数据附加到channel底层的切片中。如果channel的长度为0,那么添加的元素的下标为0。如果channel的长度不为0,那么添加的元素的下标为channel的长度。 如果channel的长度已经达到了其容量上限,那么会在内存中新建一个更大的切片,并将原来的切片中的元素拷贝到新的切片中。因此,在进行发送操作时,会使用到内存管理和拷贝的机制。 在进行接收操作时,会从channel底层的切片中取出最先被附加进去的元素。如果切片中没有元素,那么会一直等待,直到有元素可取;如果channel已经被关闭,那么接收操作会立即返回一个零值。 当进行发送或接收操作时,如果channel的切片长度已经达到其容量上限,或者channel中已有数据等待被接收,那么发送或接收操作会一直处于阻塞状态,直到有足够的空间或数据可用。 在关闭channel时,会将channel的状态设置为已关闭,并不能再进行发送数据。如果channel中有未被接收的数据,那么可以继续进行接收操作,直到channel中没有数据为止。 总结 Golang中的chan是一种实现goroutine间通信的重要方式,从语法上看也非常简洁。掌握chan的基本用法和原理对于并发编程是非常重要的。 以上就是golang chan用法的详细内容,更多请关注Gxl网其它相关文章!ch := make(chan int)
ch := make(chan int)// 发送操作go func() { ch <- 1}()// 接收操作a := <- ch
ch := make(chan int)// 发送操作go func() { ch <- 1 close(ch)}()// 循环接收操作for { if val, ok := <-ch; ok { fmt.Println(val) } else { break }}
ch := make(chan int) // 双向chan// 定义只能发送的单向chansendCh := make(chan <- int)// 定义只能接收的单向chanrecvCh := make(<- chan int)// 发送操作时可以使用单向chango func() { sendCh <- 1}()// 接收操作时也可以使用单向chana := <-recvCh
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)}