Last active
July 16, 2020 09:32
-
-
Save cpusoft/35185fe7bbd66244af9d5fac57b5cd8f to your computer and use it in GitHub Desktop.
得到协程的返回值
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // go routine 返回值,main一般是不能获取的 | |
| // 需要通过channel,打通通道,得到返回值 | |
| package main | |
| import ( | |
| "fmt" | |
| "net/http" | |
| ) | |
| // result封装错误,和其他需要附加的信息 | |
| type Result struct { | |
| Error error | |
| Response *http.Response | |
| } | |
| // 通过一个函数,将go封装起来, | |
| // done 用于终止函数 | |
| // Result为返回值 | |
| func checkStatus(done <-chan interface{}, urls ...string) <-chan Result { | |
| resultCh := make(chan Result) | |
| go func() { | |
| defer close(resultCh) | |
| for _, url := range urls { | |
| resp, err := http.Get(url) | |
| result := Result{Error: err, Response: resp} | |
| select { | |
| case <-done: | |
| return | |
| case resultCh <- result: | |
| } | |
| } | |
| }() | |
| return resultCh | |
| } | |
| //如何返回go routine 的返回值 | |
| func main() { | |
| done := make(chan interface{}) | |
| defer close(done) | |
| urls := []string{"http://www.baidu.com/", "http://badhost/"} | |
| for result := range checkStatus(done, urls...) { | |
| if result.Error != nil { | |
| fmt.Printf("error: %v", result.Error) | |
| continue | |
| } | |
| fmt.Printf("Resonse :%v\n", result.Response.Status) | |
| } | |
| } | |
| https://docs.lvrui.io/2020/03/26/go%E8%AF%AD%E8%A8%80%E5%9C%A8goroutine%E4%B8%AD%E6%8B%BF%E5%88%B0%E8%BF%94%E5%9B%9E%E5%80%BC/ | |
| 有两种方法: | |
| 1 发送给独立的goroutine处理程序 | |
| package main | |
| import ( | |
| "fmt" | |
| "sync" | |
| "time" | |
| ) | |
| var responseChannel = make(chan string, 15) | |
| func httpGet(url int, limiter chan bool, wg *sync.WaitGroup) { | |
| // 函数执行完毕时 计数器-1 | |
| defer wg.Done() | |
| fmt.Println("http get:", url) | |
| responseChannel <- fmt.Sprintf("Hello Go %d", url) | |
| // 释放一个坑位 | |
| <- limiter | |
| } | |
| func ResponseController() { | |
| for rc := range responseChannel { | |
| fmt.Println("response: ", rc) | |
| } | |
| } | |
| func main() { | |
| // 启动接收response的控制器 | |
| go ResponseController() | |
| wg := &sync.WaitGroup{} | |
| // 控制并发数为10 | |
| limiter := make(chan bool, 20) | |
| for i := 0; i < 99; i++ { | |
| // 计数器+1 | |
| wg.Add(1) | |
| limiter <- true | |
| go httpGet(i, limiter, wg) | |
| } | |
| // 等待所以协程执行完毕 | |
| wg.Wait() // 当计数器为0时, 不再阻塞 | |
| fmt.Println("所有协程已执行完毕") | |
| } | |
| 2 在当前函数中聚合返回 | |
| package main | |
| import ( | |
| "fmt" | |
| "sync" | |
| ) | |
| func httpGet(url int,response chan string, limiter chan bool, wg *sync.WaitGroup) { | |
| // 函数执行完毕时 计数器-1 | |
| defer wg.Done() | |
| // 将拿到的结果, 发送到参数中传递过来的channel中 | |
| response <- fmt.Sprintf("http get: %d", url) | |
| // 释放一个坑位 | |
| <- limiter | |
| } | |
| // 将所有的返回结果, 以 []string 的形式返回 | |
| func collect(urls []int) []string { | |
| var result []string | |
| wg := &sync.WaitGroup{} | |
| // 控制并发数为10 | |
| limiter := make(chan bool, 5) | |
| defer close(limiter) | |
| // 函数内的局部变量channel, 专门用来接收函数内所有goroutine的结果 | |
| responseChannel := make(chan string, 20) | |
| // 为读取结果控制器创建新的WaitGroup, 需要保证控制器内的所有值都已经正确处理完毕, 才能结束 | |
| wgResponse := &sync.WaitGroup{} | |
| // 启动读取结果的控制器 | |
| go func() { | |
| // wgResponse计数器+1 | |
| wgResponse.Add(1) | |
| // 读取结果 | |
| for response := range responseChannel { | |
| // 处理结果 | |
| result = append(result, response) | |
| } | |
| // 当 responseChannel被关闭时且channel中所有的值都已经被处理完毕后, 将执行到这一行 | |
| wgResponse.Done() | |
| }() | |
| for _, url := range urls { | |
| // 计数器+1 | |
| wg.Add(1) | |
| limiter <- true | |
| // 这里在启动goroutine时, 将用来收集结果的局部变量channel也传递进去 | |
| go httpGet(url,responseChannel, limiter, wg) | |
| } | |
| // 等待所以协程执行完毕 | |
| wg.Wait() // 当计数器为0时, 不再阻塞 | |
| fmt.Println("所有协程已执行完毕") | |
| // 关闭接收结果channel | |
| close(responseChannel) | |
| // 等待wgResponse的计数器归零 | |
| wgResponse.Wait() | |
| // 返回聚合后结果 | |
| return result | |
| } | |
| func main() { | |
| urls := []int{1,2,3,4,5,6,7,8,9,10} | |
| result := collect(urls) | |
| fmt.Println(result) | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment