Are channels passed by reference implicitly

非 Y 不嫁゛ 提交于 2019-12-03 02:10:26

问题


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 ?


回答1:


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
}



回答2:


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.




回答3:


You could say yes, but to say the "The channel c is modified in the sum function" isn't really the correct terminology. Channel sends and receives aren't really considered modifications.

Note that slices and maps behave in a similar way, see http://golang.org/doc/effective_go.html for more details.

Also "passed by reference" implies that an assignment could be made to c in sum that would change it's value (as opposed to it's underlying data) outside of sum, which is not the case.




回答4:


Channel variables are references, but it depends on your definition of 'reference'. Language specification never mentions reference types.

No channel (variable) is 'modified' in the sum function. Sending to a channel changes its state.

In other words, yes the channel is implemented as a pointer to some run time structure. Note that that's strictly necessary for the reference semantics.

EDIT: The above sentence was meant to read: "Note that that's not strictly necessary for the reference semantics.", ie. the word 'not' went MIA. Sorry for any eventually created confusion.



来源:https://stackoverflow.com/questions/16589983/are-channels-passed-by-reference-implicitly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!