# goroutine学习笔记
个人将《go程序设计》p182中的例程做了些许修改。整个过程中有以下几个问题
- 将缓冲通道改成无缓冲通道后的goroutine泄露问题
```go
var response = make(chan string, 3)
func request(url string) string {
switch url {
case "europe.gopl.io":
time.Sleep(5 * time.Second)
log.Println(url)
break
case "americas.gopl.io":
time.Sleep(7 * time.Second)
log.Println(url)
break
case "asia.gopl.io":
time.Sleep(3 * time.Second)
log.Println(url)
break
}
return url
}
func mirrResponse() string {
go func() { response <- request("asia.gopl.io") }()
go func() { response <- request("europe.gopl.io") }()
go func() { response <- request("americas.gopl.io") }()
fmt.Printf("channel len:%d\n", len(response))
fmt.Printf("channel cap:%d\n", cap(response))
// <-response
// <-response
return <-response
}
func main() {
for i := 0; i < 10; i++ {
fmt.Println("resp_url:", mirrResponse())
fmt.Printf("goroutineNum:%d\n", runtime.NumGoroutine())
}
}
```
运行以上程序,通过在main函数中输出运行协程数量,可以观察到携程数量不断增加。这里主要原因是:因为只有一个<-reponse,所以每次运行只会阻塞等待第一个"asia.gopl.io"的response返回,但是后台剩下的两个携程还是会运行;且由于没有等待其执行完后运行,所以每次运行mirrResponse函数时都会新增两个运行的携程,故NumGoroutine的输出每次+2
- 修改实验
```go
func mirrResponse() string {
go func() { response <- request("asia.gopl.io") }()
go func() { response <- request("europe.gopl.io") }()
go func() { response <- request("americas.gopl.io") }()
fmt.Printf("channel len:%d\n", len(response))
fmt.Printf("channel cap:%d\n", cap(response))
// <-response
<-response
return <-response
}
```
当消费者(<-reponse)==2时,mirrResponse会阻塞等待第二个协程执行完后再返回,且由于休眠的时间不同,始终有一个协程处于睡眠状态,加上main所在的主协程,故总是能输出运行协程数=2