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 ?
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:
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
}