softshipper
softshipper

Reputation: 34081

How can I use channel send direction in Go

In Go, it can be specified which direction a channel can send. I am trying to create an example about it, look at the following code:

package main

import (
    "fmt"
    "time"
)

func main() {

    ic_send_only := make(<-chan int) //a channel that can only send data - arrow going out is sending
    ic_recv_only := make(chan<- int) //a channel that can only receive a data - arrow going in is receiving

    go func() {
        ic_recv_only <- 4555
    }()

    go func() {

        ic_send_only <- ic_recv_only

    }()

    fmt.Println(ic_recv_only)
    time.Sleep(10000)

}

I get the compiler error

# command-line-arguments
.\send_receive.go:19: invalid operation: ic_send_only <- ic_recv_only (send to receive-only type <-chan int)
[Finished in 0.2s with exit code 2]

How can I use channel direction in the right way?

Or does anyone have a better sample than me?

Upvotes: 18

Views: 13971

Answers (2)

Rick-777
Rick-777

Reputation: 10248

The key point that JimB has made, to summarise, is that

  • You create channels using make
  • Every channel has two ends.
  • You communicate via the ends of channels via <-. The ends are important.
  • There is a sending end and a receiving end; channels are unidirectional.

Note also that each end can be safely accessed concurrently by more than one goroutine.

Also note that JimB's example producer(i int, ch chan<- int) and consumer(ch <-chan int) functions have parameters that specify which end they use via <-chan and chan<-, instead of just chan. Although this is optional, it is good practice because the compiler will help you fix silly mistakes if you do this.

Upvotes: 2

Mr_Pink
Mr_Pink

Reputation: 109404

Three issues:

  • You have the send and receive operations reversed (which is the error you're seeing)
  • Creating recv-only or send-only channels make no sense, as you cannot use them
  • The notation you're using is trying to send the channel itself, not the result. You need to receive and send, which requires two arrows.

    ic_recv_only <- <-ic_send_only

You may be confused because you have the terminology reversed. <-ch is a "receive operation", and ch <- is a send operation. Note that in your example, everything would be deadlocked because you can't complete the corresponding sends and receives to pass something through either channel.

Here is a complete example:

// This receives an int from a channel. The channel is receive-only
func consumer(ch <-chan int) int {
    return <-ch
}

// This sends an int over a channel. The channel is send-only
func producer(i int, ch chan<- int) {
    ch <- i
}

func main() {
    ch := make(chan int)
    go producer(42, ch)
    result := consumer(ch)
    fmt.Println("received", result)
}

Upvotes: 28

Related Questions