You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang中YAML.v3为何不基于String()方法序列化结构体?

解决Go枚举类型序列化友好字符串的问题

你的代码中stringer工具已正确生成String()方法,但输出数字的问题主要源于两点:fmt输出未正确调用String()(大概率是生成的代码未被纳入编译流程),以及yaml序列化默认不识别String()方法。

步骤1:确保String()方法被正确编译运行

stringer生成的代码需要被包含到编译环节中:

  • 执行go generate命令生成枚举的String()实现代码
  • 直接运行go run main.go,Go会自动包含同目录下所有Go文件,确保生成的代码被编译

若生成代码无误,fmt.Printf("%+v")会输出{Engine:Docker}——因为Engine类型实现了fmt.Stringer接口,%+v格式化会自动调用其String()方法。

步骤2:实现yaml序列化的友好字符串

yaml.v3默认通过反射序列化自定义类型的底层值(此处为int),不会自动调用String()方法。需为Engine类型实现yaml.Marshaler接口:

func (e Engine) MarshalYAML() (interface{}, error) {
    return e.String(), nil
}

添加该方法后,yaml序列化会输出友好的字符串形式。

可选优化:统一枚举常量命名

当前枚举中engineUnknown和engineDone为小写开头,--trimprefix=Engine不会处理这类命名,导致生成的字符串是engineUnknown而非Unknown。建议统一使用大写开头的命名:

const (
    EngineUnknown Engine = iota // must be first
    EngineDocker
    EngineDone // must be last
)

重新执行go generate后,String()方法会返回Unknown、Docker、Done,命名更规范。

修改后的完整代码

package main

import (
    "fmt"

    "gopkg.in/yaml.v3"
)

type Job struct {
    Engine Engine `json:"Engine" yaml:"Engine"`
}

//go:generate stringer -type=Engine --trimprefix=Engine
type Engine int

const (
    EngineUnknown Engine = iota // must be first
    EngineDocker
    EngineDone // must be last
)

func (e Engine) MarshalYAML() (interface{}, error) {
    return e.String(), nil
}

func main() {
    j := Job{Engine: EngineDocker}

    fmt.Printf("%+v\n\n", j)
    out, _ := yaml.Marshal(j)
    fmt.Println(string(out))
}

执行go generate后运行,输出会符合预期:

{Engine:Docker}

Engine: Docker

内容的提问来源于stack exchange,提问作者aronchick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 06:30:54