我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Go中怎么使用channel

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Go中怎么使用channel

这篇文章将为大家详细讲解有关Go中怎么使用channel,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、使用channel等待任务结束

使用案例还是在第一篇的第二节中写的代码,不过这里只需要一段即可。

package mainimport ("fmt""time")func createWorker(id int) chan<- int {c := make(chan int)go worker(id, c)return c}func worker(id int, c chan int) {for n := range c {fmt.Printf("Worker %d receive %c\n", id, n)}}func channelDemo() {var channels [10]chan<- intfor i := 0; i < 10; i++ {channels[i] = createWorker(i)}for i := 0; i < 10; i++ {channels[i] <- 'a' + i}for i := 0; i < 10; i++ {channels[i] <- 'A' + i}time.Sleep(time.Millisecond)}func main() {channelDemo()}

这里咔咔将原始源码放在这里,如果你想跟着文章的节奏走,可以放到你的编辑器中进行操作。

那这段代码的问题是在哪里呢?

可以看到在channelDemo函数最后使用了一个sleep,这玩意在程序中可不能乱用。

说到这里给大家讲一个小故事,咔咔之前在网上看到一段就是加了sleep的代码。

然后一个新手程序员不明白为什么要加这个sleep,然后问题项目经理,项目经理说老板发现程序慢之后会找咱们优化,每一次优化把这个sleep的时间缩短即可。让老板感觉到我们在做事情。

新手就是新手对不懂得代码都会进行标注,然后就写了一句注释“项目经理要求这里运行缓慢,老板让优化时,代码得到明显的速度提升”。

这句话很不巧的是被老板给看见了,老板不认识代码,但文字还是认识的哈!于是,项目经理下马。

所以说对于sleep大多数都是一个测试状态,坚决不会出现在线上的,所以呢?就要解决代码中的这个sleep。

那么大家在回忆一下,在这里为什么要加sleep呢?

发送到channel的数据都是在另一个goroutine中进行并发打印的,并发打印就会出现问题,因为根本不会知道什么时候才打印完毕。

所以说这个sleep就会为了应对这个不知道什么时候打印完的问题,给个1毫秒让进行打印。

这种做法是非常不好的,接下来看看使用一种新的方式来解决这个问题。

以下代码是修改完的代码。

package mainimport ("fmt")type worker struct {in   chan intdone chan bool}func createWorker(id int) worker {w := worker{in:   make(chan int),done: make(chan bool),}go doWorker(id, w.in, w.done)return w}func doWorker(id int, c chan int, done chan bool) {for n := range c {fmt.Printf("Worker %d receive %c\n", id, n)done <- true}}func channelDemo() {var workers [10]workerfor i := 0; i < 10; i++ {workers[i] = createWorker(i)}for i := 0; i < 10; i++ {workers[i].in <- 'a' + i<-workers[i].done}for i := 0; i < 10; i++ {workers[i].in <- 'A' + i<-workers[i].done}}func main() {channelDemo()}

将这些代码复制到你的本地,然后再来看一下都做了什么改动。

  • 首先为了参数传递方便,建立了一个结构体worker

  • 并且把之前的worker方法改为了doWorker

  • 这个时候createWorker方法返回值就不能是之前的channel了,而是创建的结构体worker

  • 然后在createWorker方法里边把channel全部创建好。并且使用结构体给doWorker传递参数。

  • 最终返回的就是结构体。

  • 最后一步就是给channelDemo方法里边发送数据的俩个循环里边接收一下workers[i]的值即可。

看一下打印结果

Go中怎么使用channel

是不是有点懵,这怎么成有序的了,如果是并行的那还有必要开那10个worker,直接按照顺序打印就好了。

现在就来解决这个问题,我不希望发一个任务然后等它结束。

最好的就是把他们全部发出去,等待它们全部结束再退出来。

代码实现如下

package mainimport ("fmt")type worker struct {in   chan intdone chan bool}func createWorker(id int) worker {w := worker{in:   make(chan int),done: make(chan bool),}go doWorker(id, w.in, w.done)return w}func doWorker(id int, c chan int, done chan bool) {for n := range c {fmt.Printf("Worker %d receive %c\n", id, n)done <- true}}func channelDemo() {var workers [10]workerfor i := 0; i < 10; i++ {workers[i] = createWorker(i)}for i, worker := range workers {worker.in <- 'a' + i}for i, worker := range workers {worker.in <- 'A' + i}for _, worker := range workers {<-worker.done<-worker.done}}func main() {channelDemo()}

