首页  >  文章  >  后端开发  >  为什么在 Go 中打印自定义 Time 类型别名会产生意外输出,如何纠正?

为什么在 Go 中打印自定义 Time 类型别名会产生意外输出,如何纠正?

Patricia Arquette
Patricia Arquette原创
2024-10-30 15:18:42321浏览

Why does printing a custom Time type alias in Go produce unexpected output, and how can it be corrected?

打印 Time.Time 类型别名时出现意外输出

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

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn