MST

星途 面试题库

面试题:Go语言中sync.Once在插件加载应用中的基本原理

请阐述在Go语言中,sync.Once方法的基本原理,并且说明它如何在插件加载场景中保证只执行一次初始化操作。
17.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

sync.Once基本原理

  1. 数据结构sync.Once 结构体只有一个字段 done uint32,以及一个未导出的互斥锁 m sync.Mutex
type Once struct {
    done uint32
    m    sync.Mutex
}
  1. Do方法Once.Do(f func()) 方法用来确保函数 f 只被执行一次。
    • 首先检查 done 字段,如果 done 已经被设置(值不为0),则直接返回,说明初始化操作已经完成,无需再次执行 f
    • 如果 done 为0,获取互斥锁 m,再次检查 done(双重检查锁定),因为在获取锁之前,其他协程可能已经完成了初始化。
    • done 仍然为0,则执行函数 f,执行完后将 done 设置为1,表示初始化已完成,最后释放互斥锁。

在插件加载场景中的应用

  1. 场景描述:在插件加载时,通常有一些初始化操作,如初始化数据库连接、配置加载等,这些操作只需要执行一次。
  2. 保证只执行一次初始化
    • 可以在插件加载的代码中定义一个 sync.Once 实例,例如:
var once sync.Once
func loadPlugin() {
    // 初始化操作,例如连接数据库、加载配置文件等
    println("Plugin initialized")
}
func GetPlugin() {
    once.Do(loadPlugin)
    // 插件使用相关代码
}
- 不同的协程在调用 `GetPlugin` 时,`loadPlugin` 函数只会被执行一次。因为 `sync.Once` 的机制保证了无论有多少个协程并发调用 `once.Do(loadPlugin)`,`loadPlugin` 函数只会在第一次调用时执行,后续调用直接返回,从而确保插件初始化操作只执行一次。