V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
yujianwjj
V2EX  ›  Go 编程语言

go 如何实现反序列提供默认值

  •  
  •   yujianwjj · 2023-11-22 03:14:17 +08:00 · 2026 次点击
    这是一个创建于 401 天前的主题,其中的信息可能已经有所发展或是发生改变。
    type ServerConfig struct {
    	URL string
    	Timeout time.Duration
        Size int
        A  int
        B int
        C int
    }
    

    ServerConfig 是从配置文件反序列化出来的,里面的变量如果配置文件没有提供的话,很多变量都是零值, 但是我期望里面的很多变量都是我自己定义的一个默认值。

    我现在的做法是反序列化后再一个一个的判断,如果是零值,就改成我期望的值,这样感觉比较麻烦,有什么其他更好的方法吗?

    14 条回复    2023-11-22 12:59:00 +08:00
    blackcurrant
        1
    blackcurrant  
       2023-11-22 03:33:20 +08:00
    使用 viper 读取配置。
    然后类似这样定义
    type RPCConfig struct {
    Host string `mapstructure:"host"`
    Port int `mapstructure:"port"`
    // 使用默认值
    Timeout int `mapstructure:"timeout,default=30"`
    }
    mornlight
        2
    mornlight  
       2023-11-22 05:31:40 +08:00
    做配置管理的第三方库很多都支持 default tag 。
    如果觉得不好用可以先用这个库 Set 一遍 github.com/creasty/defaults
    8X96ZltB8D7WggD7
        3
    8X96ZltB8D7WggD7  
       2023-11-22 08:38:04 +08:00
    先赋默认值,再反序列化
    CyJaySong
        4
    CyJaySong  
       2023-11-22 08:38:22 +08:00   ❤️ 2
    试试这样写呢
    serverConfig := ServerConfig{
    URL: "www.baidu.com",
    }
    _ = json.Unmarshal(bytes, &serverConfig)
    yuancoder
        5
    yuancoder  
       2023-11-22 09:16:40 +08:00
    一般是通过 tag 实现的
    ikaros
        6
    ikaros  
       2023-11-22 09:17:55 +08:00
    我的看法是为了这么简单的需求引入一个新的库不值(你甚至只用了他的很少功能),如果是基于 tag 的反射还影响性能, 个人解决方法偏向于给这个 struct 写个 SetDefaultValue 的方法,unmarshal 完之后调用一下
    ding2dong
        7
    ding2dong  
       2023-11-22 09:24:13 +08:00   ❤️ 1
    func GetDefaultServerConfig() ServerConfig {
    return ServerConfig{
    // 你的一些默认值...
    }
    }

    //读取配置
    serverConfig := GetDefaultServerConfig()
    json.Unmarshal([]byte(jsonStr), &serverConfig)
    Shijamlin
        8
    Shijamlin  
       2023-11-22 09:27:46 +08:00
    @ikaros 同意
    dw2693734d
        9
    dw2693734d  
       2023-11-22 09:28:34 +08:00
    @CyJaySong 这种比较简单,我也这样用
    fo0o7hU2tr6v6TCe
        10
    fo0o7hU2tr6v6TCe  
       2023-11-22 09:30:05 +08:00
    https://blog.51cto.com/hongchen99/4520434 tag 实现,重写方法?
    CzaOrz
        11
    CzaOrz  
       2023-11-22 09:45:09 +08:00
    看着有点眼熟,可以参考我自己写的一个工具库,原理就是基于反射解析 Tag 然后赋值即可:

    - https://github.com/czasg/go-fill

    ```go
    // 依赖
    import "github.com/czasg/go-fill"
    // 准备结构体
    type Config struct {
    Host string `fill:"HOST,default=localhost"`
    Port int `fill:"PORT,default=5432"`
    User string `fill:"USER,default=root"`
    Password string `fill:"PASSWORD,default=root"`
    }
    // 初始化
    cfg := Config{}
    // 填充环境变量
    _ = fill.FillEnv(&cfg)
    ```
    yujianwjj
        12
    yujianwjj  
    OP
       2023-11-22 10:02:10 +08:00
    ```
    type Config struct {
    ServerConfigs []ServerConfig
    }
    ```

    如果 先赋默认值,再反序列化的话。针对这个情况咋搞?
    fantastM
        13
    fantastM  
       2023-11-22 11:37:13 +08:00
    @yujianwjj #12 如果解析的是 yaml 配置的话,可以试试这种方式

    https://github.com/go-yaml/yaml/issues/165#issuecomment-255223956
    yujianwjj
        14
    yujianwjj  
    OP
       2023-11-22 12:59:00 +08:00 via iPhone
    嗯,确实是 yaml ,感谢 @fantastM
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1345 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:49 · PVG 07:49 · LAX 15:49 · JFK 18:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.