Golang 之协程的用法讲解
什么是协程
协程(Coroutines),也称为轻量级线程(Light Weight Thread),是一种用户态线程,不依赖于操作系统内核,由程序自己实现调度,可以在一条线程中运行多个协程,协程之间可以独立运行,也可以通过通道(Channel)进行通信和同步。协程通常用于实现事件驱动、异步编程、并发计算等技术领域。
协程的用法
在 Golang 中,协程的创建非常简单,只需要使用关键字 go
,将一个函数调用前缀即可。例如:
go func() {
// 协程要执行的代码
}()
上述代码定义了一个匿名函数,并放置在一个新的协程中执行。
除了匿名函数,我们也可以使用普通的函数。例如:
func worker() {
// 协程要执行的代码
}
go worker()
协程创建后,程序不会等待协程执行完毕,而是继续执行主流程,所以协程创建后可以与主流程并行执行。
协程在执行过程中,可以通过 time.Sleep()
或者 select
等方式等待一段时间,也可以通过 sync.WaitGroup
等方式等待协程全部执行完毕。
示例一:使用协程实现并发计数器
package main
import (
"fmt"
"sync"
)
func main() {
var count int
var lock sync.Mutex
for i := 0; i < 10000; i++ {
go func() {
lock.Lock()
count++
lock.Unlock()
}()
}
// 确保所有协程执行完毕
for count < 10000 {
// do nothing
}
fmt.Println(count)
}
上述代码定义了一个计数器变量 count
,并使用 sync.Mutex
做为锁,保证对 count
的并发访问是安全的。
在一个循环中启动了 10000 个协程,每个协程都对 count
进行加一操作,在加一操作前使用锁进行了同步,从而保证了并发安全。
最后使用一个循环等待所有协程执行完毕,然后输出计数器的值。
示例二:使用协程实现并发送邮件
package main
import (
"fmt"
"net/smtp"
)
func main() {
var to = []string{"user1@example.com", "user2@example.com", "user3@example.com"}
for _, addr := range to {
go func(addr string) {
sendMail(addr, "Subject", "Content")
}(addr)
}
// 等待所有协程执行完毕
fmt.Println("Sending mails...")
}
func sendMail(to, subject, body string) error {
from := "sender@example.com"
auth := smtp.PlainAuth("", from, "password", "smtp.example.com")
msg := "From: " + from + "\n" +
"To: " + to + "\n" +
"Subject: " + subject + "\n\n" +
body
err := smtp.SendMail("smtp.example.com:25", auth, from, []string{to}, []byte(msg))
if err != nil {
fmt.Println(err)
return err
}
fmt.Println("Mail sent to", to)
return nil
}
上述代码定义了一个接收地址列表 to
,并在循环中启动了多个协程,每个协程使用 sendMail
函数向一个地址发送邮件。
sendMail
函数中,使用 smtp.PlainAuth
构造了一个 smtp.Auth
实例,用于进行 SMTP 认证。
接下来,构造了邮件的内容 msg
,并使用 smtp.SendMail
函数发送邮件。
在协程完成邮件发送后,输出提示信息。
总结
协程是 Golang 中非常强大的并发编程模型。使用协程可以轻松地实现事件驱动、异步编程、并发计算等技术领域的需求。在使用协程时,需要注意协程间的同步和数据共享问题,可以使用锁、通道、等待组等技术保证并发安全。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Golang 之协程的用法讲解 - Python技术站