英文:
Why does *time.Time display as the timestamp instead of memory location?
问题
我一直在进行一个爱好项目的工作,已经到了区分初始化的零值和有意的零值的阶段,以便处理部分更新请求。经过大量阅读后,我选择了将所有传入的结构字段都设置为指针。由于指针初始化为nil,并且JSON编组器绑定零值,这使得我能够区分它们。我开始发送一些API请求,一开始看到的结果是我所期望的,如下所示:
{0xc00058e240 <nil>}
然而,当我向结构中添加了一个time.Time字段,并发送一个时间戳时,我看到了以下结果:
{0xc0004060d0 <nil> 2004-10-16 00:00:00 +0000 UTC}
我本以为时间戳也会是指向某个内存位置的指针。我用下面的方法进行了一些测试,它仍然打印出一个时间戳。我原本以为如果你在操作中使用*variable
,它会为你抛出一个错误。下面的代码按预期工作,所以似乎time.Time是一个指针,尽管它以正常格式从结构中打印出来。
type updateTestRequest struct {
TestString *string `json:"test_string" binding:"alphanum"`
TestName *string `json:"test_name,omitempty"`
TestTime *time.Time `json:"test_time" time_format:"2006-01-02" binding:"required"`
}
func (server *Server) updateTest(ctx *gin.Context) {
var req updateUserRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
ctx.JSON(http.StatusBadRequest, errorResponse(err))
return
}
fmt.Printf("%v", req)
if req.TestTime != nil {
fmt.Printf("value: '%v'", *req.TestTime)
} else {
println("it was nil.")
}
}
{
"test_string":"Testing",
"first_name": "",
"date_of_birth": "2004-10-16T00:00:00.00Z"
}
我对Golang还不太熟悉,所以可能是我对这门语言的理解有误。为什么时间戳不像其他指针一样打印出内存地址呢?
英文:
I've been working on a hobby project and have gotten to the point where I need to differentiate between an initialized zero value, and an intentional zero value for any partial update capable requests. After a lot of reading, I went with the route of making all of my incoming struct fields pointers. Since pointers initialize to nil, and the JSON marshaller binds zero values, it lets me make that distinguishment. I started sending some API requests over, and was seeing what I expect at first, results looking like:
{0xc00058e240 <nil>}
When I added a time.Time field to the struct though, and sent a timestamp over, I see this:
{0xc0004060d0 <nil> 2004-10-16 00:00:00 +0000 UTC}
I would have expected the timestamp to also be a pointer to some memory location. I tested a little more with the methods below, and it still prints a timestamp. I was under the impression if you tried to use *variable
in an operation, it would throw an error for you. The code below works as expected, so it's like time.Time is a pointer even though it prints right from the struct in its normal format.
type updateTestRequest struct {
TestString *string `json:"test_string" binding:"alphanum"`
TestName *string `json:"test_name,omitempty"`
TestTime *time.Time `json:"test_time" time_format:"2006-01-02" binding:"required"`
}
func (server *Server) updateTest(ctx *gin.Context) {
var req updateUserRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
ctx.JSON(http.StatusBadRequest, errorResponse(err))
return
}
fmt.Printf("%v", req)
if req.TestTime != nil {
fmt.Printf("value: '%v'", *req.TestTime)
} else {
println("it was nil.")
}
}
{
"test_string":"Testing",
"first_name": "",
"date_of_birth": "2004-10-16T00:00:00.00Z"
}
I'm still pretty new to Golang, so it could be my misunderstanding of the language. Why does timestamp not print out as a memory address like the other pointers?
答案1
得分: 2
时间包文档显示time.Time具有String() string
方法。因为指针接收器方法集包括值接收器方法,所以*time.Time也有一个String() string
方法。
fmt包文档中提到:
> 如果格式(对于Println等隐式为%v)对于字符串有效(%s %q %v %x %X),则以下两个规则适用:
> 5. 如果操作数实现了String() string
方法,该方法将被调用以将对象转换为字符串,然后按照动词(如果有)所需的格式进行格式化。
因此,*time.Time使用time的String()方法的结果来显示。
英文:
The time package documentation shows that time.Time has a String() string
method. Because the pointer receiver method set includes the value receiver methods, a *time.Time also has a String() string
method.
The fmt package documentation says:
> If the format (which is implicitly %v for Println etc.) is valid for a string (%s %q %v %x %X), the following two rules apply:
> 5. If an operand implements method String() string
, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).
It follows that the *time.Time is displayed using the result of the time's String() method.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论