14

NB: This is not a duplicate of this question, because I understand when you would use one-directional channels. I do so all the time. My question is why this program is valid:

func main() {
    ch := make(chan<- int)
    ch <- 5
    fmt.Println("Hello, playground")
}

Playground

Running it, of course, gives a deadlock. If you check the type with %T, Go does in fact report that the type of ch is a send-only channel. In Go, you're allowed to make uni-directional channels, but it makes little sense because by making a channel that at its inception is one-way only, you're ensuring at least one of read/write will never occur.

A possible explanation would be to force a goroutine to hang but that's just as easily accomplished with select {}.

My only other idea is to force a goroutine to only do something n times,

ch := make(chan<- int, 50)
// do something 50 times, since then the buffer is full
for {
  ch <- doSomething()
}

But that's more easily, not to mention less confusingly, accomplished with any number of different constructions.

Is this just a quirk/oversight of the type system, or is there use for this behavior I'm not thinking of?

Community
  • 1
  • 1
Linear
  • 21,074
  • 4
  • 59
  • 70
  • 1
    I believe one of the design goals of Go is simplicity. The language spec is very short. I believe this might be an example of simplicity at the cost of nonsense constructs. – ReyCharles Jul 06 '15 at 07:23
  • 2
    @ReyCharles I would accept that for why, say, `var ch chan<- int = make(chan int)` is valid, but `make` is such a special construct whose behavior is rather clearly and comprehensively spelled out in the spec that I think it's more of an oversight than a consequence of simplicity. – Linear Jul 06 '15 at 07:46
  • 8
    I think it's a thing you'd never want to do. (Or, at least, someone who comes up with a use for it wins today's round of Go Pub Trivia™.) But along the lines of what @ReyCharles said, specs aren't required to exclude all nonsense constructs. Go attempts to prevent some forms of nonsense that C doesn't (e.g., unused vars); Rust has static checks that try to exclude some nonsense Go happily compiles (e.g., races). That's OK, and we mostly chuckle at the occasional oddity and move on to trying to build stuff. – twotwotwo Jul 06 '15 at 09:16

1 Answers1

4

You have a language: words (tokens) and a grammar. You can always write valid nonsense: blue is not a color.

You wrote some valid nonsense:

package main

func main() {
    ch := make(chan<- int)
    ch <- 5
}

Here's some more valid nonsense:

package main

func main() {
    for {
    }
}
peterSO
  • 158,998
  • 31
  • 281
  • 276