亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么 YAML.v3 不編組基于 golang 中的 String() 的結構?

為什么 YAML.v3 不編組基于 golang 中的 String() 的結構?

Go
喵喔喔 2023-02-21 12:54:46
我有一個包含基于枚舉的類型的結構。我正在嘗試將其呈現為用戶友好的字符串。這是最小可行代碼:package mainimport (    "fmt"    "gopkg.in/yaml.v3")type Job struct {    Engine Engine `json:"Engine" yaml:"Engine"`}//go:generate stringer -type=Engine --trimprefix=Enginetype Engine intconst (    engineUnknown Engine = iota // must be first    EngineDocker    engineDone // must be last)func main() {    j := Job{Engine: EngineDocker}    fmt.Printf("%+v\n\n", j)    out, _ := yaml.Marshal(j)    fmt.Println(string(out))}這是生成的代碼:// Code generated by "stringer -type=Engine --trimprefix=Engine"; DO NOT EDIT.package mainimport "strconv"func _() {    // An "invalid array index" compiler error signifies that the constant values have changed.    // Re-run the stringer command to generate them again.    var x [1]struct{}    _ = x[engineUnknown-0]    _ = x[EngineDocker-1]    _ = x[engineDone-2]}const _Engine_name = "engineUnknownDockerengineDone"var _Engine_index = [...]uint8{0, 13, 19, 29}func (i Engine) String() string {    if i < 0 || i >= Engine(len(_Engine_index)-1) {        return "Engine(" + strconv.FormatInt(int64(i), 10) + ")"    }    return _Engine_name[_Engine_index[i]:_Engine_index[i+1]]}這是輸出:{Engine:1}Engine: 1這是我想要的輸出:{Engine:Docker}Engine: Docker我認為生成文件中的 String() 可以完成此操作。有什么辦法嗎?謝謝!
查看完整描述

1 回答

?
隔江千里

TA貢獻1906條經驗 獲得超10個贊

yaml封送拆收器不使用String方法。相反,YAML使用 encoding.TextMarshalerencoding.TextUnmarshaler接口。實際上,所有其他編解碼器方案——JSON、XML、TOML 等——都使用這些接口來讀取/寫入值。因此,如果您為您的類型實現這些方法,您將免費獲得所有其他編解碼器。

這是一個如何為您的枚舉制作人類可讀編碼的示例:https://go.dev/play/p/pEcBmAM-oZJ

type Engine int


const (

    engineUnknown Engine = iota // must be first

    EngineDocker

    engineDone // must be last

)


var engineNames []string

var engineNameToValue map[string]Engine


func init() {

    engineNames = []string{"Unknown", "Docker"}

    engineNameToValue = make(map[string]Engine)

    for i, name := range engineNames {

        engineNameToValue[strings.ToLower(name)] = Engine(i)

    }

}


func (e Engine) String() string {

    if e < 0 || int(e) >= len(engineNames) {

        panic(fmt.Errorf("Invalid engine code: %d", e))

    }

    return engineNames[e]

}


func ParseEngine(text string) (Engine, error) {

    i, ok := engineNameToValue[strings.ToLower(text)]

    if !ok {

        return engineUnknown, fmt.Errorf("Invalid engine name: %s", text)

    }

    return i, nil

}


func (e Engine) MarshalText() ([]byte, error) {

    return []byte(e.String()), nil

}


func (e *Engine) UnmarshalText(text []byte) (err error) {

    name := string(text)

    *e, err = ParseEngine(name)

    return

}

怎么運行的:


func main() {

    j := Job{Engine: EngineDocker}


    fmt.Printf("%#v\n\n", j)

    out, err := yaml.Marshal(j)

    if err != nil {

        panic(err)

    }

    fmt.Printf("YAML: %s\n", string(out))


    var jj Job

    err = yaml.Unmarshal(out, &jj)

    if err != nil {

        panic(err)

    }

    fmt.Printf("%#v\n\n", jj)


    // == JSON ==

    out, err = json.Marshal(j)

    if err != nil {

        panic(err)

    }

    fmt.Printf("JSON: %s\n", string(out))


    var jjs Job

    err = json.Unmarshal(out, &jjs)

    if err != nil {

        panic(err)

    }

    fmt.Printf("%#v\n\n", jjs)


}

輸出


main.Job{Engine:1}


YAML: Engine: Docker


main.Job{Engine:1}


JSON: {"Engine":"Docker"}

main.Job{Engine:1}

看?它無需任何額外工作即可將字符串寫入 YAML 和 JSON 并從中讀取。


查看完整回答
反對 回復 2023-02-21
  • 1 回答
  • 0 關注
  • 157 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號