首页 > 解决方案 > 如何将变量传递给 Golang 中的另一个函数并在之后将其取回

问题描述

我是 GO 新手,我想实现一些基本的东西。将几个变量(ordersPubsub、ordersWriter)传递给一个函数,然后将它们取回。

main.go

var rdb *redis.Client
var ordersPubsub redis.PubSub
var ordersWriter csv.Writer

func main() {
    rdb = redis.NewClient(&redis.Options{
        Network:  "tcp",
        Addr:     "addr",
        Password: "password",
    })
    go utils.SaveData("orders", rdb, &ordersPubsub, &ordersWriter)
    time.Sleep(2 * time.Second)
    ordersWriter.Flush()
}

实用程序/订阅者.go

func SaveData(channelSub string, rdb *redis.Client, pubSub *redis.PubSub, writer *csv.Writer) {
    csvfile, err := os.Create("data/" + channelSub + ".csv")
    if err != nil {
        log.Fatalf("failed creating file: %s", err)
    }
    writer = csv.NewWriter(csvfile)
    ctx := context.TODO()
    pubSub = rdb.Subscribe(ctx, channelSub)
    for msg := range channel {
        order := Order{}
        json.Unmarshal([]byte(msg.Payload), &order)
        var row []string
        row = append(row, order.OrderID)
        writer.Write(row)
    }
}

我测试了另一种类型的变量,它按预期工作,但为此,我收到以下错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0xf5788d]

标签: go

解决方案


您将指针传递给函数,然后在函数中设置这些指针。这只会分配传入的指针的副本,而不是首先传递给函数的实际变量。

对于您的特定问题,您不需要将这些变量传递给 goroutine,因为 goroutine 已经可以访问和设置它们。在一般情况下,您必须设置这些指针的内容:

   *writer = *csv.NewWriter(csvfile)
   ctx := context.TODO()
   *pubSub = *rdb.Subscribe(ctx, channelSub)

或者,您必须将它们声明为指针,并传递它们的地址:

var ordersPubsub *redis.PubSub
var ordersWriter *csv.Writer

...
*writer = csv.NewWriter(csvfile)
ctx := context.TODO()
*pubSub = rdb.Subscribe(ctx, channelSub)

另请注意,您将在ordersWriter没有同步的情况下使用两个 goroutine,因此这将是一场数据竞争。


推荐阅读