MST

星途 面试题库

面试题:Go语言Goroutine的销毁及资源管理问题

在Go语言中,Goroutine没有直接的销毁方法,通常依靠自然结束来释放资源。请描述一种场景,在该场景下需要在外部主动结束一个Goroutine,并说明如何通过channel和context来实现资源的合理管理。同时,解释一下context在这个过程中的作用及原理。
43.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

场景描述

假设我们有一个Goroutine用于执行一个长时间运行的任务,例如从网络下载一个大文件。在下载过程中,如果用户突然取消下载操作,就需要在外部主动结束这个正在执行下载任务的Goroutine。

通过channel实现主动结束

package main

import (
    "fmt"
    "time"
)

func main() {
    stopCh := make(chan struct{})

    go func() {
        for {
            select {
            case <-stopCh:
                fmt.Println("Goroutine stopped")
                return
            default:
                fmt.Println("Doing some work...")
                time.Sleep(1 * time.Second)
            }
        }
    }()

    time.Sleep(3 * time.Second)
    close(stopCh)
    time.Sleep(1 * time.Second)
}

在上述代码中,我们创建了一个无缓冲的stopCh通道。Goroutine通过select语句监听这个通道,当通道接收到信号(close(stopCh))时,Goroutine就会结束。

通过context实现主动结束

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()

    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("Goroutine stopped")
                return
            default:
                fmt.Println("Doing some work...")
                time.Sleep(1 * time.Second)
            }
        }
    }(ctx)

    time.Sleep(5 * time.Second)
}

这里使用context.WithTimeout创建了一个带有超时的上下文ctxcancel函数用于主动取消上下文。Goroutine通过监听ctx.Done()通道来判断是否需要结束。

context的作用及原理

  • 作用context主要用于在多个Goroutine之间传递请求范围的截止时间、取消信号以及其他请求相关的值。它为Goroutine提供了一种标准的方式来进行协作式取消和超时控制,使得资源能够得到合理的管理,避免资源泄露。
  • 原理context是一个接口类型,它的实现包含了取消功能、截止时间以及携带的值。context可以被传递给不同的Goroutine,当父context被取消或超时,所有从它衍生出来的子context也会收到相应的取消信号。ctx.Done()返回的通道会在context被取消或超时时关闭,Goroutine通过监听这个通道来做出相应的处理,从而实现资源的合理释放和任务的有序结束。