why pointer type can access all methods of embed type - go

The following is the source code to try the embed type.
Modify function is defined as func (f *F) Modify(f2 F). Could anyone explain why the Modify function is not shown in the first reflection loop? But in the second reflection loop, both Modify and Validate can be got from *s.
package main
import "fmt"
import "reflect"
type F func(int) bool
func (f F) Validate(n int) bool {
return f(n)
}
func (f *F) Modify(f2 F) {
*f = f2
}
type B bool
func (b B) IsTrue() bool {
return bool(b)
}
func (pb *B) Invert() {
*pb = !*pb
}
type I interface {
Load()
Save()
}
func PrintTypeMethods(t reflect.Type) {
fmt.Println(t, "has", t.NumMethod(), "methods:")
for i := 0; i < t.NumMethod(); i++ {
fmt.Print(" method#", i, ": ",
t.Method(i).Name, "\n")
}
}
func main() {
var s struct {
F
*B
I
}
PrintTypeMethods(reflect.TypeOf(s))
fmt.Println()
PrintTypeMethods(reflect.TypeOf(&s))
}
output:
struct { main.F; *main.B; main.I } has 5 methods:
method#0: Invert
method#1: IsTrue
method#2: Load
method#3: Save
method#4: Validate
*struct { main.F; *main.B; main.I } has 6 methods:
method#0: Invert
method#1: IsTrue
method#2: Load
method#3: Modify
method#4: Save
method#5: Validate

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 embedded 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.
Struct types
A field or method f of an embedded field in a struct x is called
promoted if x.f is a legal selector that denotes that field or method
f.
...
Given a struct type S and a defined type T, promoted methods are
included in the method set of the struct as follows:
If S contains an embedded 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 embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

If a method m is defined for a type T, that method is available for both T and *T:
type T struct {}
func (t T) m() {}
func main() {
t:=T{}
tp:=&T{}
t.m() // valid: m defined for T
tp.m() // valid: m defined for *T
}
If a method is defined with a pointer receiver, it is only defined for *T and not for T':
func (t *T) n() {}
func main() {
t:=T{}
tp:=&TP{
t.n() // Valid: &t is passed to n
tp.b // valid
mp:=map[int]T{1:t}
mp[1].n() // not valid. mp[1] is not addressable
pp:=map[int]*T{1:&t}
pp[1].n() // valid: pp[1] is *T
}
The reason for this is simple: it prevents unintentionally modifying the copy instead of the indented object. If a method with pointer receiver was available for the value type as well, with the following code:
mp[1].n()
n, taking a pointer receiver, would have modified a copy of the value of mp[1], and not the value stored at mp[1]. The fact that methods with pointer receivers are not available for value types prevents that, and this becomes a compile error, because n is not defined for T, and mp[1] is not addressable, preventing the value to be converted to a pointer by the compiler.

Related

Golang type embedding implement

I have a type T which embed type B, and *B implements I. *T can be assigned to a variable of type I but not in the case of T, does this mean (*T)'s method set contains both value and pointer receiver of B?
package main
import (
"fmt"
)
type I interface {
Foo()
}
type B struct {}
type T struct {
B
}
func (a *B) Foo() {
fmt.Println("Bar")
}
func main() {
t := T{B{}}
// var i I = t -> error
var i I = &t
i.Foo()
}
Yes, method set of *T contains methods with receiver B and *B.
Spec: Struct types:
Given a struct type S and a defined type T, promoted methods are included in the method set of the struct as follows:
If S contains an embedded 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 embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

What is meant by 'non-interface method' in the section about method values in the golang specification?

The Go Programming Language Specification says:
As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.
and:
As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&t).Mp.
So, what is non-interface method in the given context?
Interface method means the method you refer to (you call) is a call on an interface value (whose method set contains the method). Similarly, non-interface method means the method you refer to (you call) is not a call on an interface value (but on a concrete type).
For example:
var r io.Reader = os.Stdin
r.Read(nil) // Interface method: type of r is an interface (io.Reader)
var p image.Point = image.Point{}
p.String() // Non-interface method, p is a concrete type (image.Point)
To demonstrate the auto-dereferencing and address taking, see this example:
type myint int
func (m myint) ValueInt() int { return int(m) }
func (m *myint) PtrInt() int { return int(*m) }
func main() {
var m myint = myint(1)
fmt.Println(m.ValueInt()) // Normal
fmt.Println(m.PtrInt()) // (&m).PtrInt()
var p *myint = new(myint)
*p = myint(2)
fmt.Println(p.ValueInt()) // (*p).ValueInt()
fmt.Println(p.PtrInt()) // Normal
}
It outputs (try it on the Go Playground):
1
1
2
2
type T struct {}
func (t *T) f() {}
func main() {
x := T{}
x.f()
}
Above, x.f is a non-interface method.

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

Why implicit non-pointer methods not satisfy interface?

