英文:
What is causing this segfault in Go?
问题
背景:由于Go语言内置的JSON编组器在给定omitempty
标志时不会检查零值,因此我们尝试在需要干净地编组为JSON的结构中使用*time.Time
而不是time.Time
。但是,这样做的问题显然是我们在使用它时需要非常小心地检查它是否为nil。我们注意到的一件事是,在一个设置包含结构的创建时间的函数中,当我们在数据库中检查JSON时,所有的时间都完全相同,精确到纳秒。
为了检查这是否与指针有关还是因为系统性能非常好,我做了这个测试:
package main
import (
"fmt"
"time"
)
type Timekeeper struct {
myTime *time.Time
}
func main() {
t := make([]Timekeeper, 100)
var now time.Time
for _, v := range t {
now = time.Now()
v.myTime = &now
time.Sleep(1 * time.Second)
}
for i, times := range t {
fmt.Printf("Timekeeper %s time: %s.", i, times.myTime.Format(time.RFC3339Nano))
}
}
但是它一直产生以下恐慌:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0x20314]
goroutine 1 [running]:
panic(0x112c00, 0x1040a038)
/usr/local/go/src/runtime/panic.go:500 +0x720
main.main()
/tmp/sandbox675251439/main.go:23 +0x314
Program exited.
我猜这与指针被不断重新分配有关,但我有一个心理障碍,无法确定问题的具体原因。有人能解释一下这里发生了什么吗?
英文:
Background: Because Go's inbuilt JSON marshaller doesn't check for zero values when given the omitempty
flag, we're trying using *time.Time
rather than time.Time
in structs that need to be marshalled cleanly to JSON. The problem with this is obviously we need to be very careful to always check it is not nil when using it. One thing we did notice was in a function that sets a creation time on the encompassing struct, when we checked the JSON in the database all of the times were exactly the same, down to the nanosecond.
To check whether this was something to do with the pointer or just because the system was performing very well, I made this test:
package main
import (
"fmt"
"time"
)
type Timekeeper struct {
myTime *time.Time
}
func main() {
t := make([]Timekeeper, 100)
var now time.Time
for _, v := range t {
now = time.Now()
v.myTime = &now
time.Sleep(1 * time.Second)
}
for i, times := range t {
fmt.Printf("Timekeeper %s time: %s.", i, times.myTime.Format(time.RFC3339Nano))
}
}
but it keeps producing this panic:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0x20314]
goroutine 1 [running]:
panic(0x112c00, 0x1040a038)
/usr/local/go/src/runtime/panic.go:500 +0x720
main.main()
/tmp/sandbox675251439/main.go:23 +0x314
Program exited.
I'm assuming this is something to do with the pointer being constantly reassigned to, but I've got a mental block going on and I can't figure out exactly what the issue is. Can someone please explain what is happening here?
答案1
得分: 6
在你的循环中,你复制了每个Timekeeper
的值。改为这样做:
for i := range t {
now := time.Now()
t[i].myTime = &now
}
这样,每个Timekeeper
的myTime
字段都会指向一个独立的time.Time
对象。
英文:
In your loop you copy every Timekeeper
value. Do this instead:
for i := range t {
now = time.Now()
t[i].myTime = &now
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论