Go小技巧(一)— 获取channel属性

概述

这里一个介绍一个方法,可以在不取channel里的数据的前提下,查看channel是否关闭,是否阻塞,缓冲大小,通道内当前缓冲数据量等。
在这里需要了解一下golang的内存模型,然后通过指针取出相应的值。

channel的结构体在chan.go中:

type hchan struct {
    qcount   uint           // total data in the queue
    dataqsiz uint           // size of the circular queue
    buf      unsafe.Pointer // points to an array of dataqsiz elements
    elemsize uint16
    closed   uint32
    //... 以下字段没有用上,先省略
}

从上面可以看出,现在要从出取出:

  • qcount:queue里的数据总数
  • dataqsiz:queue的最大长度
  • closed:是否关闭

实现

首先我们定义一个struct来与hchan对应。(因为hchan里的字段长度不定,qcountdataqsiz都是uint还好说,主要是取closed中间隔了个unint16,所以这里偷个懒)

type hchan struct {
    qcount   uint           // total data in the queue
    dataqsiz uint           // size of the circular queue
    buf      unsafe.Pointer // points to an array of dataqsiz elements
    elemsize uint16
    closed   uint32
}

省略字段这里没用到,所以直接去掉就行了,上面的属性顺序和类型要与原hchan必须保持一致。
这里想把它通用化所以包成方法接收的会是个interface{},如里channel给interface{}那它在golang底层会被解析成eface

type eface struct {
    _type *_type
    data  unsafe.Pointer
}

所以先将指针定位到eface.data再将指向的数据空间转为自定义的hchan

i := (*[2]uintptr)(unsafe.Pointer(&c))
h := (*hchan)(unsafe.Pointer(i[1]))

这时h中值已经注入了。

附录

type hchan struct {
    qcount   uint           // total data in the queue
    dataqsiz uint           // size of the circular queue
    buf      unsafe.Pointer // points to an array of dataqsiz elements
    elemsize uint16
    closed   uint32
}
type ChanInfo struct {
    Closed bool  // 是否关闭
    Len    uint  // channel内数据量
    Cap    uint  // channel容量
    Block  bool  // 是否已经阻塞
} 

func ChanStatus(c interface{}) (*ChanInfo, error) {
    v := reflect.ValueOf(c)
    if v.Type().Kind() != reflect.Chan {
        return nil, errors.New("type must be channel")
    }
    i := (*[2]uintptr)(unsafe.Pointer(&c))
    h := (*hchan)(unsafe.Pointer(i[1]))
    return &ChanInfo{
        Cap:    h.dataqsiz,
        Len:    h.qcount,
        Closed: h.closed == 1,
        Block:  h.qcount >= h.dataqsiz,
    }, nil
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容