1. 异步方法简介
异步方法是指在执行该方法时,调用者可以继续执行其他的操作而无需等待该方法执行完毕。在传统的同步方法中,调用者必须等待被调用方法执行完毕后才能继续执行其他操作。
Golang是一门支持并发编程的语言,也提供了有力的异步编程功能。在Golang中,异步编程可以使用Go协程搭配Channel来实现。
2. 使用协程实现异步编程
协程是Golang中一个特殊的轻量级线程,可以在同一个进程中同时运行多个协程,而每个协程都运行在单独的栈空间中,且协程的创建和销毁堆栈开销非常小。这使得Golang非常适合进行高并发编程。
2.1 协程基本使用
在Golang中,可以使用关键字go
创建一个协程。例如,下面的代码展示了如何创建一个基本的协程:
func main() {
go func() {
fmt.Println("Hello, World!")
}()
}
以上代码会创建一个新的协程,该协程会在一个匿名函数中执行fmt.Println("Hello, World!")
。在另一个协程中会执行main()
函数中剩余的代码,不必等待该协程执行完毕。
2.2 协程与Channel配合使用
协程与Channel的搭配使用可以实现高效的异步编程。在Golang中,Channel是一种特殊的类型,可以用来在协程之间传递数据。
下面的代码展示了如何在协程间传递数据:
func main() {
c := make(chan string)
go func() {
time.Sleep(time.Second)
c <- "Hello, World!"
}()
fmt.Println("Waiting...")
fmt.Println(<-c)
}
以上代码创建了一个Channel,并在一个协程中向其中写入数据。在main()
函数中等待协程完成后,就可以读取并输出Channel中的数据了。
2.3 使用多个协程
使用多个协程可以进一步提高异步编程的效率。下面的代码展示了如何使用多个协程:
func worker(id int, jobs chan int, results chan int) {
for j := range jobs {
fmt.Println("Worker", id, "processing job", j)
time.Sleep(time.Second)
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)
for a := 1; a <= 9; a++ {
fmt.Println(<-results)
}
}
以上代码创建了3个协程,并启用worker()
函数来执行工作。在main()
函数中,会向jobs
Channel写入9个任务。每个协程都会从jobs
Channel中获取任务,并向results
Channel中写入结果。在main()
函数中,等待任务完成,最终读取所有的结果并输出。
3. 使用WaitGroup实现协程同步
在某些情况下,需要等待所有协程完成后再继续执行。这种情况可以使用WaitGroup来实现协程同步。
WaitGroup是Golang中的另一种特殊类型。可以使用WaitGroup来等待所有协程完成并执行特定操作。下面的代码展示了如何使用WaitGroup:
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(i, &wg)
}
wg.Wait()
fmt.Println("All workers done")
}
以上代码创建了5个协程,使用WaitGroup等待所有协程完成。在每个协程中调用wg.Done()
表示该协程已经完成。在main()
函数中调用wg.Wait()
等待所有协程完成。最后输出 "All workers done"。
4. 参考文献
Golang协程: https://zh.wikipedia.org/wiki/Goroutine
Golang Channel: https://zh.wikipedia.org/wiki/Channel
Golang WaitGroup: https://golang.org/pkg/sync/