MST

星途 面试题库

面试题:Go语言并发模型中goroutine与channel的协作原理

请详细阐述Go语言中goroutine和channel是如何协作来实现并发编程的,举例说明一个使用场景并写出相应代码。
50.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Goroutine与Channel协作实现并发编程阐述

  1. Goroutine
    • Goroutine是Go语言中实现并发的轻量级线程。它由Go运行时(runtime)管理,与操作系统线程相比,创建和销毁的开销极小。一个程序可以轻松创建成千上万的goroutine。例如,go func() { /* 这里是goroutine执行的代码 */ }() 这样就启动了一个匿名函数作为goroutine运行。
  2. Channel
    • Channel是Go语言中用于在goroutine之间进行通信和同步的机制。它可以看作是一个类型化的管道,数据可以通过它在不同的goroutine之间传递。例如,ch := make(chan int) 创建了一个可以传递 int 类型数据的channel。
  3. 协作方式
    • 发送和接收操作:goroutine通过channel进行数据的发送(ch <- value)和接收(value := <- ch)操作。发送操作会阻塞当前goroutine,直到有其他goroutine从该channel接收数据;接收操作也会阻塞,直到有数据被发送到该channel。这种阻塞特性实现了goroutine之间的同步。
    • 关闭Channel:可以使用 close(ch) 关闭一个channel。接收方可以通过 v, ok := <- ch 这种形式判断channel是否关闭,当 okfalse 时,表示channel已关闭且没有更多数据。
    • 单向Channel:还可以创建单向的channel,如 sendCh := make(chan <- int) 表示只能发送数据的channel,recvCh := make(<- chan int) 表示只能接收数据的channel,这有助于明确数据流向,增强代码的可读性和安全性。

使用场景及代码示例

  1. 场景:计算多个数字的平方,并将结果收集起来。假设我们有一组数字,希望并发地计算它们的平方,最后收集所有结果。
  2. 代码如下
package main

import (
    "fmt"
)

func square(nums []int, result chan int) {
    for _, num := range nums {
        result <- num * num
    }
    close(result)
}

func main() {
    nums := []int{1, 2, 3, 4, 5}
    result := make(chan int)

    go square(nums, result)

    for sq := range result {
        fmt.Println(sq)
    }
}

在上述代码中:

  • square 函数是一个在goroutine中运行的函数,它计算传入数字切片中每个数字的平方,并将结果发送到 result channel。计算完成后,关闭 result channel。
  • main 函数中,创建了 nums 切片和 result channel,并启动了一个goroutine来执行 square 函数。
  • 通过 for... range 循环从 result channel接收数据,当channel关闭时,循环自动结束,这样就收集到了所有数字的平方结果并打印出来。