为了账号安全,请及时绑定邮箱和手机立即绑定

Golang中的channel代码示例----无缓冲、有缓冲、range、close

标签:
Go


// code_043_channel_unbuffered project main.go

package main

import (

    "fmt"

    "time"

)

func main() {

    c := make(chan int, 0) //无缓冲的通道

    //内置函数 len 返回未被读取的缓冲元素数量, cap 返回缓冲区大小

    fmt.Printf("len(c)=%d, cap(c)=%d\n", len(c), cap(c))

    go func() {

        defer fmt.Println("子协程结束")

        for i := 0; i < 3; i++ {

            fmt.Printf("子协程正在运行[%d]: len(c)=%d, cap(c)=%d\n", i, len(c), cap(c))

            c <- i //备注:如果在上面的话, 不会执行最后一次Printf

        }

    }()

    time.Sleep(2 * time.Second) //延时2s

    for i := 0; i < 3; i++ {

        num := <-c //从c中接收数据,并赋值给num

        fmt.Println("num = ", num)

    }

    fmt.Println("main协程结束")

}

// code_044_channel_buffered project main.go

package main

import (

    "fmt"

    "time"

)

//有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道。

//只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。

//有缓冲的通道和无缓冲的通道之间的不同:

//1)无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换;

//2)有缓冲的通道没有这种保证

func main() {

    c := make(chan int, 3)

    fmt.Printf("len(c)=%d, cap(c)=%d\n", len(c), cap(c))

    go func() {

        defer fmt.Println("子协程结束")

        for i := 0; i < 3; i++ {

            c <- i

            fmt.Printf("子协程正在运行[%d]: len(c)=%d, cap(c)=%d\n", i, len(c), cap(c))

        }

    }()

    time.Sleep(2 * time.Second)

    for i := 0; i < 3; i++ {

        num := <-c

        fmt.Println("num=", num)

    }

    fmt.Println("main协程结束")

}

// code_045_channel_range_close project main.go

package main

import (

    "fmt"

)

//注意点:

//channel不像文件一样需要经常去关闭,只有当你确实没有任何发送数据了,或者你想显式的结束range循环之类的,才去关闭channel;

//关闭channel后,无法向channel 再发送数据(引发 panic 错误后导致接收立即返回零值);

//关闭channel后,可以继续向channel接收数据;

//  对于nil channel,无论收发都会被阻塞。

/* close()的使用

func main() {

    c := make(chan int)

    go func() {

        for i := 0; i < 5; i++ {

            c <- i

        }

        //把 close(c) 注释掉,程序会一直阻塞在 if data, ok := <-c; ok 那一行

        //注释后报错“死锁”:fatal error: all goroutines are asleep - deadlock!

        close(c)

    }()

    for {

        //ok为true说明channel没有关闭,为false说明管道已经关闭

        if data, ok := <-c; ok {

            fmt.Println(data)

        } else {

            break

        }

    }

    fmt.Println("Finished")

}

*/

func main() {

    c := make(chan int)

    go func() {

        for i := 0; i < 5; i++ {

            c <- i

        }

        close(c)

    }()

    for data := range c {

        fmt.Println(data)

    }

    fmt.Println("Finished")

}

©著作权归作者所有:来自51CTO博客作者ck_god的原创作品,如需转载,请注明出处,否则将追究法律责任


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消