在 Go 中,打印自定义 Time 类型别名时可能会遇到意外输出。了解行为需要进一步剖析问题。
考虑以下代码:
<code class="go">package main import ( "encoding/json" "fmt" "strings" "time" ) type Time time.Time func (st *Time) UnmarshalJSON(b []byte) error { s := strings.Trim(string(b), "\"") t, err := time.Parse(time.RFC3339, fmt.Sprintf("%s%s", s, "Z")) if err != nil { return fmt.Errorf("parse time: %w", err) } *st = Time(t) return nil } type User struct { Name string TS Time } const data = `{id: 3, name: "Name", ts: "2021-05-21T03:10:20.958450"}` func main() { user := new(User) json.Unmarshal([]byte(data), &user) fmt.Printf("%v\n", user) }</code>
运行此代码时,预期输出是格式化的时间值,类似于:
&{Name 2021-05-21 03:10:20.95845 +0000 UTC}
但是,实际输出显示为:
&{Name {958450000 63757163420 <nil>}}
出现差异是因为 Time 类型别名不实现 fmt.Stringer,导致默认格式化逻辑接管。此逻辑打印用大括号括起来的底层 time.Time 值的字段。
要解决此问题,请在委托给 time.Time.String 的 Time 类型中实现 String 方法。这将启用所需的格式化输出:
<code class="go">func (t Time) String() string { return time.Time(t).String() }</code>
另一个选项是将 time.Time 嵌入到 Time 类型中。这会自动提升 String 方法和其他方法(包括 Marshal*)。
<code class="go">type Time struct { time.Time } func (st *Time) UnmarshalJSON(b []byte) error { // ... unchanged ... st.Time = t // simple assignment without type conversion // ... unchanged ... }</code>
解析 JSON 时,避免使用 strings.Trim 手动解析;相反,使用 json.Unmarshal 进行正确解码。此外,使用 time.ParseInLocation:
<code class="go">func (st *Time) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { return err } t, err := time.ParseInLocation("2006-01-02T15:04:05", s, time.UTC) if err != nil { return err } // ... unchanged ... }</code>简化时间解析
以上是为什么在 Go 中打印自定义 Time 类型别名会产生意外输出,如何纠正?的详细内容。更多信息请关注PHP中文网其他相关文章!