当前位置: 首页> 科技> 数码 > 二十五、go语言的通道

二十五、go语言的通道

时间:2025/9/13 19:05:51来源:https://blog.csdn.net/qq_34077993/article/details/141555258 浏览次数:0次

目录

一、收发通信

二、将通道作为参数传递(读、写、读写)

三、select

1、先收到消息的先执行

2、一直没有收到消息退出通道

3、不知道何时退出情况下退出通道


go语言中的goroutine可以看成线程,但是又不能看成和其它语言一样的线程,因为在go语言中,goroutine之间的通信和其它语言不一样,例如如果在java中多条线程访问一个内存中数据在访问前需要进行加锁避免其它线程进入进行修改,本质上是通过共享了内存进行通信。而在go中是不一样的,在go中是“不要通过共享内存进行通信,而是通过通信来共享内存”

一、收发通信

import ("fmt""time"
)func receiver(c chan string) {for msg := range c {fmt.Println(msg)}
}
func main() {message := make(chan string, 2)message <- "hello"message <- "world"close(message)fmt.Println("push two message to channel")time.Sleep(time.Second * 2)receiver(message)
}

结果在2s中后输出

hello
world
解释

上述案例中 receiver函数接收了一个通道为string值的参数,并且进行循环输出

main方法中,mak(chan string,2)声明创建长度为2的通道

message <- "" 往通道内存入消息

close关闭通道意味着不可以再通过这个通道发送消息

调用receiver并传入message参数

二、将通道作为参数传递(读、写、读写)

在参数中<-在chan左边意味着可读,在右边意味着可写,没有意味着可读可写

func showReader(c <-chan string) {msg := <-cfmt.Println(msg)
}
func showWriter(c chan<- string) {c <- "hello world"
}func showReaderAndWriter(c chan string) {msg := <-cfmt.Println(msg)c <- "hello world"
}

在reader函数中,c是什么我们只能输出什么

在writer函数中,c是什么我们可以修改

在readerAndWriter函数中,c是什么我们可以输出什么也可以指定c是什么

三、select

1、先收到消息的先执行
func ping(c chan int) {time.Sleep(time.Second * 3)c <- 1
}
func ping2(c chan<- int) {time.Sleep(time.Second * 2)c <- 2
}
func main() {channel := make(chan int)channel2 := make(chan int)go ping(channel)go ping2(channel2)select {case msg := <-channel:fmt.Println(msg)case msg := <-channel2:fmt.Println(msg)}
}

结果:

2

解释L

在select中最先收到消息的执行后续代码,当创建两个ping方法时,ping sleep了3秒,ping2 sleep了2秒所以先执行了ping2

2、一直没有收到消息退出通道

当一直没有收到消息可以使用case <-time.After(time.Second * 3):

import ("fmt""time"
)func ping(c chan int) {time.Sleep(time.Second * 5)c <- 1
}
func ping2(c chan<- int) {time.Sleep(time.Second * 4)c <- 2
}
func main() {channel := make(chan int)channel2 := make(chan int)go ping(channel)go ping2(channel2)select {case msg := <-channel:fmt.Println(msg)case msg := <-channel2:fmt.Println(msg)case <-time.After(time.Second * 3):fmt.Println("timeout")}}
3、不知道何时退出情况下退出通道
import ("fmt""time"
)func sender(c chan string) {t := time.NewTicker(1 * time.Second)for {c <- "hello world"<-t.C}
}
func main() {messages := make(chan string)stop := make(chan bool)go sender(messages)go func() {time.Sleep(2 * time.Second)fmt.Println("time up")stop <- true}()for {select {case status := <-stop:fmt.Println(status)returncase msg := <-messages:fmt.Println(msg)}}
}

结果:

hello world
hello world
hello world
time up
true


解释:

 创建了一个sender方法,使用time.NewTicker(1 * time.Second),每一秒往通道中传递一次值

t := time.NewTicker(1 * time.Second)
for {c <- "hello world"<-t.C
}

在for循环中执行 

case msg := <-messages:fmt.Println(msg)

在接收到消息后执行,那么如果在没有手动终止程序的话就会一直执行

所以创建一个退出通道,当接收到true值时进行return,退出通道

case status := <-stop:fmt.Println(status)return

在同时并发执行一个func,并让这个程序sleep 2秒后,在给通道stop值为true

go func() {time.Sleep(2 * time.Second)fmt.Println("time up")stop <- true}()

所以在第一次并发调用

go sender(messages)

执行了一次

fmt.Println(msg)

此时func开始sleep 2秒,所以又执行了两次,当stop为ture时进行了return退出了通道

关键字:二十五、go语言的通道

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: