【Golang】空结构体、通道与context——从控制goroutine说起(一)说到了空结构体的应用场景,在channel中使用:使用 channel 不需要发送任何的数据,只用来通知子协程(goroutine)执行任务。接下来介绍一下其他的应用。

1.自定义集合类型

C#里面有个数据结构叫List,它是有序列表。大致有这么一些api:

List<string> list = new List<string>();
list.Add("r");
list.AddRange(list);
list.Remove("r");
list.Exists(x => x == "r");
list.Clear();
list.Contains("r");
list.Find(x => x == "r");
list.ForEach(x =>
             {
                 Console.WriteLine(x);
             });
list.Insert(5, "DD");

Go 语言标准库没有提供有序列表List的实现, 倒是可以使用 map 来实现无序集合Set。对于集合来说,只需要 map 的键,而不需要值。即使是将值设置为 bool 类型,也会多占据 1 个字节。因此呢,将 map 作为集合(Set)使用时,可以将值类型定义为空结构体,仅作为占位符使用即可。模仿一下C#的api:

package main

import "fmt"

func main() {
	set := Set{}
	set.Add("r")
	set.Add("a")
	set.Add("n")
	set.Add("d")
	set.Add("y")
	set.ForEach(func(s string) {
		fmt.Println(s)
	})
}

type Set map[string]struct{}

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

func (s Set) Remove(k string) {
	delete(s, k)
}

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

func (s Set) ForEach(action func(string)) {
	for k := range s {
		action(k)
	}
}

这种在有大量的数据需要做判断,特别是数据库数据,可以用这样的Set把数据存起来,以空间换时间。

2.方法接收者

type T struct{}

func (s *T) Call() {
}

func main() {
 var s T
 s.Call()
}

在部分场景下,结构体只包含方法,不包含任何的字段。另外场景就是没想好结构体如何设计,可以用空结构体占位,也便于未来针对该类型进行公共字段等的增加。甚至随时可以把空结构体替换为任何数据结构:

type T bool
type T int