英文:
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.
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论