

channel 是 Go 语言中用于在 goroutine 之间进行通信和同步的一种机制。它可以安全地在不同的 goroutine 之间传递数据,并且可以用来实现同步操作。
channel 可以是无缓冲的(unbuffered)或有缓冲的(buffered)。
无缓冲的 channel:发送操作会阻塞,直到另一个 goroutine 执行接收操作,反之亦然。
有缓冲的 channel:可以存储一定数量的数据,发送操作会在缓冲区未满时立即完成,接收操作会在缓冲区不为空时立即完成。
package main
import (
"fmt"
"time"
)
func main() {
// 创建一个无缓冲的整数通道
ch := make(chan int)
// 启动一个匿名 goroutine,它将在一秒钟后向通道发送数据 10
go func() {
time.Sleep(time.Second)
ch <- 10
}()
// 从通道接收数据,此操作会阻塞,直到有数据发送到通道
num := <-ch
// 打印接收到的数据
fmt.Println(num)
}
ch := make(chan int):创建一个无缓冲的整数通道,用于在不同的 goroutine 之间传递数据。go func() {...}:启动一个匿名 goroutine,在其中使用 time.Sleep(time.Second) 让该 goroutine 暂停一秒钟,然后将整数 10 发送到通道 ch 中。num := <-ch:从通道 ch 中接收数据,由于通道是无缓冲的,此操作会阻塞,直到有数据发送到通道中。fmt.Println(num):将接收到的数据打印输出。time.Sleep 来等待 goroutine 发送数据,这不是一种可靠的同步方式,在实际应用中可以使用 sync.WaitGroup 或其他同步机制来确保 goroutine 完成任务。package main
import (
"fmt"
"time"
)
func main() {
// 创建一个有缓冲的通道,容量为 20
ch := make(chan int, 20)
// 向通道发送数据
ch <- 1
ch <- 2
ch <- 3
ch <- 4
// 启动一个 goroutine 向通道发送数据
go func() {
time.Sleep(1 * time.Second)
ch <- 3
}()
// 接收数据
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}
func main() {...}:这是 Go 程序的主函数,程序从这里开始执行。ch := make(chan int, 20):创建一个有缓冲的通道 ch,其容量为 20,可存储 20 个整数。ch <- 1, ch <- 2, ch <- 3, ch <- 4:向通道 ch 发送四个整数 1、2、3 和 4。由于通道是有缓冲的且缓冲区未满,这些发送操作不会阻塞。go func() {...}:启动一个匿名 goroutine,在其中使用 time.Sleep(1 * time.Second) 让该 goroutine 暂停一秒钟,然后将整数 3 发送到通道 ch 中。fmt.Println(<-ch):从通道 ch 中接收数据并打印。这里有五次接收操作,前四次接收的是之前发送的 1、2、3、4 中的数据,最后一次接收的是匿名 goroutine 发送的数据 3(如果它已经发送)。由于通道是有缓冲的,接收操作不会阻塞,除非缓冲区为空。在 Go 语言中,close 函数用于关闭通道(channel)。关闭通道是一个重要的操作,它可以向接收方发送一个信号,表示不会再有数据发送到该通道。
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
// 接收通道中的数据
for num := range ch {
fmt.Println(num)
}
}
ch := make(chan int, 3):创建一个有缓冲的通道,容量为 3。ch <- 1, ch <- 2, ch <- 3:向通道发送数据。close(ch):关闭通道。for num := range ch {...}:使用 range 从通道中接收数据。当通道关闭时,range 循环会自动结束,不会阻塞。close 函数之前,需要确保通道没有被关闭过。v, ok := <-ch 来检查通道是否关闭,其中 ok 为 false 表示通道已关闭。package main
import (
"fmt"
)
func main() {
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for {
val, ok := <-ch
if!ok {
fmt.Println("Channel is closed")
break
}
fmt.Println(val)
}
}v, ok := <-ch:从通道接收数据,ok 为 true 表示接收成功,ok 为 false 表示通道已关闭。if!ok {...}:检查通道是否关闭,如果关闭则打印消息并退出循环。使用 close 函数的场景:
select 语句中,关闭通道可以触发相应的 case 分支。package main
import "fmt"
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
for i := 0; i < 100; i++ {
ch1 <- i
}
close(ch1)
}()
go func() {
for {
val, ok := <-ch1
if !ok {
break
}
ch2 <- val * val
}
close(ch2)
}()
for i := range ch2 {
fmt.Println(i)
}
}func main() {...}:这是 Go 程序的主函数,程序从这里开始执行。ch1 := make(chan int):创建一个无缓冲的整数通道 ch1,用于在不同的 goroutine 之间传递数据。ch2 := make(chan int):创建另一个无缓冲的整数通道 ch2,用于在不同的 goroutine 之间传递数据。go func() {...}:启动第一个匿名 goroutine,在这个 goroutine 中,使用 for 循环将 0 到 99 的整数依次发送到 ch1 通道中,发送完成后关闭 ch1 通道。go func() {...}:启动第二个匿名 goroutine,在这个 goroutine 中,使用 for 循环从 ch1 通道接收数据。 val, ok := <-ch1:从 ch1 通道接收数据,val 是接收到的数据,ok 表示通道是否关闭。if!ok {...}:如果 ok 为 false,表示 ch1 通道已关闭,此时跳出循环。ch2 <- val * val:将接收到的数据的平方发送到 ch2 通道中。close(ch2):关闭 ch2 通道。for i := range ch2 {...}:使用 for 循环从 ch2 通道接收数据,将接收到的数据打印输出。当 ch2 通道关闭时,循环自动结束。close 函数关闭通道,确保接收方知道数据发送完毕,避免死锁。goroutine 发送数据,第二个 goroutine 接收并处理数据,最后在主 goroutine 中打印处理后的数据,体现了通道在不同 goroutine 间的通信和数据处理流程。package main
import "fmt"
func connter(out chan<- int) {
for i := 0; i < 100; i++ {
out <- i
}
close(out)
}
func square(out chan<- int, in <-chan int) {
for i := range in {
out <- i * i
}
close(out)
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go connter(ch1)
go square(ch2, ch1)
for i := range ch2 {
fmt.Println(i)
}
}func connter(out chan<- int) {...}:
connter 的函数,接收一个只写通道 out(chan<- int)作为参数。for i := 0; i < 100; i++ {...}:使用 for 循环从 0 到 99 迭代。out <- i:将迭代的数字 i 发送到 out 通道中。close(out):当循环结束后,关闭 out 通道,向接收方发送信号表示数据发送完毕。func square(out chan<- int, in <-chan int) {...}:
square 的函数,接收两个通道作为参数: out chan<- int:只写通道,用于发送数据。in <-chan int:只读通道,用于接收数据。for i := range in {...}:使用 range 从 in 通道接收数据,当 in 通道关闭时,循环结束。out <- i * i:将接收到的数据 i 进行平方操作,并将结果发送到 out 通道。close(out):当 in 通道的数据全部接收并处理完后,关闭 out 通道。func main() {...}:
ch1 := make(chan int):创建一个无缓冲的整数通道 ch1。ch2 := make(chan int):创建另一个无缓冲的整数通道 ch2。go connter(ch1):启动一个 goroutine 并调用 connter 函数,将 ch1 作为参数传递给它,connter 函数会向 ch1 发送 0 到 99 的数字。go square(ch2, ch1):启动另一个 goroutine 并调用 square 函数,将 ch2 作为输出通道,ch1 作为输入通道,square 函数会从 ch1 接收数据,将其平方后发送到 ch2。for i := range ch2 {...}:使用 range 从 ch2 接收数据,并使用 fmt.Println 打印接收到的数据,当 ch2 关闭时,循环结束。goroutine 之间的安全通信和同步。close 函数的使用表示数据发送完毕,避免接收方无限等待。range 从通道接收数据,当通道关闭时,range 循环会自动结束,这是一种简洁的处理方式。