kua*_*bin 3 yaml go unmarshalling
我有如下结构:
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'
    `
如上图,超时类型为time.Duration,默认单位为纳秒,但我想得到结果:c1 && c2有错误,c3 && c4有效(超时配置必须有单位)。我应该如何重写 yaml 的 UnmarshalYAML() 方法?非常感谢。
小智 6
time.Durationyaml.v3 中作品的解组, https://play.golang.org/p/-6y0zq96gVz
package main
import (
    "fmt"
    "time"
    
    "gopkg.in/yaml.v3"
)
type Config struct {
    Timeout time.Duration `yaml:"timeout"`
}
func main() {
    var cfg Config
    b := []byte(`timeout: 60s`)
    yaml.Unmarshal(b, &cfg)
    fmt.Printf("timeout: %dm", int(cfg.Timeout.Minutes()))
}
我会在UnmarshalYAML函数中创建一个别名类型,以便所有值都可以解组为某些原始类型。然后我将重写那些匹配的值并转换那些不匹配的值:
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\n", (i + 1), err)
            continue
        }
        fmt.Printf("c%d: %+v\n", (i + 1), c)
    }
}
输出如下所示:
$ 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}