网站换域名 百度收录,华大集团 北京网站建设,建设网站西丽,施工企业的维保技术方案第47天的学习#xff1a;并发进阶——深入了解Go语言的并发模型#xff01;
目录
Go并发模型简介Goroutines深度讲解Channels的进阶使用Select语句详解并发模型设计模式实战案例分析常见问题与解决方案
1. Go并发模型简介
Go语言以其内置的并发支持而闻名。通过轻量级的g…第47天的学习并发进阶——深入了解Go语言的并发模型
目录
Go并发模型简介Goroutines深度讲解Channels的进阶使用Select语句详解并发模型设计模式实战案例分析常见问题与解决方案
1. Go并发模型简介
Go语言以其内置的并发支持而闻名。通过轻量级的goroutine和强大的channelGo提供了一种易于使用且高效的并发编程方法。
并发与并行的区别
并发处理多件事情的能力但不一定同时。并行同一时刻处理多件事情。
2. Goroutines深度讲解
Goroutine是Go语言的基本单位它比传统线程更轻量。
创建Goroutine
package mainimport (fmttime
)func say(s string) {for i : 0; i 5; i {fmt.Println(s)time.Sleep(100 * time.Millisecond)}
}func main() {go say(world)say(hello)
}运行流程图
main()├─ goroutine A : say(world)└─ goroutine B : say(hello)Goroutine的特点
启动goroutine使用 go 关键字。不阻塞当前程序的运行。实际调度由Go运行时处理。
3. Channels的进阶使用
Channels用于goroutines之间的通信。它们是类型安全的管道。
Channel的基本操作
package mainimport (fmt
)func sum(s []int, c chan int) {sum : 0for _, v : range s {sum v}c - sum
}func main() {s : []int{7, 2, 8, -9, 4, 0}c : make(chan int)go sum(s[:len(s)/2], c)go sum(s[len(s)/2:], c)x, y : -c, -cfmt.Println(x, y, xy)
}Channel类型
无缓冲Channel通信是同步的。缓冲Channel可以异步通信。
市场管理员求和的例子
**设想场景**市场末端有多个传感器会自动将商品数量推送到中央系统由系统统计总和。
操作解释创建Channelc : make(chan int)发送数据c - x在goroutine中执行接收数据x : -c
4. Select语句详解
select 语句类似于 switch 但用于Channels操作。
package mainimport (fmttime
)func fibonacci(c, quit chan int) {x, y : 0, 1for {select {case c - x:x, y y, xycase -quit:fmt.Println(quit)return}}
}func main() {c : make(chan int)quit : make(chan int)go func() {for i : 0; i 10; i {fmt.Println(-c)}quit - 0}()fibonacci(c, quit)
}作用
多路复用监听多个Channel。处理超时结合time.After实现超时控制。
5. 并发模型设计模式
工作池模型
用于限制同时运行的goroutines数目。
package mainimport (fmttime
)func worker(id int, jobs -chan int, results chan- int) {for j : range jobs {fmt.Printf(worker %d started job %d\n, id, j)time.Sleep(time.Second)fmt.Printf(worker %d finished job %d\n, id, j)results - j * 2}
}func main() {const numJobs 5jobs : make(chan int, numJobs)results : make(chan int, numJobs)for w : 1; w 3; w {go worker(w, jobs, results)}for j : 1; j numJobs; j {jobs - j}close(jobs)for a : 1; a numJobs; a {-results}
}Pipeline模式
用于串联多个处理阶段。
package mainimport (fmt
)func gen(nums ...int) -chan int {out : make(chan int)go func() {for _, n : range nums {out - n}close(out)}()return out
}func sq(in -chan int) -chan int {out : make(chan int)go func() {for n : range in {out - n * n}close(out)}()return out
}func main() {c : gen(2, 3, 4)out : sq(c)for n : range out {fmt.Println(n)}
}6. 实战案例分析
为了进一步巩固理解我们来看一个具体的并发应用示例。
案例并发Web爬虫
目标使用并发从多个URL抓取页面标题。
package mainimport (fmtnet/httpio/ioutilregexptime
)func fetch(url string, ch chan- string) {start : time.Now()resp, err : http.Get(url)if err ! nil {ch - fmt.Sprintf(Error: %s, err)return}defer resp.Body.Close()body, err : ioutil.ReadAll(resp.Body)if err ! nil {ch - fmt.Sprintf(Error reading body: %s, err)return}re : regexp.MustCompile(title(.*?)/title)matches : re.FindStringSubmatch(string(body))title : No title foundif len(matches) 1 {title matches[1]}secs : time.Since(start).Seconds()ch - fmt.Sprintf(%.2f seconds: %s, secs, title)
}func main() {urls : []string{https://golang.org,https://godoc.org,https://gopl.io,https://play.golang.org,}ch : make(chan string)for _, url : range urls {go fetch(url, ch)}for range urls {fmt.Println(-ch)}
}7. 常见问题与解决方案
在学习并发时你可能会遇到以下问题
死锁问题
原因两个goroutine相互等待对方释放资源。解决方法确保总是有一个goroutine能继续推进。
资源竞争
原因多个goroutine试图同时访问同一个资源。解决方法使用channel同步或者使用sync.Mutex。
Goroutine泄漏
原因goroutine等待无法到达的事件。解决方法确保所有channels都能正确关闭。
总结
今天我们深入探讨了Go语言的并发模型。理解如何有效地创建和管理Goroutines和Channels是写出高效并发程序的关键。通过示例代码和设计模式你学会了如何利用Go的并发特性来解决复杂的问题。 怎么样今天的内容还满意吗再次感谢观众老爷的观看关注GZH凡人的AI工具箱回复666送您价值199的AI大礼包。最后祝您早日实现财务自由还请给个赞谢谢