惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Check Point Blog
Hacker News: Ask HN
Hacker News: Ask HN
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
WordPress大学
WordPress大学
P
Proofpoint News Feed
V
Visual Studio Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
N
Netflix TechBlog - Medium
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 聂微东
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
S
Schneier on Security
T
Threat Research - Cisco Blogs
腾讯CDC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Hacker News
The Hacker News
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
GbyAI
GbyAI
N
News | PayPal Newsroom
L
LINUX DO - 最新话题
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Palo Alto Networks Blog
T
Tenable Blog
S
Secure Thoughts
T
Threatpost
V2EX - 技术
V2EX - 技术
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
罗磊的独立博客
P
Privacy & Cybersecurity Law Blog
Engineering at Meta
Engineering at Meta
小众软件
小众软件
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
Y
Y Combinator Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Cybersecurity and Infrastructure Security Agency CISA
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
P
Privacy International News Feed
H
Heimdal Security Blog
量子位
B
Blog

极客兔兔

Go sync.Cond | Go 语言高性能编程 Go 死码消除与调试(debug)模式 | Go 语言高性能编程 Go sync.Once | Go 语言高性能编程 Go 逃逸分析 | Go 语言高性能编程 2020 年终总结 | 极客兔兔 Go struct 内存对齐 | Go 语言高性能编程 控制协程(goroutine)的并发数量 | Go 语言高性能编程 | 极客兔兔 如何退出协程 goroutine (其他场景) | Go 语言高性能编程 如何退出协程 goroutine (超时场景) | Go 语言高性能编程 Go 语言陷阱 - 数组和切片 | Go 语言高性能编程 减小 Go 代码编译后的二进制体积 | Go 语言高性能编程 Go Reflect 提高反射性能 | Go 语言高性能编程 读写锁和互斥锁的性能比较 | Go 语言高性能编程 | 极客兔兔 for 和 range 的性能比较 | Go 语言高性能编程 切片(slice)性能及陷阱 | Go 语言高性能编程 | 极客兔兔 字符串拼接性能及原理 | Go 语言高性能编程 | 极客兔兔 pprof 性能分析 | Go 语言高性能编程 benchmark 基准测试 | Go 语言高性能编程 Go 语言高性能编程 | 极客兔兔 Go 接口型函数的使用场景 | 极客兔兔 Python 简明教程 | 快速入门 | 极客兔兔 Go 语言笔试面试题(代码输出) | 极客面试 | 极客兔兔 动手写RPC框架 - GeeRPC第七天 服务发现与注册中心(registry) | 极客兔兔 动手写RPC框架 - GeeRPC第六天 负载均衡(load balance) 动手写RPC框架 - GeeRPC第五天 支持HTTP协议 | 极客兔兔 动手写RPC框架 - GeeRPC第四天 超时处理(timeout) | 极客兔兔 动手写RPC框架 - GeeRPC第三天 服务注册(service register) 动手写RPC框架 - GeeRPC第二天 支持并发与异步的客户端 | 极客兔兔 动手写RPC框架 - GeeRPC第一天 服务端与消息编码 | 极客兔兔 7天用Go从零实现RPC框架GeeRPC | 极客兔兔 Go 语言笔试面试题(并发编程) | 极客面试 | 极客兔兔 Go 语言笔试面试题(基础语法) | 极客面试 | 极客兔兔 Go 语言笔试面试题汇总 | 极客面试 | 极客兔兔 Go Context 并发编程简明教程 | 快速入门 Go Mmap 文件内存映射简明教程 | 快速入门 动手写ORM框架 - GeeORM第七天 数据库迁移(Migrate) | 极客兔兔 动手写ORM框架 - GeeORM第六天 支持事务(Transaction) | 极客兔兔 动手写ORM框架 - GeeORM第五天 实现钩子(Hooks) | 极客兔兔 动手写ORM框架 - GeeORM第四天 链式操作与更新删除 | 极客兔兔 动手写ORM框架 - GeeORM第三天 记录新增和查询 | 极客兔兔 动手写ORM框架 - GeeORM第二天 对象表结构映射 | 极客兔兔 动手写ORM框架 - GeeORM第一天 database/sql 基础 SQLite 常用命令 | 速查表(Cheat Sheet) 7天用Go从零实现ORM框架GeeORM | 极客兔兔 动手写分布式缓存 - GeeCache第七天 使用 Protobuf 通信 动手写分布式缓存 - GeeCache第六天 防止缓存击穿 | 极客兔兔 动手写分布式缓存 - GeeCache第五天 分布式节点 | 极客兔兔 动手写分布式缓存 - GeeCache第四天 一致性哈希(hash) | 极客兔兔 Go Mock (gomock)简明教程 | 快速入门 动手写分布式缓存 - GeeCache第三天 HTTP 服务端 动手写分布式缓存 - GeeCache第二天 单机并发缓存 | 极客兔兔 Go Test 单元测试简明教程 | 快速入门 7天用Go从零实现分布式缓存GeeCache | 极客兔兔 Go WebAssembly (Wasm) 简明教程 | 快速入门 Go RPC & TLS 鉴权简明教程 | 快速入门 Go Protobuf 简明教程 | 快速入门 Go语言动手写Web框架 - Gee第七天 错误恢复(Panic Recover) WSL, Git, Mircosoft Terminal 等常用工具配置 Rust 简明教程 | 快速入门 | 极客兔兔 Go语言动手写Web框架 - Gee第六天 模板(HTML Template) 百宝箱 - 值得收藏的工具网站 | 极客兔兔 Go语言动手写Web框架 - Gee第五天 中间件Middleware | 极客兔兔 Go语言动手写Web框架 - Gee第四天 分组控制Group | 极客兔兔 Go语言动手写Web框架 - Gee第三天 前缀树路由Router | 极客兔兔 博客折腾记(七) - Gitalk Plus | 极客兔兔 Go语言动手写Web框架 - Gee第二天 上下文Context | 极客兔兔 Go2 新特性简明教程 | 快速入门 | 极客兔兔 博客折腾记(六) - 不要为了流量忘记了初心 | 极客兔兔 Go语言动手写Web框架 - Gee第一天 http.Handler | 极客兔兔 7天用Go从零实现Web框架Gee教程 | 极客兔兔 Go Gin 简明教程 | 快速入门 Go 语言简明教程 | 快速入门 | 极客兔兔 机器学习笔试面试题 11-20 | 极客面试 | 极客兔兔 机器学习笔试面试题 1-10 | 极客面试 | 极客兔兔 机器学习笔试面试题汇总 | 极客面试 | 极客兔兔 TensorFlow 2 中文文档 - RNN LSTM 文本分类 TensorFlow 2 中文文档 - TFHub 迁移学习 TensorFlow 2 中文文档 - 卷积神经网络分类 CIFAR-10 TensorFlow 2 中文文档 - 保存与加载模型 TensorFlow 2 中文文档 - 过拟合与欠拟合 TensorFlow 2 中文文档 - 回归预测燃油效率 TensorFlow 2 中文文档 - 特征工程结构化数据分类 TensorFlow 2 中文文档 - IMDB 文本分类 TensorFlow 2 中文文档 - MNIST 图像分类 TensorFlow 2 / 2.0 中文文档 TensorFlow 2.0 (九) - 强化学习 70行代码实战 Policy Gradient 博客折腾记(五) - 友链这件事,没那么简单 | 极客兔兔 博客折腾记(四) - 原创资格是争取来的 | 极客兔兔 TensorFlow 2.0 (八) - 强化学习 DQN 玩转 gym Mountain Car TensorFlow 2.0 (七) - 强化学习 Q-Learning 玩转 OpenAI gym 博客折腾记(三) - 主题设计、彩蛋与阅读量翻倍 | 极客兔兔 TensorFlow 2.0 (六) - 监督学习玩转 OpenAI gym game 博客折腾记(二) - 对搜索引擎的理解 | 极客兔兔 博客折腾记(一) - 极致性能的尝试 | 极客兔兔 Pandas 数据处理(三) - Cheat Sheet 中文版 TensorFlow 2.0 (五) - mnist手写数字识别(CNN卷积神经网络) TensorFlow入门(四) - mnist手写数字识别(制作h5py训练集) | 极客兔兔 TensorFlow入门(三) - mnist手写数字识别(可视化训练) | 极客兔兔 Pandas 数据处理(二) - 筛选数据 | 极客兔兔 Pandas 数据处理(一) - DataFrame 与 Series
Go 空结构体 struct{} 的使用 | Go 语言高性能编程
2020-12-25 · via 极客兔兔

