英文:
Why is time in Go printed differently in a struct?
问题
我刚刚开始学习Go语言,在我写的第一个程序中,我打印了一个结构体,结果显示为:
{wall:0 ext:63533980800 loc:<nil>}
对于这是什么的困惑,我觉得它似乎是一个time.Time()
类型,通过谷歌搜索,我找到了Go源代码的这一部分,其中解释了“墙时钟”和“单调时钟”的区别。
为了在隔离环境中进行测试,我创建了一个新的简化程序:
package main
import (
"fmt"
"time"
)
type TheStruct struct {
the_time time.Time
}
func main() {
the_struct := TheStruct{time.Now()}
fmt.Println(the_struct)
fmt.Printf("%+v\n", the_struct)
fmt.Println(the_struct.the_time)
fmt.Println()
the_struct_2 := TheStruct{time.Unix(1505099248, 200)}
fmt.Println(the_struct_2)
fmt.Printf("%+v\n", the_struct_2)
fmt.Println(the_struct_2.the_time)
}
它打印出以下内容:
{{13719544904843884912 534246 0x1140680}}
{the_time:{wall:13719544904843884912 ext:534246 loc:0x1140680}}
2017-09-11 05:08:11.35635032 +0200 CEST m=+0.000534246
{{200 63640696048 0x1140680}}
{the_time:{wall:200 ext:63640696048 loc:0x1140680}}
2017-09-11 05:07:28 +0200 CEST
所以我对这里有两个疑问:
- 为什么作为结构体的时间部分以墙时钟的形式打印出来,而单独打印时使用更常见的日期时间表示法(使用
the_struct.the_time
)? - 我的另一个程序中的代码打印出
<nil>
表示loc,这是一个问题吗?我该如何解决它?
英文:
I'm just starting out with Go, and in the first program I wrote I printed out a struct, which also showed
{wall:0 ext:63533980800 loc:<nil>}
Being puzzled over what that was it seemed to be a type time.Time()
, and a google search brought me to this part of the Go source code in which the difference between the "wall clock" and the "monotonic clock" is explained in the comments.
So to test it in isolation I created a new minimalistic program:
package main
import (
"fmt"
"time"
)
type TheStruct struct {
the_time time.Time
}
func main() {
the_struct := TheStruct{time.Now()}
fmt.Println(the_struct)
fmt.Printf("%+v\n", the_struct)
fmt.Println(the_struct.the_time)
fmt.Println()
the_struct_2 := TheStruct{time.Unix(1505099248, 200)}
fmt.Println(the_struct_2)
fmt.Printf("%+v\n", the_struct_2)
fmt.Println(the_struct_2.the_time)
}
which prints out the following:
{{13719544904843884912 534246 0x1140680}}
{the_time:{wall:13719544904843884912 ext:534246 loc:0x1140680}}
2017-09-11 05:08:11.35635032 +0200 CEST m=+0.000534246
{{200 63640696048 0x1140680}}
{the_time:{wall:200 ext:63640696048 loc:0x1140680}}
2017-09-11 05:07:28 +0200 CEST
So I wonder about two things here:
- Why is the time if part of a struct printed as wall clock as compared to the more usual datetime notation when printed out separately (using
the_struct.the_time
)? - Is it a problem that the code in my other program prints out
<nil>
for the loc? How would I be able to solve that?
答案1
得分: 6
在你的结构体中,没有打印格式化时间的原因是未导出的字段没有调用String方法(参考https://golang.org/pkg/fmt/):
当打印结构体时,fmt无法并且因此不会调用未导出字段的格式化方法,如Error或String。
将你的结构体更改为导出字段(首字母大写)将会调用String方法:
package main
import (
"fmt"
"time"
)
type TheStruct struct {
The_time time.Time
}
func main() {
the_struct := TheStruct{time.Now()}
fmt.Println(the_struct)
fmt.Printf("%+v\n", the_struct)
fmt.Println(the_struct.The_time)
fmt.Println()
the_struct_2 := TheStruct{time.Unix(1505099248, 200)}
fmt.Println(the_struct_2)
fmt.Printf("%+v\n", the_struct_2)
fmt.Println(the_struct_2.The_time)
}
输出结果:
{2009-11-10 23:00:00 +0000 UTC m=+0.000000000}
{The_time:2009-11-10 23:00:00 +0000 UTC m=+0.000000000}
2009-11-10 23:00:00 +0000 UTC m=+0.000000000
{2017-09-11 03:07:28.0000002 +0000 UTC}
{The_time:2017-09-11 03:07:28.0000002 +0000 UTC}
2017-09-11 03:07:28.0000002 +0000 UTC
在playground上查看:https://play.golang.org/p/r0rQKBlpWc
英文:
The reason why it's not printing the formatted time when in your struct is that String method is not invoked on the unexported fields (refer https://golang.org/pkg/fmt/):
> When printing a struct, fmt cannot and therefore does not invoke
> formatting methods such as Error or String on unexported fields.
Changing your structure to export fields (capitalizing the first letter) makes it invoke the String method:
package main
import (
"fmt"
"time"
)
type TheStruct struct {
The_time time.Time
}
func main() {
the_struct := TheStruct{time.Now()}
fmt.Println(the_struct)
fmt.Printf("%+v\n", the_struct)
fmt.Println(the_struct.The_time)
fmt.Println()
the_struct_2 := TheStruct{time.Unix(1505099248, 200)}
fmt.Println(the_struct_2)
fmt.Printf("%+v\n", the_struct_2)
fmt.Println(the_struct_2.The_time)
}
Output:
{2009-11-10 23:00:00 +0000 UTC m=+0.000000000}
{The_time:2009-11-10 23:00:00 +0000 UTC m=+0.000000000}
2009-11-10 23:00:00 +0000 UTC m=+0.000000000
{2017-09-11 03:07:28.0000002 +0000 UTC}
{The_time:2017-09-11 03:07:28.0000002 +0000 UTC}
2017-09-11 03:07:28.0000002 +0000 UTC
On playground : https://play.golang.org/p/r0rQKBlpWc
答案2
得分: 3
另一个回答已经很好地解答了你问题的第一部分,所以我只会在这里解答第二部分。
简单来说,不,空的位置(nil location)不是一个问题,因为根据time.Time
的源代码,空的位置表示的是UTC时间。
// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
// that correspond to this Time.
// The nil location means UTC.
// All UTC times are represented with loc==nil, never loc==&utcLoc.
loc *Location
英文:
The other answer covers the first part of your question quite well, so I will only cover the second part here.
To put it simply, no, a nil location is not a problem, as acording to the source code for time.Time
, a nil location means UTC.
> // loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
// that correspond to this Time.
// The nil location means UTC.
// All UTC times are represented with loc==nil, never loc==&utcLoc.
loc *Location
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论