在这里再进行打印看一下结果,你会发现代码是有问题的。

Go中怎么使用channel

为什么将小写的字母打印出来,而打印大写字母时发生了报错呢?

这个就要追溯到代码中了,因为我们代码本身就写的有问题。

还是回归到本文长谈的一个问题,那就是对于所有的channel有发送数据就必须有接收数据,如果没有接收数据就会报错。

那么在代码中你能看出是那块只进行了发送数据,而没有接收数据吗?

Go中怎么使用channel

这个问题就是当给channel把小写字母发送了后,就会到进入到doWorker方法,然后给done发送了一个true,但是接收done的方法是在后面,也就是说第二个发送大写字母时,就会发送循环的等待。

解决这个问题也很简单,我们只需要并发的发送done即可。

Go中怎么使用channel

看到打印结果也是正确的。

本文给的这个案例在一般项目中是不会出现的,所以说不用纠结于此。

给的案例就是为了让大家更熟悉channel的机制而已。

对于这个解决方法还有一个方案解决,请看代码。

Go中怎么使用channel

将代码还原到之前,然后在每一个发送字母的下面循环接收done即可。

对于这种多任务等待方式在go中有一个库是可以来做这个事情,接下来看一下。

sync.WaitGroup的用法

对于sync.WaitGroup的用法咔咔就不一一介绍了,简单的看一下源码的实现即可。

