面试题答案
一键面试在Go语言中,闭包可以捕获其周围环境的变量,而通道用于在goroutine之间进行通信和同步。通过合理使用闭包和通道,可以保证数据的有序处理并避免竞态条件。
以下是一个示例代码,展示了三个不同功能的goroutine如何通过闭包和通道协同工作:
package main
import (
"fmt"
)
// 生成器函数,生成一系列数字
func generator(ch chan<- int) {
for i := 1; i <= 10; i++ {
ch <- i
}
close(ch)
}
// 平方计算函数
func squarer(in <-chan int, out chan<- int) {
for num := range in {
out <- num * num
}
close(out)
}
// 打印函数
func printer(in <-chan int) {
for num := range in {
fmt.Println(num)
}
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
// 启动生成器goroutine
go generator(ch1)
// 启动平方计算goroutine
go squarer(ch1, ch2)
// 启动打印goroutine
go printer(ch2)
// 防止主线程退出
select {}
}
代码说明
- generator函数:这是一个闭包,它向通道
ch
发送数字序列1
到10
,发送完毕后关闭通道。它只写通道ch
,所以参数是chan<- int
。 - squarer函数:这也是一个闭包,它从输入通道
in
接收数字,计算其平方,并将结果发送到输出通道out
。当输入通道关闭时,它也关闭输出通道。这里in
是只读通道<-chan int
,out
是只写通道chan<- int
。 - printer函数:这是一个闭包,它从通道
in
接收数字并打印出来。当通道关闭时,循环结束。它的通道in
是只读通道<-chan int
。 - main函数:创建了两个通道
ch1
和ch2
,并分别启动了generator
、squarer
和printer
三个goroutine。generator
生成的数字通过ch1
传递给squarer
,squarer
计算平方后通过ch2
传递给printer
。 - select {}:防止主线程退出,保证所有goroutine有足够时间执行。
通过这种方式,数据在不同的goroutine之间有序传递,每个操作都在不同的goroutine中并行执行,同时避免了竞态条件,因为数据通过通道传递,而不是共享内存。