Assuming we have an understanding that,
For explicit method definition for type X, GO compiler implicitly defines the same method for type *X and vice versa, if I declare,
func (c Cat) foo(){
//do stuff_
}
and declare,
func (c *Cat) foo(){
// do stuff_
}
then GO compiler gives error,
Compile error: method re-declared
which indicates that, pointer method is implicitly defined and vice versa
In the below code,
package main
type X interface{
foo();
bar();
}
type Cat struct{
}
func (c Cat) foo(){
// do stuff_
}
func (c *Cat) bar(){
// do stuff_
}
func main() {
var c Cat
var p *Cat
var x X
x = p // OK; *Cat has explicit method bar() and implicit method foo()
x = c //compile error: Cat has explicit method foo() and implicit method bar()
}
GO compiler gives error,
cannot use c (type Cat) as type X in assignment:
Cat does not implement X (bar method has pointer receiver)
at x = c, because, implicit pointer methods satisfy interfaces, but implicit non-pointer methods do not.
Question:
Why implicit non-pointer methods do not satisfy interfaces?
Let's look into the language specification:
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).
In your example, the method set of the interface type x is [foo(), bar()]. The method set of the type Cat is [foo()], and the method set of the type *Cat is [foo()] + [bar()] = [foo(), bar()].
This explains, why variable p satisfies the interface x, but variable c doesn't.
Method set
Following the spec:
The method set of any other named type T consists of all methods with receiver type T. The method set of the corresponding pointer type *T is the set of all methods with receiver *T or T (that is, it also contains the method set of T).
Method set definition sounds weird until you follow addressable and not addressable types concept.
Addressable and not addressable types
It is possible to call a pointer receiver method on a value if the value is of addressable type.
As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.
As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&t).Mp.
It is ok to call pointer receiver methods on values till you are dealing with addressable types (struct is addressable):
type Cat struct {}
func (c *Cat) bar() string { return "Mew" }
func main() {
var c Cat
c.bar()
}
Variables of interface type are not addressable
But not all Go types are addressable. Also variables referenced through interfaces are not addressable.
It is impossible to call pointer receiver on values of not addressable types:
type X interface {
bar() string
}
type Cat struct{}
func (c *Cat) bar() string { return "Mew" }
/* Note `cat` variable is not a `struct` type value but
it is type of `X` interface therefor it is not addressable. */
func CatBar(cat X) {
fmt.Print(cat.bar())
}
func main() {
var c Cat
CatBar(c)
}
So with the following error Go runtime prevents segment fault:
cannot use c (type Cat) as type X in assignment:
Cat does not implement X (bar method has pointer receiver)
Add a little to dev.bmax's answer.
type Cat struct{
}
func (c Cat) foo(){
// do stuff_
}
func (c *Cat) bar(){
// do stuff_
}
you can do
var c cat
c.bar() // ok to call bar(), since c is a variable.
but not
cat{}.bar() // not ok to call bar(), c is not a variable.
It's legal to call a *T method on an argument of type T so long as the argument is a variable; the compiler implicitly takes its address. But this is mere syntactic sugar: a value of type T does not posses all methods that a *T pointer does, and as a result it might satisfy fewer interfaces.
On the other hand, you can always call foo() with Cat or *Cat.
How about this?
package main
import (
"fmt"
)
type Growler interface{
Growl() bool
}
type Cat struct{
Name string
Age int
}
// *Cat is good for both objects and "references" (pointers to objects)
func (c *Cat) Speak() bool{
fmt.Println("Meow!")
return true
}
func (c *Cat) Growl() bool{
fmt.Println("Grrr!")
return true
}
func main() {
var felix Cat // is not a pointer
felix.Speak() // works :-)
felix.Growl() // works :-)
var ginger *Cat = new(Cat)
ginger.Speak() // works :-)
ginger.Growl() // works :-)
}

converting a method to a function with a pointer to the struct in Golang

I read some strange codes which convert a method to a function whose first argument is a pointer to this method's struct.
I write an example to demonstrate it:
package main
import "fmt"
type fooS struct{}
func (s *fooS) fooF(fooArg interface{}) {
fmt.Println("fooF: ", fooArg)
}
type wowS struct {
callback func(s *fooS, fooArg interface{})
}
func main() {
wow := new(wowS)
wow.callback = (*fooS).fooF // strange
wow.callback(nil, 123)
}
Golang Playground Link
The example's syntax is strange but has no error.
Can any one tell me how these codes work or give me an official document about them?
Thanks:)
Method expressions:
If M is in the method set of type T, T.M is a function that is
callable as a regular function with the same arguments as M prefixed
by an additional argument that is the receiver of the method.
MethodExpr = ReceiverType "." MethodName .
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
Consider a struct type T with two methods, Mv, whose receiver is of
type T, and Mp, whose receiver is of type *T.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
The expression
T.Mv
yields a function equivalent to Mv but with an explicit receiver as
its first argument; it has signature
func(tv T, a int) int
That function may be called normally with an explicit receiver, so
these five invocations are equivalent:
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
Similarly, the expression
(*T).Mp
yields a function value representing Mp with signature
func(tp *T, f float32) float32
For a method with a value receiver, one can derive a function with an
explicit pointer receiver, so
(*T).Mv
yields a function value representing Mv with signature
func(tv *T, a int) int
Such a function indirects through the receiver to create a value to
pass as the receiver to the underlying method; the method does not
overwrite the value whose address is passed in the function call.
The final case, a value-receiver function for a pointer-receiver
method, is illegal because pointer-receiver methods are not in the
method set of the value type.
Function values derived from methods are called with function call
syntax; the receiver is provided as the first argument to the call.
That is, given f := T.Mv, f is invoked as f(t, 7) not t.f(7). To
construct a function that binds the receiver, use a function literal
or method value.
It is legal to derive a function value from a method of an interface
type. The resulting function takes an explicit receiver of that
interface type.
And see:
Go - difference between parameter and receiver
Is there a performance penalty for passing "this" by value in Go methods?
differences between pointer and value slice in for-range loop

Resources