博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go语言学习笔记-通道
阅读量:6549 次
发布时间:2019-06-24

本文共 2160 字,大约阅读时间需要 7 分钟。

之前学习的Goroutine可以让我们便捷的进行并行编程,而通道则可以让我们方便的实现Goroutine之间的通信。

一个简单的通道使用示例:

package main

import (
    "fmt"
    "time"
)
func slowFunc(c chan string) {
    time.Sleep(time.Second * 2)
    c <- "slowFunc() finished"
}
func main() {
    c := make(chan string)
    go slowFunc(c)
    msg := <-c
    fmt.Println(msg)
}

这个Go程序中,我们定义了一个传送消息类型为string的通道,我们还开启了一个Goroutine,主函数执行到msg := <-c时会阻塞,直到收到一条从通道c发来的消息为止。

 

通道还具有缓冲的功能,下面的程序我们使用了一个缓冲区大小为2的通道:

package main

import (
    "fmt"
    "time"
)
func receiver(c chan string) {
    for msg := range c {
        fmt.Println(msg)
    }
}
func main() {
    messages := make(chan string, 2)
    messages <- "hello"
    messages <- "world"
    close(messages)
    fmt.Println("Pushed two messages onto channel with no receivers")
    time.Sleep(time.Second * 1)
    receiver(messages)
}

运行该程序可知,即使调用close()关闭了通道后,已发送的消息依然保留在通道的缓冲中,只是无法再向通道发送消息。在receiver()函数中我们接收了通道中的所有消息并打印。

 

在实际项目中,我们很可能需要使用一个通道不断地传送数据,借助for语句我们可以实现这一点:

package main

import (
    "fmt"
    "time"
)
func pinger(c chan string) {
    t := time.NewTicker(1 * time.Second)
    for {
        c <- "ping"
        <-t.C
    }
}
func main() {
    messages := make(chan string)
    go pinger(messages)
    for {
        msg := <-messages
        fmt.Println(msg)
    }
}

此例为不断地通过通道发送和接收数据。

 

除此之外,还有select语句,它类似于switch语句,会执行最先收到消息的通道的case语句

package main

import (
    "fmt"
    "time"
)
func ping1(c chan string) {
    time.Sleep(time.Second * 1)
    c <- "ping on channel1"
}
func ping2(c chan string) {
    time.Sleep(time.Second * 2)
    c <- "ping on channel2"
}
func main() {
    channel1 := make(chan string)
    channel2 := make(chan string)
    go ping1(channel1)
    go ping2(channel2)
    select {
    case msg1 := <-channel1:
        fmt.Println("received", msg1)
    case msg2 := <-channel2:
        fmt.Println("received", msg2)
    }
}

从此程序可知,接收到一条消息后,select语句将不再阻塞。

 

如果不想select语句无限的阻塞,可以专门使用一个通道来接收退出消息,称之为退出通道,如下:

package main

import (
    "fmt"
    "time"
)
func sender(c chan string) {
    for {
        c <- "I'm sending a message"
        time.Sleep(time.Second * 1)
    }
}
func stopFunc(c chan bool) {
    time.Sleep(time.Second * 2)
    fmt.Println("Time's up!")
    c <- true
}
func main() {
    messages := make(chan string)
    stop := make(chan bool)
    go sender(messages)
    go stopFunc(stop)
    for {
        select {
        case <- stop:
            return
        case msg:= <- messages:
            fmt.Println(msg)
        }
    }
}

 

转载于:https://www.cnblogs.com/paralysis/p/10669747.html

你可能感兴趣的文章
网络工程师之路怎么走?
查看>>
go语言unix域套接字发送udp报文
查看>>
2.并发和并行
查看>>
OpenGL学习(二)用户与交互
查看>>
神奇的代码-常见错误代码注意点
查看>>
[直播一揽子]编码构思和套路
查看>>
[直播一揽子]x264参数的解释
查看>>
iOS学习之Objective-C 2.0 运行时系统编程
查看>>
Exchange2007-Exchange2010升级-06 数据库高可用组的创建
查看>>
phpHiveAdmin是如何通过Hive/Hadoop工作的
查看>>
双向链表内结点的删除(4)
查看>>
项目总结
查看>>
JSON字符串转成对象
查看>>
SaltStack 中ZMQ升级
查看>>
exchange 2013 提示“HTTP 500内部服务器错误”
查看>>
Linux运维学习笔记之一:运维的原则和学习方法
查看>>
怎样使用原型设计中的组件样式功能
查看>>
python threading
查看>>
谷安天下2013年6月CISA考前辅导 第一季
查看>>
ARM程序规范
查看>>