其他分享
首页 > 其他分享> > golang 空结构体 struct{}

golang 空结构体 struct{}

作者:互联网

 

定义的各种姿势
原生定义
a := struct{}{}
1
struct{} 可以就认为是一种类型,a 变量就是 struct {} 类型的一种变量,地址为 runtime.zerobase ,大小为 0 ,不占内存。

重定义类型
golang 使用 type 关键字定义新的类型,比如:

type emptyStruct struct{}
1
定义出来的 emptyStruct 是新的类型,具有对应的 type 结构,但是性质 struct{} 完全一致,编译器对于 emptryStruct 类型的内存分配,也是直接给 zerobase 地址的。
————————————————
var s struct{} 

变量 size 是 0 ; fmt.Println(unsafe.Sizeof(s))

本质上来讲,使用空结构体的初衷只有一个:节省内存,但是更多的情况,节省的内存其实很有限,这种情况使用空结构体的考量其实是:根本不关心结构体变量的值。

作用1 :做set,map[string]struct{}
由于struct{}是空,不关心内容,这样map便改造为set

 

set := make(map[string]struct{})
for _, value := range []string{"apple", "orange", "apple"} {
   set[value] = struct{}{}
}
fmt.Println(set)
// Output: map[orange:{} apple:{}]

map 和 struct {} 一般的结合姿势是这样的:

// 创建 map
m := make(map[int]struct{})
// 赋值
m[1] = struct{}{}
// 判断 key 键存不存在
_, ok := m[1]

一般 map 和 struct {} 的结合使用场景是:只关心 key,不关注值。比如查询 key 是否存在就可以用这个数据结构,通过 ok 的值来判断这个键是否存在,map 的查询复杂度是 O(1) 的,查询很快。

你当然可以用 map[int]bool 这种类型来代替,功能也一样能实现,很多人考虑使用 map[int]struct{} 这种使用方式真的就是为了省点内存,当然大部分情况下,这种节省是不足道哉的,所以究竟要不要这样使用还是要看具体场景。

 

作用2:chan struct{}
可以做退出

func worker(i int, ch chan Work, quit chan struct{}) {
    for {
        select {
        case w := <-ch:
            // do something
        case <-quit:
            fmt.Println("worker", i, "quitting")
            quit = nil
        }
    }
}

还有其他情况,比如有时候使用channel,但并不需要附带任何数据。



func worker(ch chan struct{}) {
    // Receive a message from the main program.
    <-ch
    println("roger")
    
    // Send a message to the main program.
    close(ch)
}

func main() {
    ch := make(chan struct{})
    go worker(ch)
    
    // Send a message to a worker.
    ch <- struct{}{}
    
    // Receive a message from the worker.
    <-ch
    println(“roger")
    // Output:
    // roger
    // roger
}

chan & struct{}
channel 和 struct{} 结合是一个最经典的场景,struct{} 通常作为一个信号来传输,并不关注其中内容。chan 的分析在前几篇文章有详细说明。chan 本质的数据结构是一个管理结构加上一个 ringbuffer ,如果 struct{} 作为元素的话,ringbuffer 就是 0 分配的。

chan 和 struct{} 结合基本只有一种用法,就是信号传递,空结构体本身携带不了值,所以也只有这一种用法啦,一般来说,配合 no buffer 的 channel 使用。

// 创建一个信号通道
waitc := make(chan struct{})

// ...
goroutine 1:
    // 发送信号: 投递元素
    waitc <- struct{}
    // 发送信号: 关闭
    close(waitc)

goroutine 2:
    select {
    // 收到信号,做出对应的动作
    case <-waitc:
    }    

这种场景我们思考下,是否一定是非 struct{} 不可?其实不是,而且也不多这几个字节的内存,所以这种情况真的就只是不关心 chan 的元素值而已,所以才用的 struct{}

 

原文链接:https://blog.csdn.net/qiya2007/article/details/111502649

https://blog.csdn.net/qiya2007/article/details/111502649

标签:map,set,struct,int,chan,golang,内存,结构
来源: https://www.cnblogs.com/youxin/p/16296407.html