MST

星途 面试题库

面试题:Go函数优化性能之并发与函数协同

假设你有一个任务,需要从多个API获取数据,然后将这些数据合并处理。请用Go语言设计一个解决方案,通过合理使用Go函数和并发来优化性能,并且要处理可能出现的并发安全问题,写出核心代码逻辑并解释设计思路。
43.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

核心代码逻辑

package main

import (
    "fmt"
    "sync"
)

// 模拟从API获取数据的函数
func fetchDataFromAPI(apiURL string, resultChan chan<- string, wg *sync.WaitGroup) {
    defer wg.Done()
    // 这里实际应是HTTP请求等获取数据操作,为简单模拟直接返回固定字符串
    data := "Data from " + apiURL
    resultChan <- data
}

func main() {
    apiURLs := []string{"api1.com", "api2.com", "api3.com"}
    var wg sync.WaitGroup
    resultChan := make(chan string, len(apiURLs))

    for _, url := range apiURLs {
        wg.Add(1)
        go fetchDataFromAPI(url, resultChan, &wg)
    }

    go func() {
        wg.Wait()
        close(resultChan)
    }()

    var mergedData string
    for data := range resultChan {
        mergedData += data + " "
    }

    fmt.Println("Merged Data:", mergedData)
}

设计思路

  1. 函数设计

    • fetchDataFromAPI 函数模拟从API获取数据。它接收API的URL、一个用于发送结果的通道 resultChan 以及一个 sync.WaitGroup 指针。该函数在完成数据获取(这里是简单模拟)后,通过通道发送数据,并调用 wg.Done() 表示任务完成。
  2. 并发处理

    • main 函数中,遍历 apiURLs 列表,为每个API URL启动一个新的goroutine来调用 fetchDataFromAPI 函数,实现并发获取数据。通过 wg.Add(1) 增加等待组的计数,确保所有goroutine都完成任务。
  3. 通道使用

    • 创建一个带缓冲的通道 resultChan,缓冲大小为API的数量,用于接收各个goroutine获取的数据。这样可以避免在发送数据时阻塞,提高并发效率。
    • 使用一个匿名goroutine,在所有 fetchDataFromAPI 任务完成(通过 wg.Wait() 判断)后,关闭 resultChan。这样在 for... range 循环中可以安全地迭代通道中的所有数据,直到通道关闭。
  4. 合并数据

    • main 函数的 for... range 循环中,从 resultChan 通道读取数据,并将其合并到 mergedData 字符串中,最终输出合并后的数据。
  5. 并发安全

    • 使用 sync.WaitGroup 来协调各个goroutine的完成,确保在所有数据获取完成后才关闭通道并处理合并数据,避免数据竞争等并发安全问题。同时,通道本身是类型安全的,在多goroutine间传递数据时不会出现数据混乱的情况。