源代码/数据集已上传到 Github - high-performance-go

high performance go - data structure

1 空结构体占用空间么

在 Go 语言中,我们可以使用 unsafe.Sizeof 计算出一个数据类型实例需要占用的字节数。

1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
"unsafe"
)

func main() {
fmt.Println(unsafe.Sizeof(struct{}{}))
}

运行上面的例子将会输出:

1
2
$ go run main.go
0

也就是说,空结构体 struct{} 实例不占据任何的内存空间。

2 空结构体的作用

因为空结构体不占据内存空间,因此被广泛作为各种场景下的占位符使用。一是节省资源,二是空结构体本身就具备很强的语义,即这里不需要任何值,仅作为占位符。

2.1 实现集合(Set)

Go 语言标准库没有提供 Set 的实现,通常使用 map 来代替。事实上,对于集合来说,只需要 map 的键,而不需要值。即使是将值设置为 bool 类型,也会多占据 1 个字节,那假设 map 中有一百万条数据,就会浪费 1MB 的空间。

因此呢,将 map 作为集合(Set)使用时,可以将值类型定义为空结构体,仅作为占位符使用即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type Set map[string]struct{}

func (s Set) Has(key string) bool {
_, ok := s[key]
return ok
}

func (s Set) Add(key string) {
s[key] = struct{}{}
}

func (s Set) Delete(key string) {
delete(s, key)
}

func main() {
s := make(Set)
s.Add("Tom")
s.Add("Sam")
fmt.Println(s.Has("Tom"))
fmt.Println(s.Has("Jack"))
}

2.2 不发送数据的信道(channel)

1
2
3
4
5
6
7
8
9
10
11
func worker(ch chan struct{}) {
<-ch
fmt.Println("do something")
close(ch)
}

func main() {
ch := make(chan struct{})
go worker(ch)
ch <- struct{}{}
}

有时候使用 channel 不需要发送任何的数据,只用来通知子协程(goroutine)执行任务,或只用来控制协程并发度。这种情况下,使用空结构体作为占位符就非常合适了。

2.3 仅包含方法的结构体

1
2
3
4
5
6
7
8
9
type Door struct{}

func (d Door) Open() {
fmt.Println("Open the door")
}

func (d Door) Close() {
fmt.Println("Close the door")
}

在部分场景下,结构体只包含方法,不包含任何的字段。例如上面例子中的 Door,在这种情况下,Door 事实上可以用任何的数据结构替代。例如:

1
2
type Door int
type Door bool

无论是 int 还是 bool 都会浪费额外的内存,因此呢,这种情况下,声明为空结构体是最合适的。

附 推荐与参考


edit this page last updated at 2026-02-23