MST

星途 面试题库

面试题:Go语言中如何利用Channel实现多路复用I/O操作

假设你有多个I/O操作(如网络请求、文件读取等),每个操作完成后会通过Channel返回结果。请设计一个Go程序,利用Channel实现多路复用,即哪个I/O操作先完成就先处理其结果,同时要妥善处理可能出现的错误,并且在所有操作完成后安全关闭相关资源。
40.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func main() {
    urls := []string{
        "http://example.com",
        "http://golang.org",
        "http://github.com",
    }

    resultCh := make(chan Result)
    defer close(resultCh)

    for _, url := range urls {
        go func(u string) {
            var res Result
            res.URL = u
            resp, err := http.Get(u)
            if err != nil {
                res.Err = err
                resultCh <- res
                return
            }
            defer resp.Body.Close()

            _, err = io.Copy(os.Stdout, resp.Body)
            if err != nil {
                res.Err = err
            }
            resultCh <- res
        }(url)
    }

    numCompleted := 0
    for i := 0; i < len(urls); i++ {
        res := <-resultCh
        if res.Err != nil {
            fmt.Printf("Error for %s: %v\n", res.URL, res.Err)
        } else {
            fmt.Printf("Successfully processed %s\n", res.URL)
        }
        numCompleted++
        if numCompleted == len(urls) {
            fmt.Println("All operations completed.")
        }
    }
}

type Result struct {
    URL string
    Err error
}

代码说明

  1. 定义Result结构体:用于存储每个I/O操作的结果和可能出现的错误。
  2. 创建resultCh通道:用于接收每个I/O操作的结果。
  3. 启动多个goroutine进行I/O操作:这里以HTTP请求为例,实际应用中可以替换为文件读取等其他I/O操作。每个goroutine执行I/O操作,并将结果发送到resultCh通道。
  4. 处理结果:在主goroutine中通过for循环从resultCh通道接收结果,哪个操作先完成,其结果就会先被接收并处理。如果出现错误,打印错误信息;如果成功,打印成功信息。
  5. 检查所有操作是否完成:通过numCompleted变量记录已完成的操作数量,当所有操作完成后,打印提示信息。