Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"method requires pointer receiver" in Go Programming Language

Tags:

go

I just saw a presentation of the Go programming language and thought I'd try to write a few lines. Everything worked fine until I tried to use an interface in this situation. How do I solve this?

package main

import "fmt"

type entity float32

func (e *entity) inc() {
    *e++
}

type incer interface {
    inc()
}

func doSomething(i incer) {
    i.inc()
}

func main() {
    fmt.Println("Hello, 世界")

    var e entity = 3
    e.inc()
    doSomething(e)
    fmt.Println(e)
}

I get the compiler error:

prog.go:24: cannot use e (type entity) as type incer in function argument:
entity does not implement incer (inc method requires pointer receiver)

I want to use a pointer so that the inc() will affect the enity outside the function. What is the syntax I should use?

/Ricky

like image 789
Ricky Helgesson Avatar asked Sep 15 '11 22:09

Ricky Helgesson


People also ask

What is pointer receiver in Golang?

You can declare methods with pointer receivers. This means the receiver type has the literal syntax *T for some type T . (Also, T cannot itself be a pointer such as *int .) For example, the Scale method here is defined on *Vertex .

How is a pointer receiver different from a value receiver function in go?

Pointer receiver passes the address of a type to the function. The function stack has a reference to the original object. So any modifications on the passed object will modify the original object. This shows that the method with value receivers modifies a copy of an object, And the original object remains unchanged.


2 Answers

I think there is some confusion here. inc is a method of the type *entity, and not of the type entity (while you can call methods on values directly on pointers; you cannot generally call methods on pointers directly on values). What you may be confused about is why you could call e.inc(), instead of having to do (&e).inc(). This is a little-known special case documented at the bottom of the Calls section in the language specification, that says if x is addressable, and &x's method set contains m, then x.m() is shorthand for (&x).m(). This applies to this case because e is a variable, so it is addressable; but other expressions may not be addressable. I would recommend that you not use this shortcut, however, as it causes confusion; it makes you think that e conforms to the interface inter, while it does not.

like image 82
newacct Avatar answered Nov 02 '22 19:11

newacct


Change it to: doSomething(&e). func (e *entity) inc() satisfies incer interface only for *entity type. There is no inc() for just entity type and that's what's you're passing to doSomething().

like image 28
Krzysztof Kowalczyk Avatar answered Nov 02 '22 21:11

Krzysztof Kowalczyk