数码生活指南
霓虹主题四 · 更硬核的阅读氛围

Go语言协程是什么 使用技巧与常见问题解析

发布时间:2025-12-09 06:13:31 阅读:335 次

Go语言协程是什么

在写程序时,你可能遇到过这样的情况:一个任务要等网络请求回来才能继续,但其他事情其实可以先做。比如你在等外卖的时候,完全可以先看个视频、回几条消息,而不是干坐着。Go语言里的“协程”(Goroutine)就是干这个的——让程序能同时处理多个任务,还不占太多资源。

协程是Go语言里一种轻量级的执行单元,用起来特别简单。你只需要在函数前面加个 go 关键字,这个函数就会在一个新的协程里跑起来。

怎么启动一个协程?

比如你想同时打印两句话,不互相耽误:

package main

import (
    "fmt"
    "time"
)

func sayHello() {
    fmt.Println("你好,世界")
}

func main() {
    go sayHello()
    fmt.Println("主程序继续运行")
    time.Sleep(100 * time.Millisecond) // 等协程执行完
}

这里 main 函数一运行,go sayHello() 就启动了一个新协程去打印消息,而主程序不会停下来等它,直接输出“主程序继续运行”。为了不让主程序太快结束导致协程没机会执行,我们加了个短暂的等待。

协程和线程有啥不一样?

传统编程中,多线程也能实现并发,但线程开销大,系统资源吃得多。而Go的协程是由Go运行时管理的,一个线程可以跑成百上千个协程,切换成本低,写起来也轻松。你可以一口气起几十个协程,系统也不会卡住。

比如你要从三个不同的网站拉数据,可以这样写:

func fetchData(url string) {
    resp, _ := http.Get(url)
    defer resp.Body.Close()
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Printf("从 %s 获取了 %d 字节数据\n", url, len(body))
}

func main() {
    urls := []string{
        "https://example.com",
        "https://httpbin.org/json",
        "https://api.github.com"
    }

    for _, url := range urls {
        go fetchData(url)
    }

    time.Sleep(2 * time.Second) // 等所有请求完成
}

每个请求都在独立的协程里跑,几乎同时进行,比一个接一个地等快多了。

协程之间怎么通信?

多个协程一起跑,难免需要传递数据或协调动作。Go推荐用 channel(通道)来通信,而不是共享变量。这就像快递柜——一个人放,另一个人取,避免抢同一个东西出问题。

举个例子,主协程等子协程算完结果再继续:

func calculate(ch chan int) {
    sum := 0
    for i := 1; i <= 100; i++ {
        sum += i
    }
    ch <- sum // 把结果发到通道
}

这里主协程会一直等到 calculate 把数据发进通道才继续,既安全又清晰。

Go语言的协程不是什么神秘技术,它就是帮你把程序变得更“会 multitask”的工具。写服务器、处理大量IO任务、做爬虫,用协程都能让代码更高效、更简洁。学一点,就能在实际项目里省不少时间。