在 Go Wire 注入中使用单例模式

Having a singleton pattern in Go Wire injection

我有一段代码用于从文件加载配置并将其解析为结构,我经常使用此配置,因此我在方法参数中传递它。现在,随着我的方法参数的增加,我正在研究依赖注入,并已经解决了问题。

现在我已经创建了一个提供程序来加载配置和一个注入器来提供配置结构。但是,每次我调用注入时,我的文件都会被再次读取,我希望文件被读取一次,并根据需要多次提供注入,而无需任何额外加载。

这是我的提供商:

// ProvideConfig config provider ...
func ProvideConfig() *config.FileConfig {
        var cfp string

        flag.StringVar(&cfp, "config", "config.json", "absolute path")
        flag.Parse()

    return config.Loadconfig(cfp)
}

喷油器:

// GetConfig injector ...
func GetConfig() ConfigResource {
    wire.Build(ProvideConfig, NewConfigResource)
    return ConfigResource{}
}

现在当我打电话时:

injection.GetConfig()

我看到 ProvideConfig 总是被调用。我可以检查 provide config 方法以确定配置是否已经加载,我不确定是否有更好的方法,比如内置在线路中的单个实例加载器。我尝试查看文档,但找不到任何相关内容。

据我所知,wire 中没有内置方法来指定提供程序是单例/只能调用一次。

这是通过使用 sync.Once 在 Go 中以通常的方式完成的。您的提供者函数可以是一个闭包,它只使用 sync.Once.Do 执行一次昂贵的操作。这在 Go 中是惯用的,并且不需要每个想要提供“单一”加载的库的任何特殊规定。

这是一个没有电线的例子:

type Value struct {
    id  int
    msg string
}

type ValueProvider func() *Value

// consumer takes a function that provides a new *Value and consumes
// the *Value provided by it.
func consumer(vp ValueProvider) {
    v := vp()
    fmt.Printf("Consuming %+v\n", *v)
}

// MakeSingleLoader returns a ValueProvider that creates a value once using an
// expensive operation, and then keeps returning the same value.
func MakeSingleLoader() ValueProvider {
    var v *Value
    var once sync.Once

    return func() *Value {
        once.Do(func() {
            v = ExpensiveOperation()
        })
        return v
    }
}

// ExpensiveOperation emulates an expensive operation that can take a while
// to run.
func ExpensiveOperation() *Value {
    return &Value{id: 1, msg: "hello"}
}

func main() {
    sl := MakeSingleLoader()
    consumer(sl)
    consumer(sl)
    consumer(sl)
}

如果您同意“单例”值是全局值,则可以稍微简化此代码。否则,它只会调用 ExpensiveOperation 一次,并将值缓存在 MakeSingleLoader.

之外无法访问的本地。