简明笔记:Goroutine &channel

faceNL · · 614 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

## 简明笔记:Goroutine &channel > f() // call f();wait for it to return > > go f() //create a new goroutine that calls f();don't wait ## Goroutine 调用普通函数,等待函数返回值返回。 创建一个goroutine,调用函数,不会等待其函数返回值返回。 ```go package main import ( "fmt" ) func helloworld(){ fmt.Println("goroutine...") } func main() { go helloworld() //在函数面前加上关键字Go,创建一个goroutine。 fmt.Println("执行结束...") } 输出结果: 执行结束 ``` 执行速度很快,这里看不到helloworld()函数的输出,所以验证了我上面所说的。don't wait ```go package main import ( "fmt" "time" ) func fun(){ for i:=0;i<5;i++{ time.Sleep(500*time.Millisecond) // 等待0.5秒 fmt.Println(i) } } func main() { go fun() time.Sleep(1*time.Second) // 等待1秒 fmt.Println("执行结束...") } 输出结果: 0 1 执行结束... ``` 多个goroutine 并行 ```go func fun(){ for i:=0;i<5;i++{ time.Sleep(500*time.Millisecond) // 等待0.5秒 fmt.Println(i) } } func run(){ fmt.Println("run function") } func main() { go fun() go run() time.Sleep(2*time.Second) // 等待2秒 fmt.Println("执行结束...") } 输出结果: run function 0 1 2 执行结束... ``` ## 通道(channel) ```go var ch chan int // 声明一个channel ch :=make(chan int) //定义一个channel ch <-value //向ch写入数据。通常会导致程序阻塞,知道有其它goroutine从这个channel中读取数据 value := <- ch //读取ch的数据。如果channel之前没有写入数据,那么从channel中读取数据也会导致阻塞,直到channel被写入数据为止。 ``` 举个栗子 ```go var ch chan int //定义为全局 func ready(w string){ time.Sleep(1*time.Second) fmt.Println(w,"is ready") ch <- 1 //发送1到channel ch } func main() { ch = make(chan int) go ready("Potato") fmt.Println("I'm waiting") <-ch } 输出结果: I'm waiting Potato is ready ``` ### 指定channel(通道)缓存 #### 无指定缓存大小 ```go package main import ( "fmt" "time" ) func main() { c := make(chan int) go send(c) go recv(c) time.Sleep(3 * time.Second) close(c) } func send(c chan <- int){ for i:=0;i<10;i++{ fmt.Println("发送 >>>",i) c <- i } } func recv(c <-chan int){ for i:=range c{ fmt.Println("接收 <<<",i) } } 输出结果: 发送 >>> 0 发送 >>> 1 接收 <<< 0 接收 <<< 1 发送 >>> 2 发送 >>> 3 接收 <<< 2 接收 <<< 3 发送 >>> 4 接收 <<< 4 ``` 没有指定缓存的通道,只尊顺一进一出的原则(默认是无缓存,即同步), 往channel 发送数据后,这个数据如果没有取走,channel是阻塞的,也就是不能继续向channel 里面发送数据。因为上面代码中,我们没有指定channel 缓冲区的大小,默认是阻塞的。 ### 带有缓存的channel ```go func main() { c := make(chan int,10) go send(c) go recv(c) time.Sleep(3 * time.Second) close(c) } func send(c chan <- int){ for i:=0;i<5;i++{ fmt.Println("发送 >>>",i) c <- i } } func recv(c <-chan int){ for i:=range c{ fmt.Println("接收 <<<",i) } } 输出: 发送 >>> 0 发送 >>> 1 发送 >>> 2 发送 >>> 3 发送 >>> 4 接收 <<< 0 接收 <<< 1 接收 <<< 2 接收 <<< 3 接收 <<< 4 ``` 有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道(即异步)。 通道会阻塞发送和接收动 作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区 容纳被发送的值时,发送动作才会阻塞。 > 关注公众号:面向奶酪 获取最新文章

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

614 次点击  
加入收藏 微博
5 回复  |  直到 2019-05-08 09:45:33
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传