如何在Golang Viper配置中正确表示天数时长以避免加载错误?
解决Golang配置中time.Duration不支持"d"单位的问题
问题背景
.env配置中的MAX_TOKEN_EXPIRY_DAYS=30d无法被Golang的time.Duration解析,因为标准库time包仅支持ns/us/ms/s/m/h这些单位,不包含天(d)。
可行解决方案
1. 直接转换为小时单位
将天数换算成小时(1天=24小时),修改.env配置:
MAX_TOKEN_EXPIRY_DAYS=720h ACCESS_TOKEN_DURATION=30m
原结构体无需修改,time.Duration可直接解析720h。
2. 用整数接收天数后转换
调整结构体,用int类型接收天数配置,加载后手动转换为time.Duration:
type AppConfig struct { MaxTokenExpiryDays int `mapstructure:"MAX_TOKEN_EXPIRY_DAYS"` AccessTokenDuration time.Duration `mapstructure:"ACCESS_TOKEN_DURATION"` } // 加载配置后转换 cfg := AppConfig{} // 假设已通过viper等工具加载配置到cfg maxTokenExpiry := time.Duration(cfg.MaxTokenExpiryDays) * 24 * time.Hour
.env配置保持MAX_TOKEN_EXPIRY_DAYS=30即可(无需加单位)。
3. 自定义支持"d"单位的Duration类型
实现自定义类型并支持UnmarshalText方法,让配置解析器能识别"d"单位:
import ( "strconv" "strings" "time" ) type DurationWithDays time.Duration func (d *DurationWithDays) UnmarshalText(text []byte) error { s := string(text) // 处理天单位 if strings.HasSuffix(s, "d") { daysStr := strings.TrimSuffix(s, "d") days, err := strconv.Atoi(daysStr) if err != nil { return err } *d = DurationWithDays(time.Duration(days) * 24 * time.Hour) return nil } // 兼容标准Duration单位 dur, err := time.ParseDuration(s) if err != nil { return err } *d = DurationWithDays(dur) return nil } // 修改结构体使用自定义类型 type AppConfig struct { MaxTokenExpiry DurationWithDays `mapstructure:"MAX_TOKEN_EXPIRY_DAYS"` AccessTokenDuration time.Duration `mapstructure:"ACCESS_TOKEN_DURATION"` } // 使用时转换为标准time.Duration expiry := time.Duration(cfg.MaxTokenExpiry)
这种方式可以保留.env中的30d写法,无需修改配置。
补充说明
标准库time.Duration不支持天单位,是因为天数并非固定的24小时(比如夏令时切换、闰年等场景),但在大多数业务场景下,按24小时/天换算完全满足需求。
内容的提问来源于stack exchange,提问作者Mayukh Sarkar
相关产品推荐
相关产品推荐

