【干货】Golang 并发编程:从基础到实践
Golang 是一种高效的编程语言,同时也是一种支持并发编程的语言。在 Golang 中,使用 goroutine、channel 和 select 等关键词可以很方便地进行并发编程。本文将从基础到实践,介绍 Golang 并发编程的相关知识点。
一、基础知识点
1. goroutine
Goroutine 是 Golang 中的轻量级线程,可以在单个程序中并发执行多个任务。创建 Goroutine 的方式是在前面加上关键字 go,例如 go func() { ... }()。通过关键字 go 可以让函数在一个新的 Goroutine 中运行,同时不会阻塞当前 Goroutine。
2. channel
Channel 是 Golang 中的通信机制,可以让 Goroutine 之间进行通信。Channel 可以用来同步 Goroutine 的执行,也可以用于传递数据。创建一个 channel 的方式是使用 make 函数,例如 ch := make(chan int)。
3. select
Select 是 Golang 中的多路复用机制,可以同时监听多个 channel 的操作。当多个 channel 中有数据可读或可写时,select 会随机选择一个 channel 并执行相应的操作。使用 select 可以避免 Goroutine 阻塞等待某个 channel 的数据。
二、实践应用
1. 生产者-消费者模型
生产者-消费者模型是一种常见的并发编程模型。在该模型中,有一个生产者 Goroutine 负责生成数据并将数据发送到一个 channel 中,而多个消费者 Goroutine 则从该 channel 中接收数据并进行处理。下面是一个简单的生产者-消费者模型的实现:
```go
func producer(ch chan int) {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}
func consumer(ch chan int, wg *sync.WaitGroup) {
for i := range ch {
fmt.Println("Received:", i)
time.Sleep(100 * time.Millisecond)
}
wg.Done()
}
func main() {
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(2)
go producer(ch)
go consumer(ch, &wg)
go consumer(ch, &wg)
wg.Wait()
}
```
2. 并发下载器
并发下载器是一种常见的多线程应用。在该应用中,有多个 Goroutine 同时下载指定链接的文件,并将下载结果保存到本地。下面是一个简单的并发下载器的实现:
```go
func download(url string, filename string, ch chan bool) {
res, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
file, err := os.Create(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
io.Copy(file, res.Body)
ch <- true
}
func main() {
urls := []string{"http://example.com/file1", "http://example.com/file2", "http://example.com/file3"}
ch := make(chan bool, len(urls))
for _, url := range urls {
filename := url[strings.LastIndex(url, "/")+1:]
go download(url, filename, ch)
}
for i := 0; i < len(urls); i++ {
<-ch
}
fmt.Println("All files downloaded")
}
```
在以上代码中,我们使用了带有缓冲的 channel,可以让下载 Goroutine 先将下载结果发送到 channel 中,然后通过主 Goroutine 读取 channel 中的数据,以确保所有文件都下载完成后再输出下载结果。
三、总结
本文通过介绍 Goroutine、channel 和 select 等关键词,以及生产者-消费者模型和并发下载器的实现方式,希望能够帮助读者更好地理解和应用 Golang 的并发编程。同时,需要注意 Goroutine 和 channel 的使用,以确保程序的正确性和稳定性。