Go语言中的接口和容器使用

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

Go Interface/Container usage

问题

新手Go程序员在这里。我正在编写一个读取JSON配置文件的包。当然,它使用了内置的JSON解码器。但是我希望它能够包含其他的JSON文件,通过查找一个带有键为'Includes'的文件名数组。我已经将其作为一个函数工作,并传入一个包含了一个标记为'Includes'的字符串切片的JSON数据的结构体,但我不知道如何将其指定为一个包。

以下是该函数的代码:

func ReadConfig(filename string, configuration *Configuration) error {
  log.Println("reading file", filename)
  file, err := os.Open(filename)
  if err != nil {
    log.Println("Can't read", filename)
    return err
  }
  decoder := json.NewDecoder(file)
  if err := decoder.Decode(&configuration); err != nil {
    log.Println(err)
    return err
  }

  includes := make([]string, len(configuration.Includes))
  copy(includes, configuration.Includes)
  configuration.Includes = configuration.Includes[0:0]
  for _, inc := range includes {
    log.Println(inc)
    if err := ReadConfig(inc, configuration); err != nil {
      return err
    }
  }

  return nil
}

这段代码可以与以下结构体一起使用:

type Configuration struct {
  Includes []string
  .... 其他定义
}

但是,在一个包中,我希望ReadConfig函数可以接受任何类型的Configuration结构体,只要其中一个成员是'Includes []string'。

我认为我需要将ReadConfig函数的定义更改为:

func ReadConfig(filename string, configuration interface{})

但我不知道如何在其中访问Includes切片。

英文:

Newbie Go programmer here. I'm writing a package that reads a JSON configuration file. It uses the built-in JSON decoding, of course. But I want it to be able to include other JSON files as well, by looking for an array of filenames with the key of 'Includes'. I got it working as just a function and passing in a struct for the JSON data that includes a slice of strings labeled 'Includes', but I don't know how to specify this as a package.

Here's the function:

func ReadConfig(filename string, configuration *Configuration) error {

  log.Println("reading file", filename)
  file, err := os.Open(filename)
  if err != nil {
    log.Println("Can't read", filename)
    return err
  }
  decoder := json.NewDecoder(file)
  if err := decoder.Decode(&configuration); err != nil {
    log.Println(err)
    return err
  }

  includes := make([]string, len(configuration.Includes))
  copy(includes, configuration.Includes)
  config.Includes = configuration.Includes[0:0]
  for _, inc := range includes {
    log.Println(inc)
    if err := ReadConfig(inc, configuration); err != nil {
      return err
    }
  }

  return nil
}

Which works with:

type Configuration struct {
  Includes []string
  .... other defs
}

But, in a package, I want ReadConfig to take any kind Configuration struct, as long as one of its members is 'Includes []string'.

I believe I need to change the ReadConfig def to:

func ReadConfig(filename string, configuration interface{})

But what I don't know is how to access the Includes slice within that.

答案1

得分: 3

只需为其创建一个接口

type Configurable interface {
    Configuration() []string
}

然后为你的结构体提供一个 Configuration 方法而不是字段,并将函数的签名更改为 func ReadConfig(filename string, configuration Configurable)

不过,直接传递切片而不是结构体会更容易一些。

英文:

Just create an interface for it

type Configurable interface {
    Configuration() []string
}

And then provide a Configuration method instead of a field for your structs, and change the signature of your function to func ReadConfig(filename string, configuration Configurable).

It'd be much easier to just pass in the slice instead of the struct though.

huangapple
  • 本文由 发表于 2014年1月23日 05:54:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/21294797.html
匿名

发表评论

匿名网友

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

确定