面试题答案
一键面试扇入(Fan - In)和扇出(Fan - Out)模式概念
- 扇入(Fan - In):
- 扇入是指将多个输入通道的数据合并到一个输出通道的模式。它常用于需要收集多个来源的数据并统一处理的场景,比如从多个 API 接口获取数据后汇总分析。可以理解为多个数据流“扇”形地进入到一个数据处理流中。
- 扇出(Fan - Out):
- 扇出是指将一个输入通道的数据分发到多个输出通道的模式。通常在需要将一个任务并行化处理时使用,例如将一个大的计算任务分解为多个小任务,每个小任务在独立的 goroutine 中处理,数据就从一个通道扇出到多个通道分别处理。
应用场景
- 扇入应用场景:
- 数据聚合:例如在微服务架构中,从多个不同的微服务获取相关数据,然后汇总到一个地方进行统一处理。比如一个电商系统,要展示商品详细信息,可能需要从商品服务、库存服务、评价服务等多个微服务获取数据,然后聚合在一起返回给前端。
- 日志收集:从多个服务器收集日志,然后统一进行分析和存储。每个服务器的日志输出可以看作一个输入通道,最终汇总到一个通道用于进一步处理。
- 扇出应用场景:
- 并行计算:将一个大的计算任务,如对大量数据的复杂计算,拆分成多个小任务并行执行。比如对一个大数据集进行排序,可以将数据集分成多个部分,每个部分在独立的 goroutine 中进行排序,最后再合并结果。
- 任务分发:当有大量任务需要处理时,将任务分发给多个工作者(worker)进行并行处理。例如一个消息队列系统,将接收到的消息分发给多个消费者进行处理。
Go 代码实现扇入示例
package main
import (
"fmt"
)
func fanIn(inputs...<-chan int) <-chan int {
var mergedChan = make(chan int)
go func() {
var wg sync.WaitGroup
wg.Add(len(inputs))
for _, input := range inputs {
go func(c <-chan int) {
defer wg.Done()
for val := range c {
mergedChan <- val
}
}(input)
}
go func() {
wg.Wait()
close(mergedChan)
}()
}()
return mergedChan
}
可以这样使用这个函数:
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go func() {
chan1 <- 1
chan1 <- 2
close(chan1)
}()
go func() {
chan2 <- 3
chan2 <- 4
close(chan2)
}()
resultChan := fanIn(chan1, chan2)
for val := range resultChan {
fmt.Println(val)
}
}
上述代码中,fanIn
函数接收多个输入通道,并返回一个合并后的输出通道。在 main
函数中,创建了两个输入通道 chan1
和 chan2
,并向它们发送一些数据,然后通过 fanIn
函数将这两个通道的数据合并到 resultChan
中,最后遍历 resultChan
输出数据。