面试题答案
一键面试设计思路
- 定义全局变量:使用
sync.Once
类型的变量来控制服务初始化的单次执行。 - 分层初始化:由于服务 A 依赖服务 B 和 C,首先要确保 B 和 C 正确初始化,然后再初始化 A。对于 B 和 C 之间复杂的依赖关系,通过合理安排
sync.Once
的执行顺序来处理。 - 利用通道:为了确保初始化完成后才进行下一步操作,可以使用通道(
channel
)来同步不同服务初始化的完成状态。
关键代码示例
package main
import (
"fmt"
"sync"
)
// 模拟服务B和C的初始化结果
var (
resultB string
resultC string
)
// 定义sync.Once变量
var (
onceB sync.Once
onceC sync.Once
onceA sync.Once
)
// 模拟服务B的初始化函数
func initServiceB() {
// 实际初始化逻辑,例如数据库连接,配置加载等
resultB = "Service B initialized"
fmt.Println(resultB)
}
// 模拟服务C的初始化函数
func initServiceC() {
// 实际初始化逻辑,例如数据库连接,配置加载等
resultC = "Service C initialized"
fmt.Println(resultC)
}
// 模拟服务A的初始化函数,依赖服务B和C的结果
func initServiceA() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
onceB.Do(initServiceB)
wg.Done()
}()
go func() {
onceC.Do(initServiceC)
wg.Done()
}()
go func() {
wg.Wait()
// 这里可以使用resultB和resultC进行服务A的初始化
resultA := fmt.Sprintf("Service A initialized with B: %s and C: %s", resultB, resultC)
fmt.Println(resultA)
}()
}
func main() {
// 模拟多次启动服务A
for i := 0; i < 3; i++ {
onceA.Do(initServiceA)
}
}
在上述代码中:
onceB
、onceC
和onceA
分别用于控制服务 B、C 和 A 的初始化。initServiceB
和initServiceC
是模拟服务 B 和 C 的初始化函数。initServiceA
函数中,通过sync.WaitGroup
等待服务 B 和 C 初始化完成后,再利用 B 和 C 的初始化结果来完成自身的初始化。- 在
main
函数中,通过onceA.Do(initServiceA)
多次调用确保服务 A 只会初始化一次。