Menu
CoddyTech

Goroutine 基础

本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 59 课,共 107 课。

goroutine 是由 Go 运行时管理的轻量级执行线程。与会占用大量内存的传统线程不同,goroutine 启动时只需几 KB 的栈空间,因此你可以让成千上万个 goroutine 并发运行。

要启动一个 goroutine,只需在函数调用前加上 go 关键字:

func sayHello(name string) {
    fmt.Println("Hello,", name)
}

func main() {
    go sayHello("Alice")  // 并发运行
    go sayHello("Bob")    // 并发运行
    
    time.Sleep(100 * time.Millisecond)
    fmt.Println("Done")
}

当执行 go sayHello("Alice") 时,它不会等待 sayHello 执行完毕,而是立即继续执行下一行,同时 sayHello 在后台运行。这就是我们需要 time.Sleep 的原因。没有它,main 会在 goroutine 完成之前退出。

你也可以使用匿名函数启动 goroutine:

go func(msg string) {
    fmt.Println(msg)
}("Hello from goroutine")

main 函数本身在一个 goroutine 中运行。它返回时,其他所有 goroutine 都会立即终止,没有机会完成。使用 time.Sleep 是一种临时解决方案;在接下来的课程中,你会学习使用通道和等待组进行正确的同步。

challenge icon

挑战

简单

我们来构建一个任务执行器,使用 goroutine 并发执行多个任务。你将创建一个简单的系统,让任务在后台运行,同时主程序继续执行,以此演示 goroutine 如何实现并发执行。

你将把代码分成两个文件:

  • tasks.go:定义任务执行逻辑。

    创建一个 Task 结构体,包含 Name(字符串)和 Duration(整数,表示毫秒)字段。

    为 Task 实现一个 Run() 方法,让它通过休眠指定时长来模拟任务执行,然后打印:Task [Name] completed

    创建一个 RunAllTasks(tasks []Task) 函数,将每个任务的 Run() 方法作为 goroutine 启动。启动所有 goroutine 后,函数应休眠 500 毫秒,以便它们完成,然后打印:All tasks launched

  • main.go:读取任务信息,并协调并发执行。

    读取任务数量,然后读取每个任务的名称和时长。创建这些任务,并将它们传递给 RunAllTasks。函数返回后,打印:Main function done

输入内容如下:

  • 第 1 行:任务数量(整数)
  • 后续各行:每个任务占两行,第一行为任务名称,第二行为任务时长(毫秒)

例如,给定以下输入:

3
Download
100
Process
50
Upload
75

输出应显示任务完成情况(由于并发,顺序可能不同),然后显示完成消息:

Task Process completed
Task Upload completed
Task Download completed
All tasks launched
Main function done

注意:由于 goroutine 并发运行,时长较短的任务通常会先完成。任务完成顺序取决于各自的时长,较短的任务会先于较长的任务完成。

使用 time.Sleep、time.Duration 和 time.Millisecond 设置延迟。请记住,如果没有在 RunAllTasks 中休眠,该函数会在 goroutine 完成工作之前返回。

亲手试试

package main

import (
	"fmt"
)

func main() {
	// 读取任务数量
	var numTasks int
	fmt.Scanln(&numTasks)

	// TODO: 创建一个切片来存放任务
	
	// TODO: 读取每个任务的名称和时长
	// 对于每个任务:
	//   读取任务名称
	//   读取时长(整数)
	//   创建一个 Task,并将其添加到你的切片中

	// TODO: 用你的任务切片调用 RunAllTasks

	// TODO: 打印 "Main function done"
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Go 在线编译器