Method Sets (Pointer vs Value Receiver) - go

I am having a hard time understanding as to why are these rules associated with method set of pointer type .vs. value type
Can someone please explain the reason (from the interface table perspective)
(Snippet from William Kennedy's blog)
Values Methods Receivers
-----------------------------------------------
T (t T)
*T (t T) and (t *T)
Methods Receivers Values
-----------------------------------------------
(t T) T and *T
(t *T) *T
Snippet from specification
Method sets
A type may have a method set associated with it. The method set of an interface type is its interface.
The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T). Further rules apply to structs containing anonymous fields, as described in the section on struct types. Any other type has an empty method set. In a method set, each method must have a unique non-blank method name.
The method set of a type determines the interfaces that the type implements and the methods that can be called using a receiver of that type.

If you have a *T you can call methods that have a receiver type of *T as well as methods that have a receiver type of T (the passage you quoted, Method Sets).
If you have a T and it is addressable you can call methods that have a receiver type of *T as well as methods that have a receiver type of T, because the method call t.Meth() will be equivalent to (&t).Meth() (Calls).
If you have a T and it isn't addressable (for instance, the result of a function call, or the result of indexing into a map), Go can't get a pointer to it, so you can only call methods that have a receiver type of T, not *T.
If you have an interface I, and some or all of the methods in I's method set are provided by methods with a receiver of *T (with the remainder being provided by methods with a receiver of T), then *T satisfies the interface I, but T doesn't. That is because *T's method set includes T's, but not the other way around (back to the first point again).
In short, you can mix and match methods with value receivers and methods with pointer receivers, and use them with variables containing values and pointers, without worrying about which is which. Both will work, and the syntax is the same. However, if methods with pointer receivers are needed to satisfy an interface, then only a pointer will be assignable to the interface — a value won't be valid.

From Golang FAQ:
As the Go specification says, the method set of a type T consists of all methods with receiver type T, while that of the corresponding pointer type *T consists of all methods with receiver *T or T. That means the method set of *T includes that of T, but not the reverse.
This distinction arises because if an interface value contains a pointer *T, a method call can obtain a value by dereferencing the pointer, but if an interface value contains a value T, there is no safe way for a method call to obtain a pointer. (Doing so would allow a method to modify the contents of the value inside the interface, which is not permitted by the language specification.)
Even in cases where the compiler could take the address of a value to pass to the method, if the method modifies the value the changes will be lost in the caller. As an example, if the Write method of bytes.Buffer used a value receiver rather than a pointer, this code:
var buf bytes.Buffer
io.Copy(buf, os.Stdin)
would copy standard input into a copy of buf, not into buf itself. This is almost never the desired behavior.
About Golang interface under the hood.
Go interface by Lance Taylor
Go interface by Russ Cox

-In go when we have a type we can attach methods on it, those methods attached to type are known as its method set.
Depending on Pointer or not pointer value , it will determine which method attach to it.
Case:1
Receiver (t T) Value T => https://go.dev/play/p/_agcEVFaySx
type square struct {
length int
}
type shape interface { shape as an interface
area() int
}
// receiver(t T)
func (sq square) area() int {
return sq.length * sq.length
}
func describe(s shape) {
fmt.Println("area", s.area())
}
func main() {
sq := square{
length: 5,
}
describe(sq)// value `sq` (T)
}
Case 2: Receiver (t T) Value T
// receiver(t *T)
func (sq *square) area() int {
return sq.length * sq.length
}
func main() {
describe(sq)// value sq (T)
}
Case 4: Receiver (t *T) Value T
// receiver(t *T)
func (sq *square) area() int {
return sq.length * sq.length
}
func main() {
describe(&sq)// value sq (*T)
}
Case 4: Receiver (t *T) Value T
this case fails
// receiver(t *T)
func (sq *square) area() int {
return sq.length * sq.length
}
func main() {
describe(&sq)// value sq (T)
}
we input normal value rather than pointer , but method receiver takes pointer value,it will not accept ,fails.
But we call area method like this sq.area()//rather than using interface to access it.

Related

Question regarding Golang interfaces and Composite struct [duplicate]

