附加到另一个结构内的结构切片时,内存地址无效

时间:2014-03-07 21:38:05

标签: go

我不明白为什么在附加到另一个结构中的结构片段时会出现无效的内存地址混乱。

运行代码时出现以下错误。

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)
}

2 个答案:

答案 0 :(得分:4)

错误发生在:

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

Tickers是一个nil指针,因为你还没有分配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)
}

答案 1 :(得分:2)

pairs.Pair[PairNames[i]]的值为nil,因为PairNames[i]地图中没有pairs.Pair的条目,nil是{{1}的零值}}。因此,*Tickers是取消引用pairs.Pair[PairNames[i]].Tickers指针的无效尝试。

  

The Go Programming Language Specification

     

Index expressions

     

对于地图类型M:

nil
     

Go 1.2 Release Notes

     

Use of nil

     

该语言现在指出,出于安全原因,某些用途   nil指针保证会引发运行时恐慌。