package mainimport ("fmt""sync")type worker struct {in chan intwg *sync.WaitGroup}func createWorker(id int, wg *sync.WaitGroup) worker {w := worker{in: make(chan int),wg: wg,}go doWorker(id, w.in, wg)return w}func doWorker(id int, c chan int, wg *sync.WaitGroup) {for n := range c {fmt.Printf("Worker %d receive %c\n", id, n)wg.Done()}}func channelDemo() {var wg sync.WaitGroupvar workers [10]workerfor i := 0; i < 10; i++ {workers[i] = createWorker(i, &wg)}// 添加20个任务wg.Add(20)for i, worker := range workers {worker.in <- 'a' + i}for i, worker := range workers {worker.in <- 'A' + i}wg.Wait()}func main() {channelDemo()}

这份源码也是非常简单的,具体修改得东西咔咔简单介绍一下。

  • 首先取消了channelDemo这个方法中关于done的channel。

  • 使用了sync.WaitGroup,并且给createWorker方法传递sync.WaitGroup

  • createWorker方法使用了 worker的结构体。

  • 所以要先修改worker结构体,将之前的done改为wg *sync.WaitGroup即可

  • 这样就可以直接用结构体的数据。

  • 接着在doWorker方法中把最后一个参数done改为wg *sync.WaitGroup

  • 将方法中的done改为wg.Done()

  • 最后一步就是回到函数channelDemo中把任务数添加进去,然后在代码最后添加一个等待即可。

关于这块的内容先知道这么用即可,咔咔后期会慢慢的补充并且深入。

抽象代码

这块的代码看起来不是那么的完美的,接下来抽象一下。

Go中怎么使用channel

这块代码有没有发现有点蹩脚,接下来我们使用函数式编程进行简单的处理。

package mainimport ("fmt""sync")type worker struct {in   chan intdone func()}func createWorker(id int, wg *sync.WaitGroup) worker {w := worker{in: make(chan int),done: func() {wg.Done()},}go doWorker(id, w)return w}func doWorker(id int, w worker) {for n := range w.in {fmt.Printf("Worker %d receive %c\n", id, n)w.done()}}func channelDemo() {var wg sync.WaitGroupvar workers [10]workerfor i := 0; i < 10; i++ {workers[i] = createWorker(i, &wg)}// 添加20个任务wg.Add(20)for i, worker := range workers {worker.in <- 'a' + i}for i, worker := range workers {worker.in <- 'A' + i}wg.Wait()}func main() {channelDemo()}

这块代码看不明白就先放着,写的时间长了,你就会明白其中的含义了,学习东西不要钻牛角尖。

二、使用select进行调度

开头先给一个问题,假设现在有俩个channel,谁来的快先收谁应该怎么做?

package mainimport ("fmt""math/rand""time")func generator() chan int {out := make(chan int)go func() {i := 0for {// 随机睡眠1500毫秒以内time.Sleep(time.Duration(rand.Intn(1500)) *time.Millisecond)// 往out这个channel发送i值out <- ii++}}()return out}func main() {// 这里需要明白如果代码为var c1, c2 chan int  则c1和c2都为nil// 在 select里面也是可以使用的,只不过是堵塞状态!var c1, c2 = generator(), generator()for {select {case n := <-c1:fmt.Printf("receive from c1 %d\n", n)case n := <-c2:fmt.Printf("receive from c2 %d\n", n)}}}

以上就是代码实现,代码注释也写的非常的清晰明了,就不过多的做解释了。

主要用法还是对channel的使用,在带上了一个新的概念select,可以在多个通道,那个通道先发送数据,就先执行谁,并且这个select也是可以并行执行channel管道。

在上文写的createWorkerworker俩个方法还记得吧!接下来就不在select里边直接打印了。

就使用之前写的俩个方法融合在一起,咔咔已将将源码写好了,接下来看一下实现。

package mainimport ("fmt""math/rand""time")func worker(id int, c chan int) {for n := range c {fmt.Printf("Worker %d receive %d\n", id, n)}}func createWorker(id int) chan<- int {c := make(chan int)go worker(id, c)return c}func generator() chan int {out := make(chan int)go func() {i := 0for {// 随机睡眠1500毫秒以内time.Sleep(time.Duration(rand.Intn(1500)) *time.Millisecond)// 往out这个channel发送i值out <- ii++}}()return out}func main() {// 这里需要明白如果代码为var c1, c2 chan int  则c1和c2都为nil// 在 select里面也是可以使用的,只不过是堵塞状态!var c1, c2 = generator(), generator()// 直接调用createWorker方法,返回的就是一个channelw := createWorker(0)for {select {case n := <-c1:w <- ncase n := <-c2:w <- n}}}

运行代码

Go中怎么使用channel

看到运行结果得知也是没有问题的。

这段代码虽然运行没有任何问题,但是这样有什么缺点呢?

Go中怎么使用channel

可以看下这段代码n := <-c1:这里先收了一个值,然后在下边代码w <- n又会阻塞住,这个是不好的。

那么希望是怎么执行的呢?

Go中怎么使用channel

这种模式是在select中既可以收数据,也可以发数据,目前这个程序是编译不过的,请看修改后的源码。

package mainimport ("fmt""math/rand""time")func worker(id int, c chan int) {for n := range c {fmt.Printf("Worker %d receive %d\n", id, n)}}func createWorker(id int) chan<- int {c := make(chan int)go worker(id, c)return c}func generator() chan int {out := make(chan int)go func() {i := 0for {// 随机睡眠1500毫秒以内time.Sleep(time.Duration(rand.Intn(1500)) *time.Millisecond)// 往out这个channel发送i值out <- ii++}}()return out}func main() {// 这里需要明白如果代码为var c1, c2 chan int  则c1和c2都为nil// 在 select里面也是可以使用的,只不过是堵塞状态!var c1, c2 = generator(), generator()// 直接调用createWorker方法,返回的就是一个channelvar worker = createWorker(0)// 这个n如果放在for循环里边,就会一直打印0,因为从c1和c2收数据需要时间,所以会把0直接传给workern := 0// 使用这个标识告诉有没有值hasValue := falsefor {// 利用nil  channel的特性var activeWorker chan<- intif hasValue {activeWorker = worker}select {case n = <-c1:// 收到值的话就标记为truehasValue = truecase n = <-c2:// 收到值的话就标记为truehasValue = truecase activeWorker <- n:hasValue = false}}}

这个模式还是有缺点的,因为n收c1和c2的速度跟消耗的速度是不一样的。

假设c1的生成速度特别快,一下子生成了1,2,3。那么最后输出的数据有可能就只有3,而1和2就无法输出了。

这个场景也是非常好模拟的,只需要在打印的位置加上一点延迟时间即可。

Go中怎么使用channel

此时你会看到运行结果为0、7、12、20…中间很多的数字都没来得急打印。

因此我们就需要把收到的n存下来进行排队输出。

package mainimport ("fmt""math/rand""time")func worker(id int, c chan int) {for n := range c {// 手动让消耗速度变慢time.Sleep(5 * time.Second)fmt.Printf("Worker %d receive %d\n", id, n)}}func createWorker(id int) chan<- int {c := make(chan int)go worker(id, c)return c}func generator() chan int {out := make(chan int)go func() {i := 0for {// 随机睡眠1500毫秒以内time.Sleep(time.Duration(rand.Intn(1500)) *time.Millisecond)// 往out这个channel发送i值out <- ii++}}()return out}func main() {// 这里需要明白如果代码为var c1, c2 chan int  则c1和c2都为nil// 在 select里面也是可以使用的,只不过是堵塞状态!var c1, c2 = generator(), generator()// 直接调用createWorker方法,返回的就是一个channelvar worker = createWorker(0)// 用来收n的值var values []intfor {// 利用nil  channel的特性var activeWorker chan<- intvar activeValue int// 判断当values中有值时if len(values) > 0 {activeWorker = worker// 取出索引为0的值activeValue = values[0]}select {case n := <-c1:// 将收到的数据存到values中values = append(values, n)case n := <-c2:// 将收到的数据存到values中values = append(values, n)case activeWorker <- activeValue:// 送出去后就需要把values中的第一个值拿掉values = values[1:]}}}

以上就是实现代码

此时在来看运行结果。

Go中怎么使用channel

运行结果没有漏掉数据,并且也是无序的,这样就非常好了。

计时器的使用

上面的这个程序是退出不了的,我们想让它10s后就直接退出怎么做呢?

那就需要使用计时器来进行操作了。

package mainimport ("fmt""math/rand""time")func worker(id int, c chan int) {for n := range c {// 手动让消耗速度变慢time.Sleep(time.Second)fmt.Printf("Worker %d receive %d\n", id, n)}}func createWorker(id int) chan<- int {c := make(chan int)go worker(id, c)return c}func generator() chan int {out := make(chan int)go func() {i := 0for {// 随机睡眠1500毫秒以内time.Sleep(time.Duration(rand.Intn(1500)) *time.Millisecond)// 往out这个channel发送i值out <- ii++}}()return out}func main() {// 这里需要明白如果代码为var c1, c2 chan int  则c1和c2都为nil// 在 select里面也是可以使用的,只不过是堵塞状态!var c1, c2 = generator(), generator()// 直接调用createWorker方法,返回的就是一个channelvar worker = createWorker(0)// 用来收n的值var values []int// 返回的是一个channeltm := time.After(10 * time.Second)for {// 利用nil  channel的特性var activeWorker chan<- intvar activeValue int// 判断当values中有值时if len(values) > 0 {activeWorker = worker// 取出索引为0的值activeValue = values[0]}select {case n := <-c1:// 将收到的数据存到values中values = append(values, n)case n := <-c2:// 将收到的数据存到values中values = append(values, n)case activeWorker <- activeValue:// 送出去后就需要把values中的第一个值拿掉values = values[1:]case <-tm:fmt.Println("Bye")return}}}

这里就是源码的实现,可以看到直接在select中是可以收到tm的值的,也就说如果到了10s,就会执行打印bye的操作。

那么现在还有另外一个需求,就是如果在800毫秒的时间内还没有收到数据,可以做其它事情。

使用举一反三的思想,你可以思考一下这件事情应该怎么做。

Go中怎么使用channel

其实也就很简单了,只需要在case中在设置一个定时器即可。

既然说到了这里就在给大家补充一个用法tick := time.Tick(time.Second)

同样也是在case中使用。

Go中怎么使用channel

这样就可以每秒来显示一下values队列有多少数据。

这块的内容就结束了,最终给大家发一下源码,感兴趣的可以在自己的编辑器上试试看。

package mainimport ("fmt""math/rand""time")func worker(id int, c chan int) {for n := range c {// 手动让消耗速度变慢time.Sleep(time.Second)fmt.Printf("Worker %d receive %d\n", id, n)}}func createWorker(id int) chan<- int {c := make(chan int)go worker(id, c)return c}func generator() chan int {out := make(chan int)go func() {i := 0for {// 随机睡眠1500毫秒以内time.Sleep(time.Duration(rand.Intn(1500)) *time.Millisecond)// 往out这个channel发送i值out <- ii++}}()return out}func main() {// 这里需要明白如果代码为var c1, c2 chan int  则c1和c2都为nil// 在 select里面也是可以使用的,只不过是堵塞状态!var c1, c2 = generator(), generator()// 直接调用createWorker方法,返回的就是一个channelvar worker = createWorker(0)// 用来收n的值var values []int// 返回的是一个channeltm := time.After(10 * time.Second)tick := time.Tick(time.Second)for {// 利用nil  channel的特性var activeWorker chan<- intvar activeValue int// 判断当values中有值时if len(values) > 0 {activeWorker = worker// 取出索引为0的值activeValue = values[0]}select {case n := <-c1:// 将收到的数据存到values中values = append(values, n)case n := <-c2:// 将收到的数据存到values中values = append(values, n)case activeWorker <- activeValue:// 送出去后就需要把values中的第一个值拿掉values = values[1:]case <-time.After(800 * time.Millisecond):// 如果在800毫秒没有收到数据则提示超时fmt.Println("timeout")case <-tick:// 每秒获取一下values中队列的长度fmt.Println("queue len = ", len(values))case <-tm:fmt.Println("Bye")return}}}

关于“Go中怎么使用channel”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Go中怎么使用channel

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Go中怎么使用channel

这篇文章将为大家详细讲解有关Go中怎么使用channel,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、使用channel等待任务结束使用案例还是在第一篇的第二节中写的代码,不过这里只需要一段即可。pa
2023-06-20

Go中的channel怎么声明和使用

这篇文章主要介绍了Go中的channel怎么声明和使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Go中的channel怎么声明和使用文章都会有所收获,下面我们一起来看看吧。channelGo语言中的通道(c
2023-07-05

Go语言中的Goroutine和channel怎么使用

这篇“Go语言中的Goroutine和channel怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go语言中的Gor
2023-07-05

golang中channel怎么使用

今天小编给大家分享一下golang中channel怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。什么是 channe
2023-06-29

GO使用socket和channel怎么实现简单控制台聊天室

今天就跟大家聊聊有关GO使用socket和channel怎么实现简单控制台聊天室,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。使用socket和channel,实现简单控制台聊天室这
2023-06-22

Go语言中的channel是什么意思

Go语言中的channel是一种用于协程之间进行通信和数据同步的机制。可以被看作是一种特殊的数据类型,类似于队列或管道,用于在不同的协程之间传递数据。Channel提供了两个主要操作:发送(send)和接收(receive)。在channe
Go语言中的channel是什么意思
2023-12-14

怎么在Golang中实现channel

怎么在Golang中实现channel?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是golanggolang 是Google开发的一种静态强类型、编译型、
2023-06-14

Go通道channel怎么通过通信共享内存

本文小编为大家详细介绍“Go通道channel怎么通过通信共享内存”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go通道channel怎么通过通信共享内存”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。引言不要通
2023-07-02

Go中的WaitGroup怎么使用

今天小编给大家分享一下Go中的WaitGroup怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。正常情况下,新激活的g
2023-06-30

Go中的Context怎么使用

这篇“Go中的Context怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go中的Context怎么使用”文章吧。1
2023-07-06

Golang中怎么读写Channel数据

本文小编为大家详细介绍“Golang中怎么读写Channel数据”,内容详细,步骤清晰,细节处理妥当,希望这篇“Golang中怎么读写Channel数据”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Channel
2023-07-04

GO使用socket和channel实现简单控制台聊天室

使用socket和channel,实现简单控制台聊天室 这里使用socket和channel,演示在GO中如何编写一个简单网络程序 功能分析 聊天室主要功能:用户可以加入/离开聊天室;每个用户发送的消息,广播给所有人 聊天室分为客户端和服务
2022-06-07

go语言中mysql怎么使用

本篇内容介绍了“go语言中mysql怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!golang支持多种数据库1、MySQLMySQL
2023-07-04

go语言中怎么使用select

这篇文章主要介绍“go语言中怎么使用select”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“go语言中怎么使用select”文章能帮助大家解决问题。在golang语言中,select语句 就是用来
2023-06-30

怎么在conda中设置channel镜像

这期内容当中小编将会给大家带来有关怎么在conda中设置channel镜像,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1 显示所有channel首先,conda config --show能够显示出所有
2023-06-15

怎么在Golang中监听多个channel

本篇内容介绍了“怎么在Golang中监听多个channel”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!select 关键字我们可以使用se
2023-07-05

Golang中goroutine和channel使用介绍深入分析

一次只做一件事情并不是完成任务最快的方法,一些大的任务可以拆解成若干个小任务,goroutine可以让程序同时处理几个不同的任务,goroutine使用channel来协调它们的工作,channel允许goroutine互相发送数据并同步,这样一个goroutine就不会领先于另一个goroutine
2023-01-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录