Alt text

一、空结构体的作用

空结构体的作用

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

1.1 实现集合(Set)

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

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

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"))
}

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

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)执行任务,或只用来控制协程并发度。这种情况下,使用空结构体作为占位符就非常合适了。

二、go编程建议

other
  1. 性能优化:使用反射赋值,效率非常低下,如果有替代方案,尽可能避免使用反射,特别是会被反复调用的热点代码。例如 RPC 协议中,需要对结构体进行序列化和反序列化,这个时候避免使用 Go 语言自带的 jsonMarshalUnmarshal 方法,因为标准库中的 json 序列化和反序列化是利用反射实现的。可选的替代方案有 easyjson,在大部分场景下,相比标准库,有 5 倍左右的性能提升。
  2. 并发读写map问题。解决方法:1.使用channel 2.使用sync.map 3.使用map但必须进行加锁

三、

other

四、go环境

go环境

4.1 mac下多版本go

Mac 下使用 homebrew 可以轻松实现 Go 多版本切换。

使用以下方法安装最新版本:

$ brew install go

$ go version
go version go1.17.1 darwin/amd64

使用以下方法安装指定版本:

$ brew install go@1.15

首先 unlink:

$ brew unlink go

link 指定版本:

$ brew link go@1.15

如要恢复最新版本,重复以上 unlink 和 link 操作即可。

4.2 linux下升级go

下载我们需要的 Golang 版本 tar 包:

wget https://go.dev/dl/go1.20.3.linux-amd64.tar.gz

删除机器上现有的 Golang,并将刚刚的 tar 包解压到 /usr/local/go/:

rm -rf /usr/local/go tar -C /usr/local -xzf go1.20.3.linux-amd64.tar.gz

配置环境变量,打开 /etc/profile:

vim /etc/profile

在最后加入以下内容:

export PATH=$PATH:/usr/local/go/bin

退出并保存,然后应用我们刚的修改(不然的话得重启系统或重新进入终端才会生效):

source /etc/profile

到这里 Golang 的安装就完成了,我们检查下:

$ go version

go version go1.20.3 linux/amd64

可以看到,正确打印出了 Golang 的版本信息,安装成功,Over