channel
多channel合并为一个
func merge(cs ...<-chan int) <-chan int {
var wg sync.WaitGroup//创建一个用于同步的waitGroup
out := make(chan int)
output := func(c <- chan int) {
for n := range c {
out <- n
}
wg.Done()//做完一个作业
}
wg.Add(len(cs))//做完len(cs)个Done就释放
for _, c := range cs {
go output(c)
}
go func() {
wg.Wait()//等待add添加的作业全部做完
close(out)
}()
return out
}
context包
有如下4种生存子context的方法
context.WithValue()//设置一个不可改变的值
context.WithDeadline()//用于设置DDL,到达预设时间后ctx.Err()方法返回错误信息
context.WithTimeout()//用于判断超时,到达预设的时间时ctx.Done()方法返回一个空值struct{}供channel获取
context.WithCancel()//官方范例:用于控制go routine的退出释放
context.WithValue(context.Background(), 1, "test")//根据父context,生成一个子节点
context.WithValue()例子
ctx2 := context.WithValue(context.Background(), 1, "test")
fmt.Println(ctx2.Value(1))
context.WithDeadline()例子
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(50 * time.Millisecond))
defer cancel()
time.Sleep(51 * time.Millisecond)
fmt.Println(ctx.Err())
context.WithTimeout()例子:访问baidu,如果超过WithTimeout设置的时间,则ctx.Done()返回struct{}
ctx,cancel := context.WithTimeout(context.Background(),2*time.Second)
defer cancel()
tr := &http.Transport{}
client := &http.Client{Transport:tr}
c := make(chan Result,1)
req,err := http.NewRequest("GET","http://www.baidu.com",nil)
if err != nil{
fmt.Println("http request failed,err:",err)
return
}
// 如果请求成功了会将数据存入到管道中
go func(){
resp,err := client.Do(req)
pack := Result{resp,err}
c <- pack
}()
select{
case <- ctx.Done():
tr.CancelRequest(req)
fmt.Println("timeout!")
case res := <-c:
defer res.r.Body.Close()
out,_:= ioutil.ReadAll(res.r.Body)
fmt.Printf("server response:%s",out)
}
return
context.WithCancel()例子