pointers - 通过 channel 发送指针

标签 pointers go goroutine channels

我正在尝试使用 channel 来实现一种工作池。请看下面的代码

https://play.golang.org/p/g7aKxDoP9lf (围棋 Playground )

package main

import (
    "fmt"
    "time"
)

func main() {
    q1 := make(chan int)

    fmt.Printf("worker 1\n")
    go worker1(q1)
    for i := 0; i < 10; i++ {
        fmt.Printf("sending: %v\n", i)
        q1 <- i
    }

    time.Sleep(time.Second)

    fmt.Printf("\n\nworker 2\n")
    q2 := make(chan *int)
    go worker2(q2)
    for i := 0; i < 10; i++ {
        fmt.Printf("sending: %v\n", i)
        q2 <- &i
    }
    time.Sleep(time.Second)
}

func worker1(qTodo <-chan int) {
    var curr int
    for {
        select {
        case curr = <-qTodo:
            fmt.Printf("got: %v\n", curr)
        }
    }
}

func worker2(qTodo <-chan *int) {
    var curr *int
    for {
        select {
        case curr = <-qTodo:
            fmt.Printf("got: %v\n", *curr)
        }
    }
}

这是一个示例输出

worker 1
sending: 0
got: 0
sending: 1
sending: 2
got: 1
got: 2
sending: 3
sending: 4
got: 3
got: 4
sending: 5
sending: 6
got: 5
got: 6
sending: 7
sending: 8
got: 7
got: 8
sending: 9
got: 9


worker 2
sending: 0
got: 0
sending: 1
sending: 2
got: 2
got: 2
sending: 3
sending: 4
got: 4
got: 4
sending: 5
sending: 6
got: 6
got: 6
sending: 7
sending: 8
got: 8
got: 8
sending: 9
got: 10

似乎在 worker2 收到指针时,原始变量中的值已经改变,这反射(reflect)在打印的值中。

问题是如何避免这种情况?如何解决这个问题?

最佳答案

此问题在 the Channels section of Effective Go 中有介绍.这是一个简短的摘录,其中变量名称已更改以匹配您的代码:

The bug is that in a Go for loop, the loop variable is reused for each iteration, so the i variable is shared across all goroutines. That's not what we want. We need to make sure that i is unique for each goroutine.

接着描述了两种解决方案:

  1. i 的值作为参数传递给 goroutine 中的函数
  2. 在循环中创建一个新变量并改用它

由于您的 goroutine 是在您的循环之外启动的,因此只有 #2 适用于您的代码。

关于pointers - 通过 channel 发送指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49123133/

相关文章:

python - 如何将数组和结构传递给需要 3 个 u32 指针作为参数的 c 函数(ctypes)

go - 如何在无错误的情况下按键编写互斥锁?

戈朗 : Strange behaviour with function type

go - 如何在 Go 中创建不区分大小写的 map ?

go - 在golang中优先处理goroutine

C - 使用更多指针访问文件

char指针值重新分配

GoRoutines 并将结构传递给原始上下文

在完成之前去例行结束

c++ - 成员函数指针的静态成员数组