【go从入门到精通】精通并发编程-channel
在Go语言中,并发和通信是密切相关的。channel是Go中实现并发通信的主要方式。
一、channel的定义和使用
Go语言中的通道类型(channel)允许Goroutine之间通过它们进行通信。通道是线程安全的,可以用于传递不同类型的数据。
定义一个channel:
var channel chan int
创建一个channel:
channel := make(chan int)
向channel发送数据:
channel <- 10
从channel接收数据:
value := <-channel
二、channel的不同使用方式
- 无缓冲的channel:
无缓冲的channel意味着发送和接收必须在两个goroutine同步之间进行。
package main
import (
"fmt"
"time"
)
func send(c chan int) {
c <- 10
}
func main() {
c := make(chan int)
go send(c)
fmt.Println(<-c)
}
- 有缓冲的channel:
有缓冲的channel可以存储一定数量的值,而不需要立即处理。
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int, 2)
c <- 1
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
- 使用for-range读取channel:
package main
import (
"fmt"
"time"
)
func send(c chan int) {
for i := 0; i < 5; i++ {
c <- i
}
close(c)
}
func main() {
c := make(chan int)
go send(c)
for i := range c {
fmt.Println(i)
}
}
- 使用select处理多个channel:
package main
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(2 * time.Second)
c1 <- "one"
}()
go func() {
time.Sleep(1 * time.Second)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println(msg1)
case msg2 := <-c2:
fmt.Println(msg2)
}
}
}
三、channel的关闭
可以使用内建的close函数来关闭channel。当一个channel被关闭,所有正在阻塞等待从该channel接收数据的goroutine都会收到一个0值。
package main
import (
"fmt"
"time"
)
func send(c chan int) {
for i := 0; i < 5; i++ {
c <- i
}
close(c)
}
func main() {
c := make(chan int)
go send(c)
for {
fmt.Println(<-c)
}
}
在上面的代码中,我们尝试从关闭的channel中接收数据,当所有的数据都被接收后,再尝试接收会返回0值,并且一直阻塞下去。所以,我们可以通过检查接收操作的第二个返回值来判断
评论已关闭