Is there a performance penalty for passing “this” by value in Go methods?

前端 未结 4 1809
天涯浪人
天涯浪人 2020-12-06 20:08

I\'m exploring Go after 9 years of C++ development. In C++ it is a bad practice to pass function\'s arguments by value except variables of built-in types because of performa

相关标签:
4条回答
  • 2020-12-06 20:36

    I would say your C++ knowledge will translate fine into Go about what is expensive as a function argument (passing structs by value) and what isn't (builtin types, eg int).

    The major difference would be the reference types, slices, maps and channels. These, though they appear to be passed by value (you don't need to use a pointer) are actually passed by reference, so don't in general use a pointer to a slice, map or channel.

    strings are also special - they are reference types under the hood, but they are also immutable, so pass them around directly.

    As for the specific case of this or the receiver as it is called in Go - same rules apply (note that you can have builtin types as a receiver unlike C++), and I don't think the compiler is smart enough to avoid copies, so use a pointer for large structs.

    0 讨论(0)
  • 2020-12-06 20:45

    It depends on the size of the receiver. If the receiver is less than a few dozen bytes, copying it might actually be cheaper than the pointer chasing (extra memory accesses) that would be required if you passed a pointer. Also, using a pointer makes it somewhat more likely that the struct will be allocated on the heap, putting an extra burden on the garbage collector.

    In Go, the copy is always a byte-by-byte copy, so the cost depends only on the size of the struct. In C++ it might call a copy constructor, which could potentially take a lot of time.

    So, except for really big objects, just use whatever kind of receiver makes the most sense based on the semantics of the method and consistency with the rest of your API.

    0 讨论(0)
  • 2020-12-06 20:47

    "this" in Go is called a receiver. Yes, it may be very expensive to use a non pointer receiver only to emulate a "const" semantics. But Go dropped the "const" modifier for good reasons. Thus, it's probably not a good idea to take over that specific language design decision at the cost of unnecessary copying - in the case of anything bigger than few machine words.

    BTW, the terminology difference between "this" or "self" and "receiver" implies it has also different semantics. IIRC, one cannot change the value of "this" or "self" in some other languages, but in Go, the receiver is just another function parameter (actually the first one from the compiler's point of view).

    That said, this is the reason I discourage writing methods in which the receiver variable is named this or self. It's misleading for people used to some other languages.

    A completely made-up example illustrating hopefully the idea:

    func (n *node) walk(f func(*node)) {
            for n != nil {
                    f(n)
                    n = n.next
            }
    }
    
    0 讨论(0)
  • 2020-12-06 20:55

    The other answers are good but in my opinion, there's some information missing.

    Receivers in Go are just syntactic sugar, as demonstrated by the following code:

    package main
    
    import "fmt"
    
    type Something struct {
        Value int
    }
    
    func (s *Something) ChangeValue(n int) {
        s.Value = n
    }
    
    func main() {
        o := new(Something)             // o is of type *Something
        fmt.Println(o.Value)            // Prints 0
        o.ChangeValue(8)                // Changes o.Value to 8
        fmt.Println(o.Value)            // Prints 8
        (*Something).ChangeValue(o, 16) // Same as calling o.ChangeValue(16)
        fmt.Println(o.Value)            // Prints 16
    }
    

    Based on this, consider what would happen if the receiver of ChangeValue was a value of type Something instead of a pointer to one...

    That's right! You could never actually mutate o's Value field through this method. Most of the time, you use pointer receivers to do encapsulation.

    0 讨论(0)
提交回复
热议问题