ホームページ >バックエンド開発 >Golang >Go でカスタムの Time 型エイリアスを印刷すると予期しない出力が生成されるのはなぜですか?また、それを修正するにはどうすればよいですか?

Go でカスタムの Time 型エイリアスを印刷すると予期しない出力が生成されるのはなぜですか?また、それを修正するにはどうすればよいですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-10-30 15:18:42406ブラウズ

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 を解析するときは、文字列を使用した手動解析を避けてください。代わりに、適切なデコードのために 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。