为什么在 Go 语言中,时间在结构体中打印出来的格式不同?

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

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

所以我对这里有两个疑问:

  1. 为什么作为结构体的时间部分以墙时钟的形式打印出来,而单独打印时使用更常见的日期时间表示法(使用the_struct.the_time)?
  2. 我的另一个程序中的代码打印出<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:

  1. 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)?
  2. 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

huangapple
  • 本文由 发表于 2017年9月11日 11:05:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/46147641.html
匿名

发表评论

匿名网友

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

确定