在 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中文網其他相關文章!