面试题答案
一键面试1. 数据发送和接收机制区别
- 非缓冲通道:
- 发送操作:当一个goroutine向非缓冲通道发送数据时,它会被阻塞,直到另一个goroutine从该通道接收数据。这种阻塞确保了数据的发送和接收是同步进行的,数据直接从发送方传递到接收方。
- 接收操作:当一个goroutine从非缓冲通道接收数据时,它也会被阻塞,直到有数据被发送到该通道。
- 示例代码:
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
num := 42
fmt.Println("Sending number:", num)
ch <- num
fmt.Println("Number sent")
}()
received := <-ch
fmt.Println("Received number:", received)
}
在这个例子中,发送方goroutine在发送数据后阻塞,直到接收方从通道读取数据,然后发送方才会继续执行“Number sent”的打印。
- 缓冲通道:
- 发送操作:向缓冲通道发送数据时,只要通道的缓冲区未满,发送操作不会阻塞。数据会被存入缓冲区。只有当缓冲区已满时,发送操作才会阻塞,直到有数据从通道中被接收。
- 接收操作:从缓冲通道接收数据时,如果缓冲区中有数据,接收操作不会阻塞,直接从缓冲区取出数据。只有当缓冲区为空时,接收操作才会阻塞,直到有新的数据被发送到通道。
- 示例代码:
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
fmt.Println("Data sent to buffer")
received1 := <-ch
fmt.Println("Received:", received1)
received2 := <-ch
fmt.Println("Received:", received2)
}
这里缓冲通道的容量为2,所以前两次发送操作不会阻塞,直到接收操作开始从缓冲区取数据。
2. 适用场景
- 非缓冲通道适用场景:
- 同步场景:当需要确保两个goroutine之间严格的同步时,例如在生产者 - 消费者模型中,如果希望生产者生产一个数据后,立即由消费者处理,就可以使用非缓冲通道。
- 握手场景:比如在初始化阶段,一个goroutine需要等待另一个goroutine完成某些初始化操作后再继续,非缓冲通道可以实现这种“握手”机制。
- 缓冲通道适用场景:
- 流量控制场景:在生产者 - 消费者模型中,如果生产者生产数据的速度可能比消费者处理数据的速度快一些,缓冲通道可以作为一个缓冲区,暂时存储数据,防止生产者过快地被阻塞。只要缓冲区未满,生产者就可以继续生产。
- 解耦操作场景:当希望在一定程度上解耦发送方和接收方的操作时,缓冲通道可以起到缓冲作用,使得发送方不必等待接收方立即处理数据。