英文:
invalid memory address panic when appending to slice of structures inside another structure
问题
我不明白为什么在向另一个结构体内的切片结构体追加时会出现无效的内存地址恐慌。
运行代码时,我得到以下错误:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x400d5f]
goroutine 3 [running]:
main.Pairs.CollectTickers(0x0, 0x0)
test.go:32 +0x15f
created by main.main
test.go:42 +0x42
goroutine 1 [sleep]:
time.Sleep(0x174876e800)
/usr/lib/go/src/pkg/runtime/ztime_linux_amd64.c:19 +0x2f
main.main()
test.go:43 +0x57
exit status 2
这段代码产生了以下错误:
package main
import (
"fmt"
"sync"
"time"
)
var PairNames = []string{ "kalle", "kustaa", "daavid", "pekka" }
type Data struct {
a int
b int
}
type Tickers struct {
Tickers []Data
}
type Pairs struct {
Pair map[string]*Tickers
Mutex sync.Mutex
}
func (pairs Pairs) CollectTickers() {
PairCount := len(PairNames)
for x := 0; x <= 1000; x++ {
for i := 0; i < PairCount-1; i++ {
var data Data
data.a = i * x
data.b = i + x
pairs.Mutex.Lock()
pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)
pairs.Mutex.Unlock()
fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
}
}
}
func main() {
var pairs Pairs
go pairs.CollectTickers()
time.Sleep(100 * time.Second)
}
英文:
I do not understand why I get invalid memory address panic when appending to slice of structures inside another structure.
I get the following error when running the code.
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x400d5f]
goroutine 3 [running]:
main.Pairs.CollectTickers(0x0, 0x0)
test.go:32 +0x15f
created by main.main
test.go:42 +0x42
goroutine 1 [sleep]:
time.Sleep(0x174876e800)
/usr/lib/go/src/pkg/runtime/ztime_linux_amd64.c:19 +0x2f
main.main()
test.go:43 +0x57
exit status 2
This code produces the following error:
package main
import (
"fmt"
"sync"
"time"
)
var PairNames = []string{ "kalle", "kustaa", "daavid", "pekka" }
type Data struct {
a int
b int
}
type Tickers struct {
Tickers []Data
}
type Pairs struct {
Pair map[string]*Tickers
Mutex sync.Mutex
}
func (pairs Pairs) CollectTickers() {
PairCount := len(PairNames)
for x := 0; x <= 1000; x++ {
for i := 0; i < PairCount-1; i++ {
var data Data
data.a = i * x
data.b = i + x
pairs.Mutex.Lock()
pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)
pairs.Mutex.Unlock()
fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
}
}
}
func main() {
var pairs Pairs
go pairs.CollectTickers()
time.Sleep(100 * time.Second)
}
答案1
得分: 4
错误出现在:
pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)
Tickers
是一个空指针,因为你还没有分配一个 Tickers 实例。
我不确定这是否是你想要的,但它可以编译并成功运行。
package main
import (
"fmt"
"sync"
"time"
)
var PairNames = []string{"kalle", "kustaa", "daavid", "pekka"}
type Data struct {
a int
b int
}
type Tickers struct {
Tickers []Data
}
type Pairs struct {
Pair map[string]*Tickers
Mutex sync.Mutex
}
func (pairs Pairs) CollectTickers() {
PairCount := len(PairNames)
for x := 0; x <= 1000; x++ {
for i := 0; i < PairCount-1; i++ {
var data Data
data.a = i * x
data.b = i + x
pairs.Mutex.Lock()
name := PairNames[i]
if t, ok := pairs.Pair[name]; ok {
t.Tickers = append(t.Tickers, data)
} else {
pairs.Pair[name] = &Tickers{
Tickers: []Data{data},
}
}
pairs.Mutex.Unlock()
fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
}
}
}
func main() {
var pairs = Pairs{
Pair: make(map[string]*Tickers),
}
go pairs.CollectTickers()
time.Sleep(1 * time.Second)
}
英文:
The error is at:
pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)
Tickers
is a nil pointer, since you haven't yet allocated a Tickers instance.
I'm not sure if this is what you intended, but it compiles and runs successfully.
package main
import (
"fmt"
"sync"
"time"
)
var PairNames = []string{"kalle", "kustaa", "daavid", "pekka"}
type Data struct {
a int
b int
}
type Tickers struct {
Tickers []Data
}
type Pairs struct {
Pair map[string]*Tickers
Mutex sync.Mutex
}
func (pairs Pairs) CollectTickers() {
PairCount := len(PairNames)
for x := 0; x <= 1000; x++ {
for i := 0; i < PairCount-1; i++ {
var data Data
data.a = i * x
data.b = i + x
pairs.Mutex.Lock()
name := PairNames[i]
if t, ok := pairs.Pair[name]; ok {
t.Tickers = append(t.Tickers, data)
} else {
pairs.Pair[name] = &Tickers{
Tickers: []Data{data},
}
}
pairs.Mutex.Unlock()
fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
}
}
}
func main() {
var pairs = Pairs{
Pair: make(map[string]*Tickers),
}
go pairs.CollectTickers()
time.Sleep(1 * time.Second)
}
答案2
得分: 2
pairs.Pair[PairNames[i]]
的值为nil
,因为在pairs.Pair
映射中没有PairNames[i]
的条目,而nil
是*Tickers
的零值。因此,pairs.Pair[PairNames[i]].Tickers
是对nil
指针的无效解引用尝试。
根据Go编程语言规范中的说明:
对于映射类型M:
- 如果映射为nil或不包含该条目,
a[x]
将是M值类型的零值。
根据Go 1.2发布说明中的说明:
- 为了安全起见,语言现在规定,某些对nil指针的使用将触发运行时恐慌。
英文:
The value of pairs.Pair[PairNames[i]]
is nil
because there is no entry for PairNames[i]
in the pairs.Pair
map and nil
is the zero value for *Tickers
. Therefore, pairs.Pair[PairNames[i]].Tickers
is an invalid attempt to dereference a nil
pointer.
> The Go Programming Language Specification
>
> Index expressions
>
> For a of map type M:
>
> if the map is nil or does not contain such an entry, a[x] is the zero value
> for the value type of M
>
>
> Go 1.2 Release Notes
>
> Use of nil
>
> The language now specifies that, for safety reasons, certain uses of
> nil pointers are guaranteed to trigger a run-time panic.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论