美文网首页
Go中的chan

Go中的chan

作者: 浑浑噩噩_邋邋遢遢 | 来源:发表于2017-08-01 10:23 被阅读0次

go中的chan是动态的,因此千万不要把chan想象成slice切片类型的数据。

  • 只要chan不close可以永远发送数据和接受数据
  • 如果channel里面没有数据,接收方会阻塞
  • 如果没有人正在等待channel的数据,发送方会阻塞
  • 从一个close的channel取数据永远不会阻塞, 同时获取的数据为默认值(与定义的chan类型一致)

下面这段代码,会解释上面这四个chan特点:

package main

import (
    "net/http"
    "fmt"
    "sync"
)

func printUrl(url string) {
    res, err := http.Get(url)
    if err != nil{
        fmt.Println(err)
        return
    }
    defer res.Body.Close()
    fmt.Println(url, res.Status)


}

func work2(urls chan string, wg *sync.WaitGroup)  {
    for{
        url, ok := <- urls      // 判断取出的数据是否为false 说明chan关闭
        if !ok{
            break
        }
        printUrl(url)
    }
    wg.Done()

}
func work(urls chan string, wg *sync.WaitGroup) {

    for i := range urls{        // chan中有一条数据会循环一次知道chan关闭
        printUrl(i)
    }
    wg.Done()

}

func main() {
    url := "http://www.baidu.com"
    var u []string

    for i :=0; i<15;i ++{   // 先生成一些数据
        u = append(u, url)
    }
    wg := new(sync.WaitGroup)   // 利用WaitGroup的方式协程同步
    //wg.Add(5)                 // 可一次性添加任务总数
    urlchann := make(chan string)

    for i:=0; i<5 ;i++  {
        wg.Add(1)           // 也可每创建一个任务 添加一个标识
        go work(urlchann, wg)
    }

    for _, line := range u{
        urlchann <- line        // 将任务需要的数据添加到队列中
    }
    close(urlchann)         // 关闭chan
    wg.Wait()
}

代码中的Work与Work2效果是一样的。

特别要记住一点,chan的大小是动态的,不要理解为像slice那样的固定长度。

相关文章

网友评论

      本文标题:Go中的chan

      本文链接:https://www.haomeiwen.com/subject/kbtjlxtx.html