make(chan _,_)是原子的吗?

Is it thread-safe to modify the channel that a consumer is reading from?

Consider the following code:

func main(){
    channel     := make(chan int, 3)
    channel_ptr := &channel

    go supplier (channel_ptr)
    go consumer (channel_ptr)

    temp = *channel_ptr
    // Important bit
    *channel_ptr = make(chan int, 5)

    more := true
    for more{
        select {
            case msg := <-temp:
                *channel_ptr <- msg
            default:
                more = false
        }
    }
    // Block main indefinitely to keep the children alive
    <-make(chan bool)
}

func consumer(c *chan int){
    for true{
        fmt.Println(<-(*c))
    }
}

func supplier(c *chan int){
    for i :=0; i < 5; i ++{
        (*c)<-i
    }
}

If channels and make work the way that I want them to, I should get the following properties:

  1. The program always outputs 0 1 2 3 4
  2. The program will never panic from trying to read from a non-initialized channel (IE, the part I labelled Important bit is atomic)

From several test runs, this seems to be true, but I can't find it anywhere in the documentation and I'm worried about subtle race conditions.

Update

Yeah, what I was doing doesn't work. This thread is probably buried at this point, but does anybody know how to dynamically resize a buffered channel?

It's not thread safe.

If you run with -race flag to use race detector, you'll see the bug:

$ run -race t.go
==================
WARNING: DATA RACE
Write at 0x00c420086018 by main goroutine:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:14 +0x128

Previous read at 0x00c420086018 by goroutine 6:
  main.supplier()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:37 +0x51

Goroutine 6 (running) created at:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:9 +0xb4
0
==================
1
2
3
==================
WARNING: DATA RACE
Read at 0x00c420086018 by goroutine 6:
  main.supplier()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:37 +0x51

Previous write at 0x00c420086018 by main goroutine:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:14 +0x128

Goroutine 6 (running) created at:
  main.main()
      /Users/kjk/src/go/src/github.com/kjk/go-cookbook/start-mysql-in-docker-go/t.go:9 +0xb4
==================
4

As a rule of thumb, you should never pass channel as a pointer. Channel already is a pointer internally.

Stepping back a bit: I don't understand what you're trying to achieve.

I guess there's a reason you're trying to pass a channel as a pointer. The pattern of using channels in Go is: you create it once and you pass it around as value. You don't pass a pointer to it and you never modify it after creation.

In your example the problem is that you have a shared piece of memory (memory address pointed to by channel_ptr) and you write to that memory in one thread while some other thread reads it. That's data race.

It's not specific to a channel, you would have the same issue if it was pointer to an int and two threads were modifying the value of an int.