MST

星途 面试题库

面试题:Go 中扇入扇出模式基础与扩展性

请简述 Go 语言中扇入(Fan - In)和扇出(Fan - Out)模式的概念,并说明在设计具有扩展性的系统时,扇入扇出模式通常在哪些场景下应用。同时,用 Go 代码实现一个简单的扇入示例,假设有多个输入通道,将这些通道的数据合并到一个输出通道。
48.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

扇入(Fan - In)和扇出(Fan - Out)模式概念

  1. 扇入(Fan - In)
    • 扇入是指将多个输入通道的数据合并到一个输出通道的模式。它常用于需要收集多个来源的数据并统一处理的场景,比如从多个 API 接口获取数据后汇总分析。可以理解为多个数据流“扇”形地进入到一个数据处理流中。
  2. 扇出(Fan - Out)
    • 扇出是指将一个输入通道的数据分发到多个输出通道的模式。通常在需要将一个任务并行化处理时使用,例如将一个大的计算任务分解为多个小任务,每个小任务在独立的 goroutine 中处理,数据就从一个通道扇出到多个通道分别处理。

应用场景

  1. 扇入应用场景
    • 数据聚合:例如在微服务架构中,从多个不同的微服务获取相关数据,然后汇总到一个地方进行统一处理。比如一个电商系统,要展示商品详细信息,可能需要从商品服务、库存服务、评价服务等多个微服务获取数据,然后聚合在一起返回给前端。
    • 日志收集:从多个服务器收集日志,然后统一进行分析和存储。每个服务器的日志输出可以看作一个输入通道,最终汇总到一个通道用于进一步处理。
  2. 扇出应用场景
    • 并行计算:将一个大的计算任务,如对大量数据的复杂计算,拆分成多个小任务并行执行。比如对一个大数据集进行排序,可以将数据集分成多个部分,每个部分在独立的 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 函数中,创建了两个输入通道 chan1chan2,并向它们发送一些数据,然后通过 fanIn 函数将这两个通道的数据合并到 resultChan 中,最后遍历 resultChan 输出数据。