内部购物券网站怎么做,镇江百度seo,网站后台怎么修改文字,淘宝联盟推广做网站违法s t r u c t struct struct是 G o l a n g Golang Golang里的关键字#xff0c;用于定义结构类型 比如
type Student struct{id intname string
}struct{}是有 0 0 0个元素的结构体. struct{}{}表示类型struct{}的值为空{}
1.性质
1.1不占用内存
大小为 0 0 0#xff0c;… s t r u c t struct struct是 G o l a n g Golang Golang里的关键字用于定义结构类型 比如
type Student struct{id intname string
}struct{}是有 0 0 0个元素的结构体. struct{}{}表示类型struct{}的值为空{}
1.性质
1.1不占用内存
大小为 0 0 0不需要内存来存储struct{}类型的值。
func Test_Size(t *testing.T) {var x intvar y stringvar z struct{}t.Log(unsafe.Sizeof(x), unsafe.Sizeof(y), unsafe.Sizeof(z)) //8 16 0
}1.2 地址相同
定义两个struct{}类型的变量打印并比较其地址发现是相同的
func Test_Address(t *testing.T) {var x struct{}var y struct{}t.Logf(%p %p %v %v, x, y, x y, x y) // 0x1290460 0x1290460 true true
}2.用途
2.1实现set
golang里没有实现set如果在使用map的时候只关心key不关心value的话可以借助struct{}来实现set。比如key为string类型那么set的实现map[string]struct{}。 因为struct{}不占用空间所以在查找和判断的过程中速度会快而且占用的内存也会小 简单实现
func Test_set(t *testing.T) {set : make(map[string]struct{})set[a] struct{}{}if _, ok : set[a]; ok {t.Log(exists) //exists}
}使用interface{}实现
type Set map[interface{}]struct{}func (s Set) Add(item interface{}) {s[item] struct{}{}
}func (s Set) Remove(item interface{}) {delete(s, item)
}func (s Set) Contains(item interface{}) bool {_, exists : s[item]return exists
}func Test_any_set(t *testing.T) {set : make(Set)set.Add(apple)set.Add(banana)set.Add(orange)fmt.Println(Set:, set)fmt.Println(Contains apple:, set.Contains(apple))fmt.Println(Contains grape:, set.Contains(grape))set.Remove(banana)fmt.Println(Set:, set)
}使用泛型实现
type Set[T comparable] map[T]struct{}func (s Set[T]) Add(v T) {s[v] struct{}{}
}func (s Set[T]) Remove(v T) {delete(s, v)
}func (s Set[T]) Contains(v T) bool {_, ok : s[v]return ok
}func (s Set[T]) Len() int {return len(s)
}func (s Set[T]) Values() []T {values : make([]T, 0, s.Len())for v : range s {values append(values, v)}return values
}func Test_any_set(t *testing.T) {s : Set[string]{}s.Add(apple)s.Add(banana)s.Add(orange)fmt.Println(Set:, s.Values())fmt.Println(Contains apple:, s.Contains(apple))fmt.Println(Contains grape:, s.Contains(grape))s.Remove(banana)fmt.Println(Set:, s.Values())
}2.2. 用于无数据的channel
有的时候 c h a n n e l channel channel不需要发送数据只需要一个触发信号就可以使用struct{}来减少信号传递过程中的内存开销 a. 等待协程完成 w o r k e r worker worker函数是一个协程它会模拟一些工作并在完成后发送空结构体值到 d o n e done done通道。 在 T e s t _ w a i t Test\_wait Test_wait函数中我们通过从 d o n e done done通道接收空结构体值来等待工作完成。
func worker(done chan struct{}) {fmt.Println(Worker: Performing some work...)time.Sleep(2 * time.Second)fmt.Println(Worker: Work completed!)done - struct{}{} // 发送空结构体值表示工作完成
}
func Test_wait(t *testing.T) {done : make(chan struct{})go worker(done)-done // 接收空结构体值等待工作完成t.Log(Main: Done!)
}b.触发事件 w a i t F o r E v e n t waitForEvent waitForEvent函数会等待接收到空结构体值表示事件发生。 t r i g g e r E v e n t triggerEvent triggerEvent函数会在一段时间后发送空结构体值到event通道表示事件发生。 通过使用空结构体值作为通道元素我们可以简单地实现事件的触发和等待。
func waitForEvent(event chan struct{}) {fmt.Println(Waiting for event...)-event // 等待接收到空结构体值表示事件发生fmt.Println(Event received!)
}func triggerEvent(event chan struct{}) {time.Sleep(2 * time.Second)fmt.Println(Triggering event...)event - struct{}{} // 发送空结构体值表示事件发生
}
func Test_event(t *testing.T) {event : make(chan struct{})go waitForEvent(event)go triggerEvent(event)time.Sleep(3 * time.Second)
} 2.3 方法接收器
实现一个接口只需要实现一些方法不用声明一些额外的数据可以用struct{}来实现也可以换成其他任意的变量比如 i n t int int b o o l bool bool
type Animal interface {Shouting()
}
type Dog struct{}func (dog *Dog) Shouting() {fmt.Println(wang wang wang)
}