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

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

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 (
        &quot;fmt&quot;
        &quot;sync&quot;
        &quot;time&quot;
)

var PairNames = []string{ &quot;kalle&quot;, &quot;kustaa&quot;, &quot;daavid&quot;, &quot;pekka&quot; }

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 &lt;= 1000; x++ {
                for i := 0; i &lt; 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(&quot;a = %v, b = %v\r\n&quot;, 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 (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;
)

var PairNames = []string{&quot;kalle&quot;, &quot;kustaa&quot;, &quot;daavid&quot;, &quot;pekka&quot;}

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 &lt;= 1000; x++ {
	    for i := 0; i &lt; 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] = &amp;Tickers{
				    Tickers: []Data{data},
			    }
		    }
		    pairs.Mutex.Unlock()
		    fmt.Printf(&quot;a = %v, b = %v\r\n&quot;, 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.

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:

确定