golang oncefunc.go 的 OnceFunc 和 once.go Do 的区别
sync.Once 的 Do 方法和 OnceFunc/OnceValue/OnceValues 函数的主要区别在于使用场景和灵活性:
1、直接使用Once.Do(f):
更基础、低级的 API。你需要显式声明一个 sync.Once 变量,然后在其上调用 Do(f)方法来执行函数f。
仅保证函数f执行一次,但不直接提供函数的返回值管理或处理f中可能发生的 panic 的机制。
提供给用户更多的控制权,比如你可以决定在哪里初始化 Once 变量,以及如何围绕 Do 调用编写额外的逻辑。
示例:https://github.com/farwish/go-lab/blob/master/src/sync/once.go
2、OnceFunc, OnceValue, 和 OnceValues:
高级封装,提供了更方便的 API 来处理函数的单次执行,特别是当涉及到返回值或 panic 处理时。
自动管理了 sync.Once 实例,无需用户直接操作 Once 变量。
对于有返回值的情况(如OnceValue和OnceValues),它们处理了存储和返回首次调用的结果。
特别地,它们都妥善处理了函数 fpanic 的情况,确保在并发调用时 panic 行为一致且可预测,要么首次调用时立即重新 panic,要么在后续调用时再次 panic 同样的值。
示例:https://github.com/farwish/go-lab/blob/master/src/sync/oncefunc.go
总结来说,如果你需要简单的单次执行保证,直接使用 Once.Do 就足够了。
但如果你需要更复杂的特性,如自动管理返回值或统一处理 panic,那么 OnceFunc, OnceValue, 和 OnceValues 提供了更加便捷和高级的解决方案。