您的位置:首页 > 财经 > 金融 > 设计官网推荐_建筑设计公司资质等级_培训心得体会800字_今天的新闻发布会

设计官网推荐_建筑设计公司资质等级_培训心得体会800字_今天的新闻发布会

2025/3/14 15:19:55 来源:https://blog.csdn.net/cpxsxn/article/details/145992894  浏览:    关键词:设计官网推荐_建筑设计公司资质等级_培训心得体会800字_今天的新闻发布会
设计官网推荐_建筑设计公司资质等级_培训心得体会800字_今天的新闻发布会

sync.WaitGroup

sync.WaitGroup 是 Go 语言中的一个并发原语,用于等待一组协程(goroutine)完成。在使用多个协程时,WaitGroup 可以帮助你确保所有协程都执行完毕后再继续执行主程序。以下是 sync.WaitGroup 的基本用法和示例:
下面是一个简单的示例,展示如何使用 sync.WaitGroup 来等待多个协程完成:

package mainimport ("fmt""sync""time"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 在函数退出时调用 Donefmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second) // 模拟工作fmt.Printf("Worker %d done\n", id)
}func main() {var wg sync.WaitGroupconst numWorkers = 5for i := 1; i <= numWorkers; i++ {wg.Add(1) // 启动一个新协程前增加计数go worker(i, &wg)}wg.Wait() // 等待所有协程完成fmt.Println("All workers done")
}

注意事项

  • 正确使用 Add 和 Done:确保在启动协程之前调用 Add,并在协程结束时调用 Done,否则可能导致死锁或计数错误。
  • 传递指针:WaitGroup 通常作为指针传递给协程,以避免复制并确保对同一个 WaitGroup 实例进行操作。
  • 不要复制 WaitGroup:WaitGroup 不应该被复制,因为它内部包含一个计数器,复制会导致计数器不一致。

sync.Mutex

sync.Mutex 是 Go 语言中的一种互斥锁,用于在多协程环境中保护共享资源,防止数据竞争。当多个协程需要访问同一个共享变量时,可以使用 Mutex 来确保同时只有一个协程能够访问该变量。

下面是一个简单的示例,展示如何使用 sync.Mutex 来保护对共享变量的访问:
package main

import ("fmt""sync""time"
)var (counter intmu      sync.Mutex
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done()for i := 0; i < 5; i++ {mu.Lock() // 加锁counter++fmt.Printf("Worker %d incremented counter to %d\n", id, counter)mu.Unlock() // 解锁time.Sleep(time.Millisecond * 100) // 模拟工作}
}func main() {var wg sync.WaitGroupconst numWorkers = 3for i := 1; i <= numWorkers; i++ {wg.Add(1)go worker(i, &wg)}wg.Wait()fmt.Printf("Final counter value: %d\n", counter)
}

sync.Cond

sync.Cond 是 Go 语言中的一个同步原语,用于在 goroutine 之间协调执行顺序。它提供了一种 goroutine 可以等待某个条件满足的机制,并在条件满足时通知等待的 goroutine。

以下是一个简单的例子,展示了如何使用 sync.Cond 来实现生产者-消费者模型:

package mainimport ("fmt""sync""time"
)type Queue struct {items []intcond  *sync.Cond
}func NewQueue() *Queue {return &Queue{items: make([]int, 0),cond:  sync.NewCond(&sync.Mutex{}),}
}func (q *Queue) Enqueue(item int) {q.cond.L.Lock()q.items = append(q.items, item)fmt.Printf("Produced: %d\n", item)q.cond.L.Unlock()q.cond.Signal() // Notify one waiting goroutine that an item has been added
}func (q *Queue) Dequeue() int {q.cond.L.Lock()for len(q.items) == 0 {q.cond.Wait() // Wait until there is an item to consume}item := q.items[0]q.items = q.items[1:]q.cond.L.Unlock()fmt.Printf("Consumed: %d\n", item)return item
}func main() {queue := NewQueue()// Producergo func() {for i := 0; i < 5; i++ {queue.Enqueue(i)time.Sleep(time.Second)}}()// Consumergo func() {for i := 0; i < 5; i++ {queue.Dequeue()time.Sleep(2 * time.Second)}}()// Wait for goroutines to finishtime.Sleep(10 * time.Second)
}代码说明:
Queue 结构体:包含一个整数切片 items 和一个 sync.Cond。sync.Cond 用于在队列为空时阻塞消费者 goroutine。
NewQueue 函数:初始化一个 Queue 实例,使用 sync.NewCond 创建一个新的条件变量,绑定一个 sync.Mutex。
Enqueue 方法:加锁后将新项添加到队列,并使用 Signal 方法通知一个等待的 goroutine 有新数据可用。Signal 方法只唤醒一个等待的 goroutine。如果需要唤醒所有等待的 goroutine,可以使用 Broadcast 
Dequeue 方法:加锁后检查队列是否为空,如果为空则调用 Wait 方法阻塞当前 goroutine,直到被 Signal 或 Broadcast 唤醒。在被唤醒后,继续执行,取出队列的第一个
生产者和消费者 goroutine:生产者定期向队列中添加数据。消费者从队列中取数据并
通过这种方式,sync.Cond 可以有效地协调多个 goroutine 的执行顺序,确保生产者和消费者之间的正确同步。

errgroup

errgroup 是 Go 语言标准库中的一个包,提供了一种方便的方式来管理一组并发任务,并收集它们中的第一个错误。它通常用于需要并发执行多个任务并等待所有任务完成的场景。

package mainimport ("context""errors""fmt""golang.org/x/sync/errgroup""time"
)func main() {// 创建一个带有上下文的 errgroupg, ctx := errgroup.WithContext(context.Background())// 模拟的任务列表tasks := []int{1, 2, 3, 4, 5}// 为每个任务启动一个 goroutinefor _, task := range tasks {// 捕获 task 变量task := taskg.Go(func() error {// 模拟任务执行fmt.Printf("Starting task %d\n", task)time.Sleep(time.Duration(task) * time.Second)// 模拟一个错误发生在任务 3if task == 3 {return errors.New("error in task 3")}fmt.Printf("Completed task %d\n", task)return nil})}// 等待所有任务完成if err := g.Wait(); err != nil {fmt.Printf("Encountered error: %v\n", err)} else {fmt.Println("All tasks completed successfully")}
}

golang type optionFunc func(*config) 的用法

在 Go 语言中,type optionFunc func(*config) 定义了一种函数类型 optionFunc,它是一个函数签名,接受一个指向 config 结构体的指针作为参数,并且没有返回值。这个模式通常用于实现可选配置(option pattern),使得代码在创建对象时可以灵活地应用不同的配置选项。

这种模式通常用于构建器模式(builder pattern)或函数选项模式(functional options pattern),以便为对象提供可选的配置参数,而不是通过大量的构造函数或初始化函数来处理各种配置组合。

package mainimport ("fmt"
)// 定义一个配置结构体
type config struct {host stringport int
}// 定义一个函数类型,用于修改配置
type optionFunc func(*config)// 应用选项函数以修改配置
func newConfig(opts ...optionFunc) *config {cfg := &config{host: "localhost", // 默认值port: 8080,        // 默认值}for _, opt := range opts {opt(cfg)}return cfg
}// 定义具体的选项函数
func withHost(host string) optionFunc {return func(cfg *config) {cfg.host = host}
}func withPort(port int) optionFunc {return func(cfg *config) {cfg.port = port}
}func main() {// 创建一个配置对象,使用默认值defaultConfig := newConfig()fmt.Printf("Default config: host=%s, port=%d\n", defaultConfig.host, defaultConfig.port)// 创建一个配置对象,使用自定义选项customConfig := newConfig(withHost("example.com"),withPort(9090),)fmt.Printf("Custom config: host=%s, port=%d\n", customConfig.host, customConfig.port)
}
代码说明
配置结构体: config 结构体包含两个字段 host 和 port,用来存储配置数据。、
选项函数类型: optionFunc 是一个函数类型,定义了接受一个 *config 类型的指针参数的函数。
创建配置函数: newConfig 函数接受可变参数 opts ...optionFunc,这些参数用于修改默认配置。
选项函数: withHost 和 withPort 是两个具体的选项函数,返回一个 optionFunc 类型的函数,用于修改配置中的 host 和 port。
使用示例: 在 main 函数中,演示了如何使用默认配置和自定义选项来创建配置对象。

这种模式的优点是可以灵活地添加新的配置选项,而不需要修改现有的代码结构,使得代码更加可维护和可扩展。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com