😥 整理不易,此资源只针对正式星主开放,
还请入驻星球后再来观看。

GOLANG ROADMAP

阅读模式

  • 沉浸
  • 自动
  • 日常
首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
author-avatar

GOLANG ROADMAP


首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
  • Go真实面试题汇总系列

    • Go基础篇
  • 宝典内容

    • 2. 对已经关闭的channel进行读写操作会发生什么?
    • 7.介绍一下通道
    • 8.channel实现方式/原理/概念/底层实现
    • 9. 同一个协程里面,对无缓冲channel同时发送和接收数据有什么问题
    • 10.channel和锁的对比
    • 11. channel的应用场景
    • 14. 向为nil的channel发送数据会怎么样
    • 28. channel有缓冲和无缓冲在使用上有什么区别?
    • 47. 管道是否能二次关闭?
    • 48. 管道关闭是否能读写?
    • 52. channel是否线程安全等;
    • 91. go利用channel通信的方式
    • 103. 被close的channel会有什么问题
    • 104. 分布式锁知道哪些?用channel如何实现?
    • 105. 集群用channel如何实现分布式锁
    • 118. Channel 的使用场景
    • 149. gochannel实现排序
    • 189. go 里的 syncLock 和 channel 的性能有区别吗?
    • 209. 了解过channel吗?
    • 210. channel内部数据结构有了解吗?
    • 216. 介绍下go的chan,chan可以做什么
    • 217. 如何实现限流器,请用chan实现一种限流器,也可以不用chan实现
    • 260. 如何判断channel已关闭?
    • 273. channel关闭以后,再往其发送或接收,会发生什么
    • 307. go channel底层实现
    • 331. 说说你了解的管道
    • 332. 看过管道的底层源码吗
    • 346. 实现chan struct{}不占用内存空间,实现传递信号的通道
    • 364. channel有了解吗?
    • 382. golang的管道怎么用;我说是channel
    • 390. channel和锁对比一下
    • 391. channel的应用场景
    • 395. chan的阻塞和非阻塞?
    • 405. channel怎么实现线程安全
    • 412. channelnobuffer以及buffer的区别。
    • 425. channel 底层
    • 426. sync包中的同步原语和channel的使用场景
    • 436. channel和共享内存有什么优劣势?

😥 整理不易,此资源只针对正式星主开放,
还请入驻星球后再来观看。

8.channel实现方式/原理/概念/底层实现


企业题库解析小组

题目序号:(66,122,208,493,657,839,984,1035,1618,1681,1951、6621)

**题目来源:**好未来、米哈游、跟谁学,字节跳动、美团、网易、新浪、滴滴、小米

频次: 12

答案1:(知北游)+

背景:

  • Go语言提供了一种不同的并发模型--通信顺序进程(communicating sequential processes,CSP)。
  • 设计模式:通过通信的方式共享内存
  • channel收发操作遵循先进先出(FIFO)的设计

底层结构:

type hchan struct {
    qcount   uint           // channel中的元素个数
    dataqsiz uint           // channel中循环队列的长度
    buf      unsafe.Pointer // channel缓冲区数据指针
    elemsize uint16            // buffer中每个元素的大小
    closed   uint32            // channel是否已经关闭,0未关闭
    elemtype *_type // channel中的元素的类型
    sendx    uint   // channel发送操作处理到的位置
    recvx    uint   // channel接收操作处理到的位置
    recvq    waitq  // 等待接收的sudog(sudog为封装了goroutine和数据的结构)队列由于缓冲区空间不足而阻塞的Goroutine列表
    sendq    waitq  // 等待发送的sudogo队列,由于缓冲区空间不足而阻塞的Goroutine列表

    lock mutex   // 一个轻量级锁
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

channel创建:

ch := make(chan int, 3)
1
  • 创建channel实际上就是在内存中实例化了一个***hchan***结构体,并返回一个chan指针
  • channle在函数间传递都是使用的这个指针,这就是为什么函数传递中无需使用channel的指针,而是直接用channel就行了,因为channel本身就是一个指针

channel发送数据:

ch <- 1
ch <- 2
1
2
  • 检查 recvq 是否为空,如果不为空,则从 recvq 头部取一个 goroutine,将数据发送过去,并唤醒对应的 goroutine 即可。
  • 如果 recvq 为空,则将数据放入到 buffer 中。
  • 如果 buffer 已满,则将要发送的数据和当前 goroutine 打包成 sudog 对象放入到 sendq中。并将当前 goroutine 置为 waiting 状态。

channel接收数据:

<-ch
<-ch
1
2
  • 检查sendq是否为空,如果不为空,且没有缓冲区,则从sendq头部取一个goroutine,将数据读取出来,并唤醒对应的goroutine,结束读取过程。
  • 如果sendq不为空,且有缓冲区,则说明缓冲区已满,则从缓冲区中首部读出数据,把sendq头部的goroutine数据写入缓冲区尾部,并将goroutine唤醒,结束读取过程。
  • 如果sendq为空,缓冲区有数据,则直接从缓冲区读取数据,结束读取过程。
  • 如果sendq为空,且缓冲区没数据,则只能将当前的goroutine加入到recvq,并进入waiting状态,等待被写goroutine唤醒。

channel规则:

操作 空channel 已关闭channel 活跃中的channel
close(ch) panic panic 成功关闭
ch<- v 永远阻塞 panic 成功发送或阻塞
v,ok = <-ch 永远阻塞 不阻塞 成功接收或阻塞