Golang接口和接收器 – 需要建议

huangapple go评论95阅读模式
英文:

Golang interfaces and receivers - advice needed

问题

我正在尝试将我的 Golang 配置加载器类从特定的配置文件结构转换为更通用的结构。最初,我定义了一个包含一组特定于程序的变量的结构体,例如:

type WatcherConfig struct {
    FileType   string
    Flag       bool
    OtherType  string
    ConfigPath string
}

然后,我使用指针接收器定义了两个方法:

func (config *WatcherConfig) LoadConfig(path string) error {}

func (config *WatcherConfig) Reload() error {}

我现在尝试使其更通用,计划是定义一个接口 Config,并在接口上定义 LoadConfigReload 方法。然后,我可以为每个需要配置的模块创建一个具有相应配置布局的结构体,避免重复编写一个基本上打开文件、读取 JSON 并将其转储到结构体中的方法。

我尝试创建了一个接口并定义了一个方法,如下所示:

type Config interface {
    LoadConfig(string) error
}
func (config *Config) LoadConfig(path string) error {}

但是,这显然会引发错误,因为 Config 不是一个类型,而是一个接口。我需要向我的类中添加一个更抽象的结构体吗?值得注意的是,所有配置结构体都将具有 ConfigPath 字段,因为我使用它来重新加载配置。

我相当确定我正在错误的方向上进行尝试,或者我尝试的方式在 Go 中不起作用。我真的很希望能得到一些建议!

  • 在 Go 中,我正在尝试的做法是否可行?
  • 在 Go 中,这是一个好主意吗?
  • 有什么替代的 Go 语言方式吗?
英文:

I'm trying to convert my config loader class in Golang from a specific config file structure to a more general one. Originally, I defined a struct with a set of program-specific variables, for example:

type WatcherConfig struct {
    FileType   string
    Flag       bool
    OtherType  string
    ConfigPath string
}

I then defined two methods with pointer receivers:

func (config *WatcherConfig) LoadConfig(path string) error {}

and

func (config *WatcherConfig) Reload() error {}

I'm now attempting to make this more general, and the plan was to define an interface Config and define the LoadConfig and Reload methods on this. I could then create a struct with the config layout for each module that needed it, and save myself repeating a method that basically opens a file, reads JSON, and dumps it into a struct.

I've tried creating an interface and defining a method like this:

type Config interface {
    LoadConfig(string) error
}
func (config *Config) LoadConfig(path string) error {}

But that is obviously throwing errors as Config is not a type, it's an interface. Do I need to add a more abstract struct to my class? It may be useful to know that all configuration structs will have the ConfigPath field, as I use this to Reload() the config.

I'm fairly sure I'm going about this the wrong way, or what I'm trying to do isn't a pattern that works nicely in Go. I'd really appreciate some advice!

  • Is what I'm trying to do possible in Go?
  • Is it a good idea in Go?
  • What would be the alternative Go-ism?

答案1

得分: 3

即使您使用_embedding_来处理接口和实现,Config.LoadConfig()的实现也无法知道嵌入它的类型(例如WatcherConfig)。

最好的方法是将其实现为简单的_helper_或_factory_函数。

您可以这样做:

func LoadConfig(path string, config interface{}) error {
    // 加载实现
    // 例如,您可以将文件内容解组到config变量中(如果是指针)
}

func ReloadConfig(config Config) error {
    // 重新加载实现
    path := config.Path() // Config接口可能有一个Path()方法
    // 例如,您可以将文件内容解组到config变量中(如果是指针)
}
英文:

Even if you'd use embedding both the interfaces and the implementations, the implementation of Config.LoadConfig() cannot know about the type that embeds it (e.g. WatcherConfig).

Best would be not to implement this as methods but as simple helper or factory functions.

You could do it like this:

func LoadConfig(path string, config interface{}) error {
    // Load implementation
    // For example you can unmarshal file content into the config variable (if pointer)
}

func ReloadConfig(config Config) error {
    // Reload implementation
    path := config.Path() // Config interface may have a Path() method
    // for example you can unmarshal file content into the config variable (if pointer)
}

huangapple
  • 本文由 发表于 2015年4月7日 17:56:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/29488764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定