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任务、做爬虫,用协程都能让代码更高效、更简洁。学一点,就能在实际项目里省不少时间。