分享
golang channel 总结
cqvoip · · 1930 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
1、未初始化的channel读,阻塞
package main
import (
"fmt"
"time"
)
func main() {
var ch chan int
go check(ch)
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
}
func check(ch chan int) {
select {
case i := <-ch:
fmt.Println("read ch data=", i)
}
fmt.Println("check runtime exit")
}
2、未初始化的channel写,阻塞
package main
import (
"fmt"
"time"
)
func main() {
go func() {
for {
time.Sleep(time.Second * 1)
}
}()
var ch chan int
go check(ch)
time.Sleep(time.Second * 1)
fmt.Println("xxxxxxx")
<-ch
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
}
func check(ch chan int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("recover ", r)
}
}()
ch <- 1
fmt.Println("check runtime exit")
}
3、向已关闭的channel读,返回默认值和false
package main
import (
"fmt"
"time"
)
func main() {
var ch chan int
ch = make(chan int)
go check(ch)
fmt.Println("main runtime end")
close(ch)
time.Sleep(time.Second * 1000)
}
func check(ch chan int) {
select {
case i, k := <-ch:
fmt.Println("read ch data=", i, " k=", k) //k=false i=0
}
fmt.Println("check runtime exit")
}
4、向已关闭的channel写,panic
package main
import (
"fmt"
"time"
)
func main() {
var ch chan int
ch = make(chan int)
close(ch)
ch <- 1
fmt.Println("end")
time.Sleep(time.Second * 1000)
}
5、time.Timer Stop后,time.Timer.C将阻塞
package main
import (
"fmt"
"time"
)
func main() {
tm := time.NewTimer(time.Second * 3)
go check(tm)
time.Sleep(time.Second * 1)
tm.Stop()
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
}
func check(tm *time.Timer) {
select {
case i, k := <-tm.C: //阻塞
fmt.Println("read ch data=", i, " k=", k)
}
fmt.Println("check runtime exit")
}
6、无缓冲与有缓冲channel的重要区别,无缓冲的channel在写时必须有读携程,否则会阻塞。如下例子,超时后向exit发数据会阻塞,因为只有一个携程,此时没有其他携程对exit进行读。【踩了坑才理解深刻】
package main
import (
"fmt"
"time"
)
func main() {
exit := make(chan int)
go check(exit)
time.Sleep(time.Second * 100)
}
func check(exit chan int) {
tm := time.NewTimer(time.Second * 3)
select {
case <-exit:
fmt.Println("exit")
case <-tm.C:
fmt.Println("time out")
exit <- 1
fmt.Println("exit <- 1 ok")
}
fmt.Println("check runtime exit")
}
例子2:
package main
import (
"fmt"
"time"
)
func main() {
go func() {
for {
time.Sleep(time.Second * 1)
}
}()
exit := make(chan int, 1)
exit <- 1
fmt.Println("end")
}
这里会直接END,如果exit:=make(chan int),会阻塞在exit<-1
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信1930 次点击
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
1、未初始化的channel读,阻塞
package main
import (
"fmt"
"time"
)
func main() {
var ch chan int
go check(ch)
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
}
func check(ch chan int) {
select {
case i := <-ch:
fmt.Println("read ch data=", i)
}
fmt.Println("check runtime exit")
}
2、未初始化的channel写,阻塞
package main
import (
"fmt"
"time"
)
func main() {
go func() {
for {
time.Sleep(time.Second * 1)
}
}()
var ch chan int
go check(ch)
time.Sleep(time.Second * 1)
fmt.Println("xxxxxxx")
<-ch
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
}
func check(ch chan int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("recover ", r)
}
}()
ch <- 1
fmt.Println("check runtime exit")
}
3、向已关闭的channel读,返回默认值和false
package main
import (
"fmt"
"time"
)
func main() {
var ch chan int
ch = make(chan int)
go check(ch)
fmt.Println("main runtime end")
close(ch)
time.Sleep(time.Second * 1000)
}
func check(ch chan int) {
select {
case i, k := <-ch:
fmt.Println("read ch data=", i, " k=", k) //k=false i=0
}
fmt.Println("check runtime exit")
}
4、向已关闭的channel写,panic
package main
import (
"fmt"
"time"
)
func main() {
var ch chan int
ch = make(chan int)
close(ch)
ch <- 1
fmt.Println("end")
time.Sleep(time.Second * 1000)
}
5、time.Timer Stop后,time.Timer.C将阻塞
package main
import (
"fmt"
"time"
)
func main() {
tm := time.NewTimer(time.Second * 3)
go check(tm)
time.Sleep(time.Second * 1)
tm.Stop()
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
}
func check(tm *time.Timer) {
select {
case i, k := <-tm.C: //阻塞
fmt.Println("read ch data=", i, " k=", k)
}
fmt.Println("check runtime exit")
}
6、无缓冲与有缓冲channel的重要区别,无缓冲的channel在写时必须有读携程,否则会阻塞。如下例子,超时后向exit发数据会阻塞,因为只有一个携程,此时没有其他携程对exit进行读。【踩了坑才理解深刻】
package main
import (
"fmt"
"time"
)
func main() {
exit := make(chan int)
go check(exit)
time.Sleep(time.Second * 100)
}
func check(exit chan int) {
tm := time.NewTimer(time.Second * 3)
select {
case <-exit:
fmt.Println("exit")
case <-tm.C:
fmt.Println("time out")
exit <- 1
fmt.Println("exit <- 1 ok")
}
fmt.Println("check runtime exit")
}
例子2:
package main
import (
"fmt"
"time"
)
func main() {
go func() {
for {
time.Sleep(time.Second * 1)
}
}()
exit := make(chan int, 1)
exit <- 1
fmt.Println("end")
}
这里会直接END,如果exit:=make(chan int),会阻塞在exit<-1