package main import ( "fmt" "time" "unsafe" ) // Empty 空结构体 type Empty struct{} // EmptyMultiple 由多个空结构体组成的结构体 type EmptyMultiple struct { s1 Empty s2 Empty s3 Empty } func main() { struct0 := struct{}{} // 定义空结构体类型变量 struct1 := Empty{} // 定义空结构体类型变量 struct2 := EmptyMultiple{} // 定义由多个空结构体组合形成的结构体类型变量 fmt.Printf("struct0 --- pointer:%p,size:%d \n", &struct0, unsafe.Sizeof(struct0)) fmt.Printf("struct1 --- pointer:%p,size:%d \n", &struct1, unsafe.Sizeof(struct1)) fmt.Printf("struct2 --- pointer:%p,size:%d \n", &struct2, unsafe.Sizeof(struct2)) // struct0 --- pointer:0x3193f8,size:0 // struct1 --- pointer:0x3193f8,size:0 // struct2 --- pointer:0x3193f8,size:0 // 重要说明①:空结构体的指针都是一样的。 // 重要说明②:无论是单个空结构体,还是由多个空结构体组合形成的新结构体,它们的变量都不占用内存空间。 // ========== 使用场景①:实现set集合 ========== // set := map[string]struct{}{} // 初始化map数据类型变量,其中value的数据类型为空结构体 // 重要说明:set集合可以理解为只使用key的map,所以value的数据类型设置为int、bool、string等也能实现, // 既然如此那么使用不占用内存空间的空结构体则是最优方案。 set["红楼梦"] = struct{}{} // set集合只需使用key,无需使用value,故将value设为空结构体 set["西游记"] = struct{}{} // set集合只需使用key,无需使用value,故将value设为空结构体 set["水浒传"] = struct{}{} // set集合只需使用key,无需使用value,故将value设为空结构体 // 重要说明:上面三个元素的value都不占用内存空间 // 检查《三国演义》是否存在 book := "三国演义" value, exist := set[book] // 这里实际上就是检查指定key的map元素是否存在 if exist { fmt.Printf("《%+v》存在(size=%d) \n", book, unsafe.Sizeof(value)) } else { fmt.Printf("《%+v》不存在 \n", book) // 《三国演义》不存在 } // 检查《西游记》是否存在 book = "西游记" value, exist = set[book] // 这里实际上就是检查指定key的map元素是否存在 if exist { fmt.Printf("《%+v》存在(size=%d) \n", book, unsafe.Sizeof(value)) // 《西游记》存在(size=0) } else { fmt.Printf("《%+v》不存在 \n", book) } // ========== 使用场景②:空结构体类型管道 ========== // channel := make(chan struct{}) // 重要说明:这里管道的数据类型设置为int、bool、string等也一样可以实现功能,只是这个管道仅用来传递信号, // 数据类型是什么不重要,数据值是什么也无所谓,那么使用不占用内存空间的空结构体则是最优方案。 go func() { time.Sleep(time.Second * 3) channel <- struct{}{} // 往管道写入空结构体 }() fmt.Println("协程任务执行中……") // 协程任务执行中…… <-channel // 重要提醒:这里会发生阻塞 fmt.Println("协程任务已执行完毕") // 协程任务已执行完毕 } // ========== 总结 ========== // // 1、空结构体类型的变量不占用内存空间,而且不限于单个空结构体,由多个空结构体组合形成的结构体也不占用内存空间。 // 2、无论什么场景,使用空结构体都是围绕其不占用内存空间的特性做文章,这些场景的共同特征是不关心数据的类型是什么,也不关心 // 数据的值是什么。
Copyright © 2024 码农人生. All Rights Reserved