使用Viper语言处理接口的工作

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

Working with interfaces using Viper language

问题

我正在使用ViperCobra构建一个小应用程序。目前,我有一个像这样的yaml文件:

hosts:
  - name: host1
    port: 90
    key: my_key
  - name: host2
    port: 90
    key: prompt

我使用Viper读取了配置文件。

当我运行viper.Get("hosts")时,它返回一个接口(或接口切片?)。这是我得到的数据结构:

([]interface {}) (len=2 cap=2) {
 (map[interface {}]interface {}) (len=3) {
  (string) (len=4) "name": (string) (len=20) "host1",
  (string) (len=4) "port": (int) 90,
  (string) (len=3) "key": (string) (len=6) "my_key"
 },
 (map[interface {}]interface {}) (len=3) {
  (string) (len=3) "key": (string) (len=6) "prompt",
  (string) (len=4) "name": (string) (len=20) "host2",
  (string) (len=4) "port": (int) 90
 }
}

我想做的是遍历数组的每个元素,并使用name、port和key的值执行操作。

我对Golang中的接口完全不熟悉,所以这并不清楚,而且关于这方面的文献非常令人困惑 使用Viper语言处理接口的工作

感谢任何帮助。

英文:

I am building a little app using Viper and Cobra. At the moment, I have a yaml file like this:

hosts:
  - name: host1
    port: 90
    key: my_key
  - name: host2
    port: 90
    key: prompt

And I've read in the config file using Viper.

When I run viper.Get("hosts") it returns an interface (or a slice of interfaces?). This is the data structure I end up with:

([]interface {}) (len=2 cap=2) {
 (map[interface {}]interface {}) (len=3) {
  (string) (len=4) "name": (string) (len=20) "host1",
  (string) (len=4) "port": (int) 90,
  (string) (len=3) "key": (string) (len=6) "my_key"
 },
 (map[interface {}]interface {}) (len=3) {
  (string) (len=3) "key": (string) (len=6) "prompt",
  (string) (len=4) "name": (string) (len=20) "host2",
  (string) (len=4) "port": (int) 90
 }
}

What I'd like to do here is loop over each of the array elements and perform an operation using the values of name, port and key.

I'm completely new to interfaces in Golang, so this isn't very clear, and the literature on this is extremely confusing 使用Viper语言处理接口的工作

Any help is appreciated.

答案1

得分: 10

通过定义配置文件类型并使用viper.Unmarshal,您可以将接口转换为所需的特定类型。这里是一个示例:

main.go

package main

import (
	"fmt"

	"github.com/spf13/viper"
)

type Host struct {
	Name string
	Port int
	Key  string
}

type Config struct {
	Hosts []Host
}

func main() {
	viper.AddConfigPath("./")
	viper.SetConfigName("test")
	viper.ReadInConfig()
	var config Config
	err := viper.Unmarshal(&config)
	if err != nil {
		panic("无法解析配置")
	}
	for _, h := range config.Hosts {
		fmt.Printf("Name: %s, Port: %d, Key: %s\n", h.Name, h.Port, h.Key)
	}
}

test.yml

hosts:
  - name: host1
    port: 90
    key: my_key
  - name: host2
    port: 90
    key: prompt

运行:

$ go run main.go
Name: host1, Port: 90, Key: my_key
Name: host2, Port: 90, Key: prompt

如果您只想解码某些键,而不是整个配置文件,请使用viper.UnmarshalKey

main.go

package main

import (
	"fmt"

	"github.com/spf13/viper"
)

type Host struct {
	Name string
	Port int
	Key  string
}

func main() {
	viper.AddConfigPath("./")
	viper.SetConfigName("test")
	viper.ReadInConfig()
	var hosts []Host
	err := viper.UnmarshalKey("hosts", &hosts)
	if err != nil {
		panic("无法解析主机")
	}
	for _, h := range hosts {
		fmt.Printf("Name: %s, Port: %d, Key: %s\n", h.Name, h.Port, h.Key)
	}
}

运行:

$ go run main.go
Name: host1, Port: 90, Key: my_key
Name: host2, Port: 90, Key: prompt
英文:

By defining the configuration file type and using viper.Unmarshal you can cast the interface to the specific type you need. Here is an example:

main.go

package main

import (
	"fmt"

	"github.com/spf13/viper"
)

type Host struct {
	Name string
	Port int
	Key  string
}

type Config struct {
	Hosts []Host
}

func main() {
	viper.AddConfigPath("./")
	viper.SetConfigName("test")
	viper.ReadInConfig()
	var config Config
	err := viper.Unmarshal(&config)
	if err != nil {
		panic("Unable to unmarshal config")
	}
	for _, h := range config.Hosts {
		fmt.Printf("Name: %s, Port: %d, Key: %s\n", h.Name, h.Port, h.Key)
	}
}

test.yml

hosts:
  - name: host1
    port: 90
    key: my_key
  - name: host2
    port: 90
    key: prompt

Run:

$ go run main.go
Name: host1, Port: 90, Key: my_key
Name: host2, Port: 90, Key: prompt

If you want to decode only some keys, not the entire configuration file, use viper.UnmarshalKey.

main.go

package main

import (
	"fmt"

	"github.com/spf13/viper"
)

type Host struct {
	Name string
	Port int
	Key  string
}

func main() {
	viper.AddConfigPath("./")
	viper.SetConfigName("test")
	viper.ReadInConfig()
	var hosts []Host
	err := viper.UnmarshalKey("hosts", &hosts)
	if err != nil {
		panic("Unable to unmarshal hosts")
	}
	for _, h := range hosts {
		fmt.Printf("Name: %s, Port: %d, Key: %s\n", h.Name, h.Port, h.Key)
	}
}

Run:

$ go run main.go
Name: host1, Port: 90, Key: my_key
Name: host2, Port: 90, Key: prompt

huangapple
  • 本文由 发表于 2017年3月12日 19:56:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/42747085.html
匿名

发表评论

匿名网友

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

确定