drfu29983 2017-03-12 03:56
浏览 68
已采纳

使用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 :(

Any help is appreciated.

  • 写回答

1条回答 默认 最新

  • dousonghs58612 2017-03-12 06:34
    关注

    By defining the configuration file type and using viper.Unmarshal you can cast the interface to 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
    ", 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
    ", h.Name, h.Port, h.Key)
        }
    }
    

    Run:

    $ go run main.go
    Name: host1, Port: 90, Key: my_key
    Name: host2, Port: 90, Key: prompt
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

悬赏问题

  • ¥50 代码还没怎么运行但是需要代码功能调用数据
  • ¥15 vue请求不到数据,返回状态200,数据为html
  • ¥15 访问url时不会自动调用其 Servlet的doGet()
  • ¥15 用白鹭引擎开发棋牌游戏的前端为什么这么难找
  • ¥35 哪位专业人士知道这是什么原件吗?哪里可以买到?
  • ¥15 关于#c##的问题:treenode反序列化后获取不到上一节点和下一节点,Fullpath和Handle报错
  • ¥15 一部手机能否同时用不同的app进入不同的直播间?
  • ¥20 输入import torch显示Intel MKL FATAL ERROR,系统驱动1%,: Cannot load mkl_intel_thread.dll.
  • ¥15 点云密度大则包围盒小
  • ¥15 nginx使用nfs进行服务器的数据共享
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部