Go 并发概述
Go语言以其简洁的语法和强大的并发支持而闻名。并发编程是现代软件开发中的重要概念,它允许程序同时执行多个任务,从而提高效率。Go语言通过goroutine和channel等机制,使得并发编程变得简单且高效。
什么是并发?
并发是指在同一时间段内处理多个任务的能力。与并行不同,并发并不一定意味着任务同时执行,而是任务可以在时间上重叠。Go语言通过goroutine实现了轻量级的并发。
Go routine
Goroutine是Go语言中的轻量级线程,由Go运行时管理。与操作系统线程相比,goroutine的创建和销毁开销更小,因此可以轻松创建成千上万个goroutine。
创建Goroutine
在Go中,只需在函数调用前加上go
关键字即可创建一个goroutine:
go
package main
import (
"fmt"
"time"
)
func printNumbers() {
for i := 1; i <= 5; i++ {
fmt.Println(i)
time.Sleep(500 * time.Millisecond)
}
}
func main() {
go printNumbers() // 创建一个goroutine
time.Sleep(2 * time.Second) // 等待goroutine执行完毕
fmt.Println("Main function finished")
}
输出:
1
2
3
4
5
Main function finished
备注
注意:time.Sleep
用于确保主函数等待goroutine执行完毕。在实际应用中,通常会使用channel或sync.WaitGroup
来同步goroutine。
Channel
Channel是goroutine之间通信的管道。通过channel,goroutine可以安全地发送和接收数据。
创建和使用Channel
go
package main
import (
"fmt"
"time"
)
func sendData(ch chan string) {
time.Sleep(2 * time.Second)
ch <- "Hello from goroutine"
}
func main() {
ch := make(chan string)
go sendData(ch)
msg := <-ch
fmt.Println(msg)
}
输出:
Hello from goroutine
提示
Channel可以是带缓冲的或不带缓冲的。带缓冲的channel允许在没有接收者的情况下发送多个值。
实际应用场景
并发下载文件
假设我们需要并发下载多个文件,可以使用goroutine和channel来实现:
go
package main
import (
"fmt"
"io"
"net/http"
"os"
"sync"
)
func downloadFile(url string, wg *sync.WaitGroup) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error downloading:", url, err)
return
}
defer resp.Body.Close()
out, err := os.Create("downloaded_file")
if err != nil {
fmt.Println("Error creating file:", err)
return
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
fmt.Println("Error saving file:", err)
return
}
fmt.Println("Downloaded:", url)
}
func main() {
var wg sync.WaitGroup
urls := []string{
"https://example.com/file1",
"https://example.com/file2",
"https://example.com/file3",
}
for _, url := range urls {
wg.Add(1)
go downloadFile(url, &wg)
}
wg.Wait()
fmt.Println("All files downloaded")
}
警告
在实际应用中,请确保处理所有可能的错误,并考虑网络超时和重试机制。
总结
Go语言的并发模型通过goroutine和channel提供了简单而强大的工具,使得并发编程变得容易。通过理解并掌握这些概念,你可以编写高效且可扩展的并发程序。
附加资源
练习
- 修改上面的并发下载文件示例,使其能够将下载的文件保存为不同的文件名。
- 创建一个程序,使用多个goroutine计算1到1000的平方和,并使用channel将结果汇总。