这是我参与「第五届青训营 」笔记创作活动的第2天
- 使用goroutine的并发性
- 如果一个程序是为了支持并发而编写,那么可能也支持并行:同时运行多任务。(目前大部分计算机都有多个处理器)
- goroutine称为并发任务,也称为协程;在其他编程语言中类似与“线程”。但是“协程”比“线程”用更少的计算机内存,启动和停止的时间更少
- 每一个GO程序默认运行着一个goroutine,即GO程序中的main函数。
- 下面来看具体的并发特性
- 下面为正常执行两个函数,a()完成后,执行b().
func a() {
for i := 0; i < 10; i++ {
fmt.Print("a")
}
}
func b() {
for i := 0; i < 10; i++ {
fmt.Print("b")
}
}
func main() {
a()
b()
fmt.Println("main end()")
}
// 结果:aaaaaaaaabbbbbbbbbbmain end()
- 下面我们将两个函数分别都启用一个goroutine来运行,只需要在函数调用前加go关紧字就可以了。
func a() {
for i := 0; i < 20; i++ {
fmt.Print("a")
}
}
func b() {
for i := 0; i < 20; i++ {
fmt.Print("b")
}
}
func main() {
go a()
go b()
time.Sleep(time.Second)
fmt.Println("main end()")
}
// 结果:aaaaaabbbbaaabbbbbbmain end()
- 可以观察到输出结果中,a与b交替输出,并没有顺序执行。
- 注意:main函数中填加了一秒的睡眠函数,因为GO程序在
main goutine执行结束时会结束所有的goutine,a()与b()就都无法执行,这样可以先给1秒钟看看效果。
- 协程的顺序
- 第一个问题: 通过上面的例子我们了解到,GO程序实现了并发的执行,但是我们无法控制a()、b()以及main()协程的执行顺序。甚至main先结束会影响另外的协程运行;所以这不是我们想要的,接下来,我们使用“channel”来解决这个问题。
- 第二个问题: GO不允许使用go语句调用的函数具有返回值,因为在
main goroutine中需要使用go语句的返回值时,该协程可能还没有执行完无法返回!这也不是我们想看到的,这里编译器就直接不会给我们通过,也需要使用“channle”来解决。 - 每个“channle”将携带特定类型的值
type Page struct {
URL string
Size int
}
func main() {
pages := make(chan Page)
urls := []string{"https://example.com", "https://baidu.com", "https://qq.com"}
for _, url := range urls {
go responseSize(url, pages)
}
for i := 0; i < len(urls); i++ {
page := <-pages
fmt.Printf("%s: %d\n", page.URL, page.Size)
}
}
func responseSize(url string, channel chan Page) {
response, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
// main函数退出,就释放链接
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
// len() 字节切片的大小与页面大小相同
channel <- Page{URL: url, Size: len(body)}
}
/*
results:
https://baidu.com: 370900
https://qq.com: 228
https://example.com: 1256
*/
- 上面的例子帮助我们解决了协程的两个问题,同步goroutine。“channel”通过使用
blocking goroutine来暂停当前当前协程中所有进一步的操作来等待另一个goroutine发送值到“channel”中 - 所以我们使用“channel”来实现同步关系时,有“发送”就要有“接收”;有“接收”就要有“发送”,不然都会导致程序失败,甚至死锁问题。
源:《Head First GO语言程序设计》——Jay McGavren, 刘红泉,王佳 译