golang type conversion in unmarshaljson

huangapple go评论81阅读模式
英文:

golang type conversion in unmarshaljson

问题

有人可以帮我看看这里出了什么问题吗?由于某种原因,输出结果不一样,我不明白为什么。

type rTime time.Time

func (rt *rTime) UnmarshalJSON(data []byte) error {
    var s string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }

    t, err := time.Parse("2006-01-02", s)
    if err != nil {
        return err
    }
    log.Println(t)

    *rt = rTime(t)
    
    log.Println(*rt)
    return nil
}

日志输出如下:

2014/09/18 04:31:35 1999-10-15 00:00:00 +0000 UTC
2014/09/18 04:31:35 {63075542400 0 0x933ea0}

为什么转换没有起作用?输入的字符串是 1995-10-15

英文:

Could someone help me please what's going wrong here? For some reason the output are not the same and I don't get why.

type rTime time.Time

func (rt *rTime) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}

	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return err
	}
	log.Println(t)

	*rt = rTime(t)
	
	log.Println(*rt)
	return nil
}

Log looks like this:

2014/09/18 04:31:35 1999-10-15 00:00:00 +0000 UTC
2014/09/18 04:31:35 {63075542400 0 0x933ea0}

Why's the conversion not working? The input string is 1995-10-15 btw.

答案1

得分: 3

转换是有效的,但是fmt.Println()寻找一个String()方法,在time.Time上存在,但在你的类型上不存在。你只需要使用func (rt rTime) String() string { return time.Time(rt).String() }String()调用重定向到time.Time的实现即可。

这里有一个示例:

package main

import (
	"log"
	"time"
)

type rTime time.Time

func (rt rTime) String() string { return time.Time(rt).String() }

func main() {
	s := "1999-10-15"
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		panic(err)
	}
	log.Println(t)

	rt := rTime(t)

	log.Println(rt)
}

请注意,我将两种时间类型都视为值,因为标准库也是这样做的,根据规范建议,对于具有值语义的小结构体,应避免使用指针。

更有趣的是,你可以使用类型嵌入来自动获取time.Time的所有方法,除非你覆盖了其中的某些方法。语法稍有变化,如下所示:

package main

import (
	"log"
	"time"
)

type rTime struct { time.Time }

func main() {
	s := "1999-10-15"
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		panic(err)
	}
	log.Println(t)

	rt := rTime{t}

	log.Println(rt)
}

如果你使用了嵌入并且想要编写自己的自定义方法,以“代理”到嵌入类型的方法,你可以使用类似rt.Time.String()的语法:

// 添加笑脸的自定义String方法
func (rt rTime) String() string { return "😁 " + rt.Time.String() + " 😁" }

obj.EmbeddedTypeName也是你访问嵌入的非struct类型上的操作符的方式。

英文:

The conversion is working, but fmt.Println() looks for a String() method, and that exists on time.Time but not on your type. You should need nothing more than func (rt rTime) String() string { return time.Time(rt).String() } to direct String() calls back to time.Time's implementation.

Here's an example:

package main

import (
	"log"
	"time"
)

type rTime time.Time

func (rt rTime) String() string { return time.Time(rt).String() }

func main() {
	s := "1999-10-15"
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		panic(err)
	}
	log.Println(t)

	rt := rTime(t)

	log.Println(rt)
}

Note that I treated both time types as values because the standard library does, per the canonical advice to avoid pointers for tiny structs with value semantics.

Maybe more interesting, you can use type embedding to automagically pick up all of the methods of time.Time except any you override. The syntax changes slightly (see on Playground):

package main

import (
	"log"
	"time"
)

type rTime struct { time.Time }

func main() {
	s := "1999-10-15"
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		panic(err)
	}
	log.Println(t)

	rt := rTime{t}

	log.Println(rt)
}

If you've used embedding and want to write your own custom methods that "proxy through" to the embedded type's, you use a syntax like obj.EmbeddedTypeName.Method, which could be like, for instance, rt.Time.String():

// a custom String method that adds smiley faces
func (rt rTime) String() string { return "😁 " + rt.Time.String() + " 😁"  }

obj.EmbeddedTypeName is also how you (for example) access operators on non-struct types that you've embedded.

huangapple
  • 本文由 发表于 2014年9月18日 10:38:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/25903326.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定