Go中go与channel的简单例子的疑惑,望高人指点

Vampire · 2015-03-19 09:24:44 · 2134 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2015-03-19 09:24:44 的主题,其中的信息可能已经有所发展或是发生改变。

最近自学Go语言,看到go并发和channel通信了,还没深入channel通信,就先写个简单例子了解一下,代码如下:

package main

import "fmt"

func Add(index int, ch chan int) {

    fmt.Println(index, ":Before Counting")
    ch <- 1
    fmt.Println(index, ":After Counting")
}

func main() {

    chs := make([]chan int, 10)

    for i := 0; i < 10; i++ {
        chs[i] = make(chan int)
        go Add(i, chs[i])
    }

    for i, ch := range chs {
        fmt.Println("第", i, "个ch输出", <-ch)
    }
}

运行结果如下:

0 :Before Counting
0 :After Counting
1 :Before Counting
2 :Before Counting
3 :Before Counting
4 :Before Counting
5 :Before Counting
6 :Before Counting
7 :Before Counting
8 :Before Counting
9 :Before Counting
第 0 个ch输出 1
第 1 个ch输出 1
第 2 个ch输出 1
第 3 个ch输出 1
第 4 个ch输出 1
第 5 个ch输出 1
第 6 个ch输出 1
第 7 个ch输出 1
第 8 个ch输出 1
第 9 个ch输出 1

请问:为什么第一个goroutine的before和after都输出了?为什么后面的都只输出了before,而且没有after的输出?


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

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

2134 次点击  
加入收藏 微博
14 回复  |  直到 2015-03-21 00:47:57
zeast
zeast · #1 · 10年之前

协程还没输出 after 的时候主程序就退出了,在代码末尾加上 time.Sleep(5 * time.Second) 就可以看到了,不过正确的方法还是加上同步,参考 http://golang.org/pkg/sync/#WaitGroup

Vampire
Vampire · #2 · 10年之前
zeastzeast #1 回复

协程还没输出 after 的时候主程序就退出了,在代码末尾加上 time.Sleep(5 * time.Second) 就可以看到了,不过正确的方法还是加上同步,参考 http://golang.org/pkg/sync/#WaitGroup

您好,能结合上面的例子给具体修改一下吗?还有,为什么第一个goroutine的after输出了?不是应该阻塞的吗?

ckrissun
ckrissun · #3 · 10年之前

把 chs[i] = make(chan int),改成 chs[i] = make(chan int,1) 再看看结果

Vampire
Vampire · #4 · 10年之前
ckrissunckrissun #3 回复

把 chs[i] = make(chan int),改成 chs[i] = make(chan int,1) 再看看结果

这样就变成顺序before、after的依次输出了,能否对这整个的流程做个详细的说明啊?并不是很理解这里为什么会这样输出

ckrissun
ckrissun · #5 · 10年之前
VampireVampire #4 回复

#3楼 @ckrissun 这样就变成顺序before、after的依次输出了,能否对这整个的流程做个详细的说明啊?并不是很理解这里为什么会这样输出

Vampire
Vampire · #6 · 10年之前
ckrissunckrissun #5 回复

#4楼 @Vampire http://golang.org/ref/mem#tmp_7

英文不太好,跪求简单的叙述一下

ckrissun
ckrissun · #7 · 10年之前
VampireVampire #6 回复

#5楼 @ckrissun 英文不太好,跪求简单的叙述一下

发现了个中文版 http://www.hellogcc.org/effective_go.html#channels 其实就是 不带缓冲区和带缓冲区channel之间的区别

qkb_75_go
qkb_75_go · #8 · 10年之前

你的结果是正常的,没有异常:

1)第一个goroutine的before和after都输出了, 那是凑巧了,也可能不输出 after没有定论; 当然也可能第二个goroutine的before和after都输出了,谁知道。
2)后面的都只输出了before,而且没有after,那是因为 main()退出了。
polaris
polaris · #9 · 10年之前
VampireVampire #6 回复

#5楼 @ckrissun 英文不太好,跪求简单的叙述一下

Vampire
Vampire · #10 · 10年之前
ckrissunckrissun #7 回复

#6楼 @Vampire 发现了个中文版 http://www.hellogcc.org/effective_go.html#channels 其实就是 不带缓冲区和带缓冲区channel之间的区别

谢谢你

Vampire
Vampire · #11 · 10年之前
qkb_75_goqkb_75_go #8 回复

你的结果是正常的,没有异常: 1)第一个goroutine的before和after都输出了, 那是凑巧了,也可能不输出 after没有定论; 当然也可能第二个goroutine的before和after都输出了,谁知道。 2)后面的都只输出了before,而且没有after,那是因为 main()退出了。

谢谢你的回答,可能这里我还得再理解一下,多看看书了,不过还是非常感谢你

Vampire
Vampire · #12 · 10年之前
polarispolaris #9 回复

#6楼 @Vampire 本站就有中文版文档: http://docscn.studygolang.com/doc/effective_go.html#信道

嗯,知道了,谢谢你的帮助

ckrissun
ckrissun · #13 · 10年之前
VampireVampire #12 回复

#9楼 @polaris 嗯,知道了,谢谢你的帮助

不带缓冲区的channel: ch <- 1时,只有ch里面的值被另外的goroutine接收后,才能执行ch<-1 的下一行代码;带缓冲区的channle: ch<-1时,若ch未满,则继续执行下去。。。否则阻塞住

Vampire
Vampire · #14 · 10年之前
ckrissunckrissun #13 回复

#12楼 @Vampire 不带缓冲区的channel: ch <- 1时,只有ch里面的值被另外的goroutine接收后,才能执行ch<-1 的下一行代码;带缓冲区的channle: ch<-1时,若ch未满,则继续执行下去。。。否则阻塞住

嗯,这个解释太通俗易懂了,呵呵,谢谢

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传