在另一个结构体内追加结构体切片时出现无效的内存地址恐慌。

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

invalid memory address panic when appending to slice of structures inside another structure

问题

我不明白为什么在向另一个结构体内的切片结构体追加时会出现无效的内存地址恐慌。

运行代码时,我得到以下错误:

  1. panic: runtime error: invalid memory address or nil pointer dereference
  2. [signal 0xb code=0x1 addr=0x0 pc=0x400d5f]
  3. goroutine 3 [running]:
  4. main.Pairs.CollectTickers(0x0, 0x0)
  5. test.go:32 +0x15f
  6. created by main.main
  7. test.go:42 +0x42
  8. goroutine 1 [sleep]:
  9. time.Sleep(0x174876e800)
  10. /usr/lib/go/src/pkg/runtime/ztime_linux_amd64.c:19 +0x2f
  11. main.main()
  12. test.go:43 +0x57
  13. exit status 2

这段代码产生了以下错误:

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. )
  7. var PairNames = []string{ "kalle", "kustaa", "daavid", "pekka" }
  8. type Data struct {
  9. a int
  10. b int
  11. }
  12. type Tickers struct {
  13. Tickers []Data
  14. }
  15. type Pairs struct {
  16. Pair map[string]*Tickers
  17. Mutex sync.Mutex
  18. }
  19. func (pairs Pairs) CollectTickers() {
  20. PairCount := len(PairNames)
  21. for x := 0; x <= 1000; x++ {
  22. for i := 0; i < PairCount-1; i++ {
  23. var data Data
  24. data.a = i * x
  25. data.b = i + x
  26. pairs.Mutex.Lock()
  27. pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)
  28. pairs.Mutex.Unlock()
  29. fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
  30. }
  31. }
  32. }
  33. func main() {
  34. var pairs Pairs
  35. go pairs.CollectTickers()
  36. time.Sleep(100 * time.Second)
  37. }
英文:

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.

  1. panic: runtime error: invalid memory address or nil pointer dereference
  2. [signal 0xb code=0x1 addr=0x0 pc=0x400d5f]
  3. goroutine 3 [running]:
  4. main.Pairs.CollectTickers(0x0, 0x0)
  5. test.go:32 +0x15f
  6. created by main.main
  7. test.go:42 +0x42
  8. goroutine 1 [sleep]:
  9. time.Sleep(0x174876e800)
  10. /usr/lib/go/src/pkg/runtime/ztime_linux_amd64.c:19 +0x2f
  11. main.main()
  12. test.go:43 +0x57
  13. exit status 2

This code produces the following error:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sync&quot;
  5. &quot;time&quot;
  6. )
  7. var PairNames = []string{ &quot;kalle&quot;, &quot;kustaa&quot;, &quot;daavid&quot;, &quot;pekka&quot; }
  8. type Data struct {
  9. a int
  10. b int
  11. }
  12. type Tickers struct {
  13. Tickers []Data
  14. }
  15. type Pairs struct {
  16. Pair map[string]*Tickers
  17. Mutex sync.Mutex
  18. }
  19. func (pairs Pairs) CollectTickers() {
  20. PairCount := len(PairNames)
  21. for x := 0; x &lt;= 1000; x++ {
  22. for i := 0; i &lt; PairCount-1; i++ {
  23. var data Data
  24. data.a = i * x
  25. data.b = i + x
  26. pairs.Mutex.Lock()
  27. pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)
  28. pairs.Mutex.Unlock()
  29. fmt.Printf(&quot;a = %v, b = %v\r\n&quot;, data.a, data.b)
  30. }
  31. }
  32. }
  33. func main() {
  34. var pairs Pairs
  35. go pairs.CollectTickers()
  36. time.Sleep(100 * time.Second)
  37. }

答案1

得分: 4

错误出现在:

  1. pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)

Tickers 是一个空指针,因为你还没有分配一个 Tickers 实例。

我不确定这是否是你想要的,但它可以编译并成功运行。

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. )
  7. var PairNames = []string{"kalle", "kustaa", "daavid", "pekka"}
  8. type Data struct {
  9. a int
  10. b int
  11. }
  12. type Tickers struct {
  13. Tickers []Data
  14. }
  15. type Pairs struct {
  16. Pair map[string]*Tickers
  17. Mutex sync.Mutex
  18. }
  19. func (pairs Pairs) CollectTickers() {
  20. PairCount := len(PairNames)
  21. for x := 0; x <= 1000; x++ {
  22. for i := 0; i < PairCount-1; i++ {
  23. var data Data
  24. data.a = i * x
  25. data.b = i + x
  26. pairs.Mutex.Lock()
  27. name := PairNames[i]
  28. if t, ok := pairs.Pair[name]; ok {
  29. t.Tickers = append(t.Tickers, data)
  30. } else {
  31. pairs.Pair[name] = &Tickers{
  32. Tickers: []Data{data},
  33. }
  34. }
  35. pairs.Mutex.Unlock()
  36. fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
  37. }
  38. }
  39. }
  40. func main() {
  41. var pairs = Pairs{
  42. Pair: make(map[string]*Tickers),
  43. }
  44. go pairs.CollectTickers()
  45. time.Sleep(1 * time.Second)
  46. }
英文:

The error is at:

  1. 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.

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sync&quot;
  5. &quot;time&quot;
  6. )
  7. var PairNames = []string{&quot;kalle&quot;, &quot;kustaa&quot;, &quot;daavid&quot;, &quot;pekka&quot;}
  8. type Data struct {
  9. a int
  10. b int
  11. }
  12. type Tickers struct {
  13. Tickers []Data
  14. }
  15. type Pairs struct {
  16. Pair map[string]*Tickers
  17. Mutex sync.Mutex
  18. }
  19. func (pairs Pairs) CollectTickers() {
  20. PairCount := len(PairNames)
  21. for x := 0; x &lt;= 1000; x++ {
  22. for i := 0; i &lt; PairCount-1; i++ {
  23. var data Data
  24. data.a = i * x
  25. data.b = i + x
  26. pairs.Mutex.Lock()
  27. name := PairNames[i]
  28. if t, ok := pairs.Pair[name]; ok {
  29. t.Tickers = append(t.Tickers, data)
  30. } else {
  31. pairs.Pair[name] = &amp;Tickers{
  32. Tickers: []Data{data},
  33. }
  34. }
  35. pairs.Mutex.Unlock()
  36. fmt.Printf(&quot;a = %v, b = %v\r\n&quot;, data.a, data.b)
  37. }
  38. }
  39. }
  40. func main() {
  41. var pairs = Pairs{
  42. Pair: make(map[string]*Tickers),
  43. }
  44. go pairs.CollectTickers()
  45. time.Sleep(1 * time.Second)
  46. }

答案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.

huangapple
  • 本文由 发表于 2014年3月8日 05:38:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/22261163.html
匿名

发表评论

匿名网友

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

确定