发布时间:2024-12-23 05:55:20
1. 信号量
信号量是一种常见的并发编程模式,它可以用来协调和管理多个协程之间的资源访问。在 Golang 中,我们通常使用 channel 来实现信号量。然而,当我们只需要一个标识符来表示某个协程是否可执行时,空 struct 是一个比较简洁的解决方案。 ```go var semaphore = make(chan struct{}, 1) func worker() { // 获取信号量 <-semaphore // 执行任务 // 释放信号量 semaphore <- struct{}{} } func main() { // 初始化信号量 semaphore <- struct{}{} // 启动多个 worker go worker() go worker() // 阻塞主协程,保持程序运行 select {} } ```2. set 集合
set 是一种常用的数据结构,它允许我们存储一组唯一的元素。在 Golang 中,我们可以使用 map 类型来实现 set 集合,但是这会造成一些内存浪费。相比之下,使用空 struct 来实现 set 集合更加高效。 ```go var mySet = make(map[string]struct{}) func main() { // 添加元素 mySet["a"] = struct{}{} mySet["b"] = struct{}{} mySet["c"] = struct{}{} // 检查元素是否存在 _, ok := mySet["a"] if ok { fmt.Println("Element exists") } else { fmt.Println("Element does not exist") } // 删除元素 delete(mySet, "a") } ```3. 锁
在并发编程中,我们经常需要使用锁来保护共享资源。Golang 的 sync 包提供了各种锁的实现,如 Mutex、RWMutex 等。然而,在某些场景下,我们只需要一个简单的标识来表示某个资源是否被锁住,此时空 struct 是一个很好的选择。 ```go type MyLock struct { ch chan struct{} } func NewMyLock() *MyLock { return &MyLock{ ch: make(chan struct{}, 1), } } func (l *MyLock) Lock() { <-l.ch } func (l *MyLock) Unlock() { l.ch <- struct{}{} } func main() { var lock MyLock // 加锁 lock.Lock() // 解锁 lock.Unlock() } ```