Go语言是一门支持并发编程的编程语言,它的并发模型让程序员可以利用多核CPU的优势进行高效的并发编程,提高程序性能。在Go语言中,可以使用goroutine和channel实现并发。下面,我们来详细讲解Go语言并发模型的2种编程方案。
方案1:使用Goroutine实现并发
Goroutine是Go语言提供的一种轻量级的并发机制,它可以在单个线程内同时运行多个Goroutine,相较于传统的线程,Goroutine更轻量,更高效。
Goroutine的使用
使用Goroutine非常简单,只需要在函数调用前加上"go"关键字即可。例如:
func main() {
go printNum()
fmt.Println("main function")
}
func printNum() {
for i := 1; i <= 10; i++ {
fmt.Println(i)
}
}
上面的代码创建了一个新的Goroutine,在新的Goroutine中打印1~10的数字。同时,在主函数中打印"main function"。运行上面的代码,你会发现"main function"会在1~10的数字之前输出。
Goroutine的优势
使用Goroutine的最大优势在于可以实现非常高效的并发操作。Goroutine的创建和销毁非常轻量,可以很容易地创建上千个Goroutine,而这些Goroutine可以在单个线程内同时运行,避免了线程切换的开销。
方案2:使用Channel实现并发
Channel是Go语言提供的一种用于在Goroutine之间传递数据的机制。它可以用于同步和通信,并保证并发安全。
Channel的使用
Channel可以使用内置的make函数创建,语法为make(chan
func main() {
c := make(chan int)
go sendNum(c)
num := <-c
fmt.Println(num)
}
func sendNum(c chan int) {
for i := 1; i <= 10; i++ {
c <- i
}
}
上面的代码创建了一个int类型的Channel,并使用sendNum函数向Channel中发送了1~10的数字。主函数中从Channel中读取并打印了第一个数字。由于Channel是阻塞的,在没有数据传输的时候会等待,因此可以保证sendNum函数执行完毕后再执行主函数。
Channel的优势
使用Channel可以实现非常高效的Goroutine之间的通信,并且保证并发安全。Channel的使用使得Goroutine之间的同步和通信变得非常容易,可以有效地避免数据竞争和死锁等问题。
示例说明
下面我们来举两个使用Goroutine和Channel实现并发的示例。
示例1
我们可以通过使用Goroutine和Channel实现并发的计算。例如:
func calc(num int, c chan int) {
sum := 0
for i := 1; i <= num; i++ {
sum += i
}
c <- sum
}
func main() {
c := make(chan int)
go calc(100, c)
go calc(200, c)
go calc(300, c)
sum1 := <-c
sum2 := <-c
sum3 := <-c
fmt.Println(sum1 + sum2 + sum3)
}
上面的代码使用三个Goroutine分别计算1~100、1~200和1~300的数字之和,并将结果发送到同一个Channel中。主函数从Channel中读取三个结果并相加,最后将结果打印出来。
示例2
我们也可以利用Goroutine和Channel实现并发的爬虫程序。例如:
func crawl(url string, ch chan<- string) {
resp, err := http.Get(url)
if err != nil {
log.Println("ERROR: Failed to crawl", url)
ch <- ""
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("ERROR: Failed to read response body of", url)
ch <- ""
return
}
ch <- string(body)
}
func main() {
urls := []string{"https://www.baidu.com", "https://www.google.com", "https://www.bing.com"}
ch := make(chan string)
for _, url := range urls {
go crawl(url, ch)
}
for range urls {
fmt.Println(<-ch)
}
}
上面的代码创建了三个Goroutine分别爬取百度、谷歌和必应的首页,并将结果发送到同一个Channel中。主函数从Channel中读取三个结果并打印出来。
这两个示例说明了使用Goroutine和Channel实现的并发程序可以应用到各种场景中,并且非常高效和灵活。只需要将需要并发执行的任务封装成一个函数,在函数前加上"go"关键字或将结果发送到Channel中即可。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Go语言并发模型的2种编程方案 - Python技术站