Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are channels passed by reference implicitly

The go tour has this example for channels: https://tour.golang.org/concurrency/2

package main  import "fmt"  func sum(a []int, c chan int) {     sum := 0     for _, v := range a {         sum += v     }     c <- sum // send sum to c }  func main() {     a := []int{7, 2, 8, -9, 4, 0}      c := make(chan int)     go sum(a[:len(a)/2], c)     go sum(a[len(a)/2:], c)     x, y := <-c, <-c // receive from c      fmt.Println(x, y, x+y) } 

The channel c is modified in the sum function and the changes persist after the function has terminated. Obviously c was passed by reference but no pointer to c was created. Are channels implicitly passed by reference in go ?

like image 231
lhk Avatar asked May 16 '13 14:05

lhk


People also ask

Are Go channels FIFO?

Buffered channels in Go are always FIFO. The specification clearly says: Channels act as first-in-first-out queues. If the values coming out of the channel are not FIFO, then this is a bug in the channel implementation.

Are maps passed by value Golang?

No. Maps are reference by default.

What is reference type in Go?

Reference types in Go are the set of slice, map, channel, interface, and function types. When you declare a variable from one of these types, the value that's created is called a header value. Technically, a string is also a reference type value.


2 Answers

Technically they're copied, because when you use make, you are allocating something on the heap, so it's technically a pointer behind the scenes. But the pointer type is not exposed, so they can be thought of as a reference type.

EDIT: From the spec:

The built-in function make takes a type T, which must be a slice, map or channel type, optionally followed by a type-specific list of expressions. It returns a value of type T (not *T). The memory is initialized as described in the section on initial values.

A channel must be initialized before it can be used. make() does this, so it can be used as a reference type.

What this basically means is that you can pass it into a function and write to or read from it. The general rule of thumb is if you use make, new or &, you can pass it to another function without copying the underlying data.

So, the following are "reference" types:

  • slices
  • maps
  • channels
  • pointers
  • functions

Only data types (numbers, bools and structs, etc) are copied when passing into a function. Strings are special, because they're immutable, but not passed by value. This means that the following won't work as expected:

type A struct {     b int } func f(a A) {     a.b = 3 } func main() {     s := A{}     f(s)     println(s.b) // prints 0 } 
like image 113
beatgammit Avatar answered Oct 21 '22 23:10

beatgammit


Everything in Go is passed and assigned by value. Certain built-in types, including channel types and map types, behave as opaque pointers to some hidden internal structure. And it is possible to modify that internal structure by operations on the channel or map. They start out as nil, which is analogous to the nil pointer.

like image 20
newacct Avatar answered Oct 22 '22 00:10

newacct