duansha6410 2018-08-09 19:33
浏览 150
已采纳

yaml:解组错误:无法将字符串解组到时间中

I have struct as below:

type Connect struct {
     ClientID string `yaml:"clientid"`
     Password string `yaml:"password"`
     Timeout  time.Duration `yaml:"timeout"`
}

c1 := `
    id: 'client1'
    password: 'hhhhhhha'
    timeout: 10
    `

c2 := `
    id: 'client2'
    password: 'llllllla'
    timeout: '10'
    `

c3 := `
    id: 'client3'
    password: 'hhhhhhha'
    timeout: 10s
    `

c4 := `
    id: 'client4'
    password: 'llllllla'
    timeout: '10s'
    `

as shown above, type of Timeout is time.Duration, the default unit is Nanosecond, but I want to get the result: c1 && c2 has error, c3 && c4 is valid(the config of Timeout must have unit). How should I do to rewrite the UnmarshalYAML() Method for yaml? Thanks a lot.

  • 写回答

2条回答 默认 最新

  • drqn5418 2018-08-10 09:20
    关注

    I would create an aliased type in the UnmarshalYAML function so that all the values could be unmarshaled to some primitive types. Then I will rewrite those values that match and convert those which do not:

    package main
    
    import (
        "fmt"
        "time"
    
        "gopkg.in/yaml.v2"
    )
    
    type Connect struct {
        ClientID string        `yaml:"clientid"`
        Password string        `yaml:"password"`
        Timeout  time.Duration `yaml:"timeout"`
    }
    
    func (ut *Connect) UnmarshalYAML(unmarshal func(interface{}) error) error {
        type alias struct {
            ClientID string `yaml:"clientid"`
            Password string `yaml:"password"`
            Timeout  string `yaml:"timeout"`
        }
    
        var tmp alias
        if err := unmarshal(&tmp); err != nil {
            return err
        }
    
        t, err := time.ParseDuration(tmp.Timeout)
        if err != nil {
            return fmt.Errorf("failed to parse '%s' to time.Duration: %v", tmp.Timeout, err)
        }
    
        ut.ClientID = tmp.ClientID
        ut.Password = tmp.Password
        ut.Timeout = t
    
        return nil
    }
    
    func main() {
        c1 := `
    id: 'client1'
    password: 'hhhhhhha'
    timeout: 10
    `
    
        c2 := `
    id: 'client2'
    password: 'llllllla'
    timeout: '10'
    `
    
        c3 := `
    id: 'client3'
    password: 'hhhhhhha'
    timeout: 10s
    `
    
        c4 := `
    id: 'client4'
    password: 'llllllla'
    timeout: '10s'
    `
    
        cc := []string{c1, c2, c3, c4}
        for i, cstr := range cc {
            var c Connect
            err := yaml.Unmarshal([]byte(cstr), &c)
            if err != nil {
                fmt.Printf("Error for c%d: %v
    ", (i + 1), err)
                continue
            }
            fmt.Printf("c%d: %+v
    ", (i + 1), c)
        }
    }
    

    The output looks as follows:

    $ go run main.go
    Error for c1: failed to parse '10' to time.Duration: time: missing unit in duration10
    Error for c2: failed to parse '10' to time.Duration: time: missing unit in duration10
    c3: {ClientID: Password:hhhhhhha Timeout:10s}
    c4: {ClientID: Password:llllllla Timeout:10s}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码