There are already several Q&As on this "X does not implement Y (... method has a pointer receiver)" thing, but to me, they seems to be talking about different things, and not applying to my specific case.
So, instead of making the question very specific, I'm making it broad and abstract -- Seems like there are several different cases that can make this error happen, can someone summary it up please?
I.e., how to avoid the problem, and if it occurs, what are the possibilities? Thx.
This compile-time error arises when you try to assign or pass (or convert) a concrete type to an interface type; and the type itself does not implement the interface, only a pointer to the type.
Short summary: An assignment to a variable of interface type is valid if the value being assigned implements the interface it is assigned to. It implements it if its method set is a superset of the interface. The method set of pointer types includes methods with both pointer and non-pointer receiver. The method set of non-pointer types only includes methods with non-pointer receiver.
Let's see an example:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
The Stringer interface type has one method only: String(). Any value that is stored in an interface value Stringer must have this method. We also created a MyType, and we created a method MyType.String() with pointer receiver. This means the String() method is in the method set of the *MyType type, but not in that of MyType.
When we attempt to assign a value of MyType to a variable of type Stringer, we get the error in question:
m := MyType{value: "something"}
var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
// MyType does not implement Stringer (String method has pointer receiver)
But everything is ok if we try to assign a value of type *MyType to Stringer:
s = &m
fmt.Println(s)
And we get the expected outcome (try it on the Go Playground):
something
So the requirements to get this compile-time error:
A value of non-pointer concrete type being assigned (or passed or converted)
An interface type being assigned to (or passed to, or converted to)
The concrete type has the required method of the interface, but with a pointer receiver
Possibilities to resolve the issue:
A pointer to the value must be used, whose method set will include the method with the pointer receiver
Or the receiver type must be changed to non-pointer, so the method set of the non-pointer concrete type will also contain the method (and thus satisfy the interface). This may or may not be viable, as if the method has to modify the value, a non-pointer receiver is not an option.
Structs and embedding
When using structs and embedding, often it's not "you" that implement an interface (provide a method implementation), but a type you embed in your struct. Like in this example:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
Again, compile-time error, because the method set of MyType2 does not contain the String() method of the embedded MyType, only the method set of *MyType2, so the following works (try it on the Go Playground):
var s Stringer
s = &m2
We can also make it work, if we embed *MyType and using only a non-pointer MyType2 (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
Also, whatever we embed (either MyType or *MyType), if we use a pointer *MyType2, it will always work (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
Relevant section from the spec (from section Struct types):
Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:
If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
So in other words: if we embed a non-pointer type, the method set of the non-pointer embedder only gets the methods with non-pointer receivers (from the embedded type).
If we embed a pointer type, the method set of the non-pointer embedder gets methods with both pointer and non-pointer receivers (from the embedded type).
If we use a pointer value to the embedder, regardless of whether the embedded type is pointer or not, the method set of the pointer to the embedder always gets methods with both the pointer and non-pointer receivers (from the embedded type).
Note:
There is a very similar case, namely when you have an interface value which wraps a value of MyType, and you try to type assert another interface value from it, Stringer. In this case the assertion will not hold for the reasons described above, but we get a slightly different runtime-error:
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
Runtime panic (try it on the Go Playground):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
Attempting to convert instead of type assert, we get the compile-time error we're talking about:
m := MyType{value: "something"}
fmt.Println(Stringer(m))
To keep it short and simple, let say you have a Loader interface and a WebLoader that implements this interface.
package main
import "fmt"
// Loader defines a content loader
type Loader interface {
load(src string) string
}
// WebLoader is a web content loader
type WebLoader struct{}
// load loads the content of a page
func (w *WebLoader) load(src string) string {
return fmt.Sprintf("I loaded this page %s", src)
}
func main() {
webLoader := WebLoader{}
loadContent(webLoader)
}
func loadContent(loader Loader) {
loader.load("google.com")
}
The above code will give you this compile time error
./main.go:20:13: cannot use webLoader (type WebLoader) as type Loader
in argument to loadContent:
WebLoader does not implement Loader (Load method has pointer receiver)
To fix it you only need to change webLoader := WebLoader{} to following:
webLoader := &WebLoader{}
Why this will fix the issue? Because you defined this function func (w *WebLoader) Load to accept a pointer receiver. For more explanation please read #icza and #karora answers
Another case when I have seen this kind of thing happening is if I want to create an interface where some methods will modify an internal value and others will not.
type GetterSetter interface {
GetVal() int
SetVal(x int) int
}
Something that then implements this interface could be like:
type MyTypeA struct {
a int
}
func (m MyTypeA) GetVal() int {
return a
}
func (m *MyTypeA) SetVal(newVal int) int {
int oldVal = m.a
m.a = newVal
return oldVal
}
So the implementing type will likely have some methods which are pointer receivers and some which are not and since I have quite a variety of these various things that are GetterSetters I'd like to check in my tests that they are all doing the expected.
If I were to do something like this:
myTypeInstance := MyType{ 7 }
... maybe some code doing other stuff ...
var f interface{} = myTypeInstance
_, ok := f.(GetterSetter)
if !ok {
t.Fail()
}
Then I won't get the aforementioned "X does not implement Y (Z method has pointer receiver)" error (since it is a compile-time error) but I will have a bad day chasing down exactly why my test is failing...
Instead I have to make sure I do the type check using a pointer, such as:
var f interface{} = new(&MyTypeA)
...
Or:
myTypeInstance := MyType{ 7 }
var f interface{} = &myTypeInstance
...
Then all is happy with the tests!
But wait! In my code, perhaps I have methods which accept a GetterSetter somewhere:
func SomeStuff(g GetterSetter, x int) int {
if x > 10 {
return g.GetVal() + 1
}
return g.GetVal()
}
If I call these methods from inside another type method, this will generate the error:
func (m MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
Either of the following calls will work:
func (m *MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
func (m MyTypeA) OtherThing(x int) {
SomeStuff(&m, x)
}
Extend from above answers (Thanks for all of your answers)
I think it would be more instinctive to show all the methods of pointer / non pointer struct.
Here is the playground code.
https://play.golang.org/p/jkYrqF4KyIf
To summarize all the example.
Pointer struct type would include all non pointer / pointer receiver methods
Non pointer struct type would only include non pointer receiver methods.
For embedded struct
non pointer outer struct + non pointer embedded struct => only non pointer receiver methods.
non pointer outer struct + pointer embedded struct / pointer outer struct + non pointer embedded struct / pointer outer struct + pointer embedded struct => all embedded methods

Can interface type and value be a type that does not implement the interface and its value?

Here is the link to the code and description I was looking at: https://tour.golang.org/methods/11
I change method M of type *T to T, that is changing from a pointer receiver to a value receiver as below.
package main
import (
"fmt"
"math"
)
type I interface {
M()
}
type T struct {
S string
}
func (t T) M() {
fmt.Println(t.S)
}
type F float64
func (f F) M() {
fmt.Println(f)
}
func main() {
var i I
i = &T{"Hello"}
describe(i)
i.M()
i = F(math.Pi)
describe(i)
i.M()
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
However, the change above gave me the same result as it was still a pointer receiver.
(&{Hello}, *main.T)
Hello
(3.141592653589793, main.F)
3.141592653589793
I am not sure I got this concept right. From my understanding since interface variable i got assign a pointer to an instance of struct T, the type of that interface variable should be a pointer to struct T, and since pointer to struct T does not implement method M, it will cause a panic.
Spec: Method sets:
The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).
[...] The method set of a type determines the interfaces that the type implements and the methods that can be called using a receiver of that type.
So all methods you declare with value receiver will also belong to the method set of the corresponding pointer type, and thus all interfaces a non-pointer type implements will also be implemented by the pointer type too (and possibly more).
Go has some shortcuts. For example:
a.Method()
a.Field
is the same as
(*a).Method()
(*a).Field
is similar to the concept here https://tour.golang.org/moretypes/4

In golang, is it necessary change all method of a type to have pointer receivers if one of the method must have pointer receiver?

I'm studying golang and I'm a little confused about defining methods on values or pointers. As mentioned in the doc:
Next is consistency. If some of the methods of the type must have
pointer receivers, the rest should too, so the method set is
consistent regardless of how the type is used. See the section on
method sets for details.
If I have a type T, it need to implement several interfaces. One interface has method which need to use pointer receiver, and methods in another interfaces can work pretty well with value receiver. Is it necessary to change all methods in all interfaces to have pointer receivers? If so, why?
It depends :)
Your type T has two method sets:
method set of receiver (t T) which is all methods defined with
receiver (t T)
method set of receiver (t *T) which is all methods that have receiver (t *T) AND all methods that have receiver (t T)
So if you have an interface that is satisfied by T, it is also satisfied by *T. (but not vice versa)
Hence, if you have to add a *T receiver method to a type to satisfy an interface you do not need to change the other method receivers to *T, but you will have to be aware that now only a *T satisfies that interface and not a T and other interfaces may be satisfied for both.
type fooer interface {
foo()
}
type barer interface {
bar()
}
type T struct {}
func (t T)foo(){}
func (t *T)bar(){}
var _ fooer = T{} // ok
var _ barer = T{} // NOT OK - won't compile
var _ barer = &T{} // ok
var _ fooer = &T{} // ok
Confusing? Yes it can be. So although you don't have to change all of the methods to have a pointer receiver it's more consistent and less confusing if you do - that way you know that you are always dealing with a *T in your code - and it seems to be what most people do.
It is not needed. What you cited is just an argument for doing so. It is therefore recommended.
As you have mentioned about Golang spec for methods have pointer or value receiver. If an interface as a method receiver then its better for consistency to have other methods with pointer receivers. But It is not necessary.
Lets take a requirement of pointer receivers. Suppose I have a struct which contains details of DB connection and session. And there are methods which are using same connection for methods with insert/update/delete queries. Then it is better to pointer receiver so that you need not to create connection every time. You can manage with current session for all methods used to query database.
type Env struct {
db *sql.DB
}
func main() {
db, err := models.NewDB("postgres://user:pass#localhost/dbname")
if err != nil {
log.Panic(err)
}
env := &Env{db: db}
}
func (env *Env) fetch(){}
func (env *Env) Insert(){}
func (env *Env) Update(){}

Address of composite literal used as interface

The address of a composite literal is evaluated as the literal itself when used as an interface. Can somebody please point to the part of the ref spec which deals with this ?
package main
import "fmt"
type ntfc interface {
rx() int
}
type cncrt struct {
x int
}
func (c cncrt) rx() int{
return c.x
}
func rtrnsNtfca() ntfc {
return &cncrt{3}
}
func rtrnsNtfc() ntfc {
return cncrt{3}
}
func rtrnsCncrt() *cncrt {
return &cncrt{3}
}
func main() {
fmt.Println(rtrnsNtfca().rx())
fmt.Println(rtrnsNtfc().rx())
fmt.Println(rtrnsCncrt().rx())
}
Also here. For future ref., is it acceptable to just link to the playground without including the code here?
Spec: Method sets:
A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).
So the method set of *cncrt includes the methods set of cncrt. Since rx() is an element of cncrt's method set, it will also be in *cncrt's method set. Which means both cncrt and *cncrt types implement the ntfc interface.
If you have a pointer value (*cncrt) and you call rx() on it, the pointer will automatically be dereferenced which will be the receiver of the rx() method.
In your rtnsNtfca() and rtnsNtfc() functions an interface value of ntfc will automatically be created and returned. Interface values in Go are represented as (type;value) pairs (for more details: The Laws of Reflection #The representation of an interface). So both rtnsNtfca() and rtnsNtfc() return an interface value, but the first one holds a dynamic value of type *cncrt and the latter one holds a dynamic value of type cncrt.
And your 3rd method rtrnsCncrt() returns a concrete type (*cncrt), there is no interface wrapping involved there.
Note: "The other way around"
Spec: Calls:
If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
This means if you would have declared rx() to have a pointer receiver, and you have a variable of type cncrt (note: not pointer), you could still call the rx() method on it if it is addressable, and the address would be taken automatically and used as the receiver.

Why no methods defined for named pointer types?

In the documentation for effective Go it states:
As we saw with ByteSize, methods can be defined for any named type
(except a pointer ...
type ByteSlice []byte
func (slice ByteSlice) Append(data []byte) []byte {
// Body exactly the same as above
}
It then goes on to provide an example with a pointer as receiver:
func (p *ByteSlice) Append(data []byte) {
slice := *p
// Body as above, without the return.
*p = slice
}
Doesn't that contradict ? Or does it mean that this isn't valid:
type ByteSlice []byte
type Pb *ByteSlice
func (p Pb) Append(data []byte) []byte {
}
Though it looks just like a typedef!
Named pointer types could lead to ambiguities like so:
type T int
func (t *T) Get() T {
return *t + 1
}
type P *T
func (p P) Get() T {
return *p + 2
}
func F() {
var v1 T
var v2 = &v1
var v3 P = &v1
fmt.Println(v1.Get(), v2.Get(), v3.Get())
}
In the last case (esp. v3) per the current spec, it's ambiguous which Get() method should be called. Yes, there's no reason that the method resolution couldn't be defined, but it's one more detail to add to the language for something that already has a solution.
A named type that is a pointer isn't the same as a pointer to a named type.
This is what the language reference says:
That parameter section must declare a single parameter, the receiver.
Its type must be of the form T or *T (possibly using parentheses)
where T is a type name. The type denoted by T is called the receiver
base type; it must not be a pointer or interface type and it must be
declared in the same package as the method.
That's clear enough: if T denotes a pointer type, then you can't use it as a method receiver.
Note the careful language of the reference here: the phrase "Its type must be of the form T or T*" refers to the syntax-level specification of the method receiver (that is, the "form" of the type). That's different from the phrase "The type denoted by T", where it's talking about the type that T names (that is, what the type "denotes").

Resources