面试题答案
一键面试常见误用情况:未缓冲 channel 的死锁
- 示例代码
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
ch <- 1 // 向未缓冲 channel 发送数据
fmt.Println(<-ch)
}
在这段代码中,向未缓冲的 channel
发送数据时,由于没有其他 goroutine 准备好接收这个数据,就会导致死锁。因为未缓冲的 channel
只有在发送方和接收方都准备好时才能进行数据传递。
避免方法
- 使用缓冲 channel
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 1) // 创建有缓冲的 channel
ch <- 1
fmt.Println(<-ch)
}
这里创建了一个容量为 1 的缓冲 channel
,发送操作可以先将数据放入缓冲区,而不会立即阻塞,避免了死锁。
2. 使用 goroutine 进行接收
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
ch <- 1
close(ch)
}()
for val := range ch {
fmt.Println(val)
}
}
通过在一个新的 goroutine 中进行发送操作,并适时关闭 channel
,主 goroutine 可以通过 for... range
循环安全地接收数据,避免死锁。同时这种方式也保证了并发程序的正确性和高效性,利用了 goroutine 的并发特性。