Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different ways to pass channels as arguments in function

I was reading some go code and say a few different ways to pass go channels. Maybe they are the same but I was wondering if there is any difference since I couldn't find documentation online:

1)

func serve(ch <-chan interface{}){ //do stuff } 

2)

func serve(ch chan<- interface{}){ //do stuff } 

3)

func serve(ch chan interface{}){ //do stuff } 

4)

func server(ch *chan interface{}){ //do stuff} 

I was wondering what the difference between them were and if they were just equivalent ways to do the same thing: pass a channel around different goroutines.

NOTE: I am aware that there is no reason to pass a pointer to a chan, map, or slice, or function value, since those are all reference types which internally contain a pointer (the exception would be if you want the callee to change the reference type header). The only reason I provided it is for completeness (i.e. to really provide every way a channel could be attempted to be passed as a parameter and to make on question that hopefully, references all ways to do this and compares them).

like image 260
Charlie Parker Avatar asked Jul 21 '14 15:07

Charlie Parker


People also ask

Are channels passed by reference Golang?

Are channels implicitly passed by reference in go ? Yes, the reference types in Go are slice , map and channel . When passing these, you're making a copy of the reference. (Strings are also implemented as a reference type, though they're immutable.)

How do you wait for a Goroutine to finish?

In order to be able to run the goroutines until the finish, we can either make use of a channel that will act as a blocker or we can use waitGroups that Go's sync package provides us with.

When should I use go channel?

Go channels are used for communicating between concurrently running functions by sending and receiving a specific element type's data. When we have numerous Goroutines running at the same time, channels are the most convenient way for them to communicate with one another.

What is buffered channel in Golang?

Buffered channels allows to accept a limited number of values without a corresponding receiver for those values. It is possible to create a channel with a buffe. Buffered channel are blocked only when the buffer is full. Similarly receiving from a buffered channel are blocked only when the buffer will be empty.


2 Answers

I always recommend that the direction is passed everywhere it is possible, e.g.

func serve(ch <-chan SomeType) { /*do stuff*/ }  func serve(ch chan<- SomeType) { /*do stuff*/ } 

By including the arrow <-chan or chan<-, you are achieving three things:

  • You are making it clear that the parameter is one end of a channel.
  • You are expressing clearly which end is being supplied. chan<- is the sending (writing) end. <-chan is the receiving (reading) end.
  • You are giving more information to the compiler for checking. If the function body tries to use the wrong end of the channel, the compiler can raise an error.

These are good reasons to show the channel end whenever possible.

Your third case depicts not specifying the end of the channel. This allows both ends of the channel to be accessed, which will be correct in some cases but in other cases may lead to accidental errors.

The fourth case, passing a pointer to a channel, is quite unusual and perhaps a bit odd. If you wanted to change the channel, it would be clearer to include it as a return parameter instead.

like image 150
Rick-777 Avatar answered Sep 30 '22 00:09

Rick-777


The rule of thumb: Arrow shows if the data is going into (output) or going out of (input) channel. No arrow is general purpose channel.

chan <-          writing to channel (output channel) <- chan          reading from channel (input channel) chan             read from or write to channel (input/output channel) 
like image 21
smishra Avatar answered Sep 29 '22 23:09

smishra