golang的struct{}类型channel

golang的struct{}类型channel

struct{}是个什么鬼

之前看代码的时候发现有如下定义的channel,就觉得很诧异

var ch chan struct{}

这其中,struct{}是个什么鬼。

实际上struct{}就是一种普通数据类型,只是没有具体的值而已。

常用用法

通常struct{}类型channel的用法是使用同步,一般不需要往channel里面写数据,只有读等待,而读等待会在channel被关闭的时候返回。

package main

import (
    "time"
    "log"
)

var ch chan struct{} = make(chan struct{})

func foo() {
    
    log.Println("foo() 111");
    time.Sleep(5 * time.Second)
    log.Println("foo() 222");
    close(ch)
    log.Println("foo() 333");
}

func main() {
    
    log.Println("main() 111");
    go foo()
    log.Println("main() 222");
    <-ch
    log.Println("main() 333");
}

运行结果为

2018/04/12 06:46:33 main() 111
2018/04/12 06:46:33 main() 222
2018/04/12 06:46:33 foo() 111
2018/04/12 06:46:38 foo() 222
2018/04/12 06:46:38 foo() 333
2018/04/12 06:46:38 main() 333

在main函数里面ch读操作一直等待foo调用close(ch)才返回。

注意啊,channel对象一定要make出来才能使用。

往chann struct{}写入数据

另一个问题,我们能不能往struct{}类型的channel里面写数据呢,答案当然也是可以的。

package main

import (
    "time"
    "log"
)

var ch chan struct{} = make(chan struct{})

func foo() {
    ch <- struct{}{}
    log.Println("foo() 111");
    time.Sleep(5 * time.Second)
    log.Println("foo() 222");
    close(ch)
    log.Println("foo() 333");
}

func main() {
    
    log.Println("main() 111");
    go foo()
    log.Println("main() 222");
    <-ch
    log.Println("main() 333");
}

在foo()入口处给ch赋了一个值
注意写法是"struct{}{}",第一个"{}"对表示类型,第二个"{}"对表示一个类型对象实例。

运行结果:

2018/04/12 06:50:16 main() 111
2018/04/12 06:50:16 main() 222
2018/04/12 06:50:16 foo() 111
2018/04/12 06:50:16 main() 333

由于在foo()启动的时候往ch里面写入了一个对象,所以在main()函数里面不需要等待close(ch)就能拿到一个值,因此main()函数可以马上退出,不需要等到foo()的Sleep()完成。

带缓冲的chan struct{}数据读写

另外也可以定义带缓冲的channel

package main

import (
    "time"
    "log"
)

var ch chan struct{} = make(chan struct{}, 2)

func foo() {
    ch <- struct{}{}
    log.Println("foo() 000");
    ch <- struct{}{}
    log.Println("foo() 111");
    time.Sleep(5 * time.Second)
    log.Println("foo() 222");
    close(ch)
    log.Println("foo() 333");
}

func main() {
    var b struct{}
 
    log.Println("main() 111");
    go foo()
    log.Println("main() 222");
    a := <-ch
    log.Println("main() 333", a);
    b  = <-ch
    log.Println("main() 444", b);
    c := <-ch
    log.Println("main() 555", c);
}

运行结果为

2018/04/12 06:58:06 main() 111
2018/04/12 06:58:06 main() 222
2018/04/12 06:58:06 foo() 000
2018/04/12 06:58:06 foo() 111
2018/04/12 06:58:06 main() 333 {}
2018/04/12 06:58:06 main() 444 {}
2018/04/12 06:58:11 foo() 222
2018/04/12 06:58:11 foo() 333
2018/04/12 06:58:11 main() 555 {}

带两个缓冲大小的channel;
另外我们可以看到,其实也可以从channel里面读出数据来,但是这种数据显然没有实际意义。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,969评论 19 139
  • 选择题 [primary] 下面属于关键字的是() A. func B. def C. struct D. cla...
    盘木阅读 1,848评论 0 29
  • channel[通道]是golang的一种重要特性,正是因为channel的存在才使得golang不同于其它语言。...
    码洞阅读 22,508评论 1 53
  • 今年的第三个大满贯赛事,美网即将开战,希望、期待、悬念、猜测一股脑般地装满了网球爱好者的头脑,最渴望、最期待的莫过...
    ZHANGAQ阅读 282评论 0 0
  • 听过无数遍一个问题,这个问题应该是所有处在迷茫期的有志青年都在思考的问题:是留在北上广还是回家? 是啊,好难的问题...
    黄小蚁阅读 286评论 1 0