Pointer methods on non pointer types - pointers

According to this response to this question
The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers
But in fact I can execute pointer method on non pointer values:
package main
import "fmt"
type car struct {
wheels int
}
func (c *car) fourWheels() {
c.wheels = 4
}
func main() {
var c = car{}
fmt.Println("Wheels:", c.wheels)
c.fourWheels()
// Here i can execute pointer method on non pointer value
fmt.Println("Wheels:", c.wheels)
}
So, what is wrong here? Is this a new feature ? or the response to the question is wrong ?

You are calling a "pointer method" on a pointer value. In the expression:
c.fourWheels()
c is of type car (non-pointer); since the car.fourWheels() method has a pointer receiver and because the receiver value is a non-pointer and is addressable, it is a shorthand for:
(&c).fourWheels()
This is in Spec: Calls:
If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
The statement:
The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers
Interpret it like this:
If you have a value method, you can always call it: if you have a value, it's ready to be the receiver; and if you have a pointer, you can always dereference it to obtain a value ready to be the receiver.
If you have a pointer method, you may not always be able to call it if you only have a value, as there are several expressions (whose result) are not addressable, and therefore you would not be able to obtain a pointer to it that would be used as the receiver; such examples are function return values and map indexing expressions. For details and examples, see How can I store reference to the result of an operation in Go?; and How to get the pointer of return value from function call? (Sure, you could always assign it to a local variable and take its address, but that's a copy and the pointer method could only modify this copy and not the original.)

Related

About the interface assignment

Why doesn't Go think it's type mismatch error when a struct pointer be assigned to an interface?
package main
import "fmt"
type ABC interface {
a() string
b() int
}
type XYZ struct {
aa string
bb int
}
func (xyz XYZ) a() string {
return "XYZ"
}
func (xyz XYZ) b() int {
return 123
}
func main() {
var xyz *XYZ
var abc ABC = xyz // type of abc is *main.XYZ,I think that Golang can find this error here, but why not?
fmt.Printf("%T\n", abc)
a, ret := abc.(*XYZ)
fmt.Println(a, ret) // type of a is *main.XYZ
fmt.Println(a.a()) // will occur a error, because the type of a(*main.XYZ) not implements the interface ABC
}
I want know why Go doesn't think this is an error at "var abc ABC = xyz"
XYZ does implement ABC. This has to do with how method sets are determined (emphasis added):
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).
The method set determines whether an interface is implemented:
An interface type specifies a method set called its interface. A variable of interface type can store a value of any type with a method set that is any superset of the interface. Such a type is said to implement the interface.
When calling *XYZ.a(), the Go compiler can always automatically dereference the pointer to obtain a value receiver. There is no downside to doing so, because the receiver cannot be modified (as far as the caller is concerned).
The inverse is true if and only if the value is addressable:
type T struct {}
func (*T) M()
func main() {
var t T
t.M() // ok; t is addressable and the compiler rewrites this to (*t).M()
var m map[string]T
m["x"].M() // error: cannot take the address of m["x"]
}
See also: Golang Method Sets (Pointer vs Value Receiver)
will occur a error, because the type of a(*main.XYZ) not implements the interface ABC
Wrong. *main.XYZ implements ABC (else abc = xyz would fail at compile-time, try to rename the method b to c for example), but the variable a holds a nil pointer (of type *XYZ). And since the XYZ.a() method has value receiver, to call that, a pointer value of type *XYZ would have to be dereferenced. But a nil pointer points to nothing, it cannot be dereferenced, an attempt to do so results in a runtime panic, just as you experienced.
If you would initialize xyz in the beginning with a non-nil pointer, it would work:
var xyz *XYZ = new(XYZ)
Try it on the Go Playground.
Also note that if XYZ.a() and XYZ.b() would have pointer receivers, then it would also work if xyz is nil:
func (xyz *XYZ) a() string {
return "XYZ"
}
func (xyz *XYZ) b() int {
return 123
}
func main() {
var xyz *XYZ
// ...
Try it on the Go Playground. The reason for this is because if the receivers are pointers, the nil pointer does not have to be dereferenced in order to call methods with pointer receivers, so no runtime panic occurs. Of course if in the methods you would refer to the XZY.aa or XYZ.bb fields, that would be a runtime panic, but your current method implementations does not do so, so it works.
#icza, maybe I don't understand all of what you said, but I think I can give a answer for the question now. when I invoke a method on a value(not pointer, the method of a struct that implements a interface, and the receiver of the method is a pointer). the Golang will create a new object and copy value from the original struct value, then, the iface.data will point the new object, now ,when we pass the pointer of the new object to method, it will can be modify, but this operate will not change the origin struct value, this is not any useful, so, Golang will occur a error when we assign a struct value to a interface(pointer receiver)

Passing by reference and value in Go to functions

I am a bit confused about passing by reference and value in Go.
I've seen this explained of the * in front of a type.
in front of a type name, means that the declared variable will store an address of another variable of that type (not a value of that
type).
This just doesn't make sense to me.
In Java if I was passing a Database instance into a function I would do
databaseFunction(DatabaseType db) {
// do something
}
However in the go example I have it's passed like so.
func PutTasks(db *sql.DB) echo.HandlerFunc {
}
Why do we need to have the asterisk in front of the type?
According to this cheat sheet, I found.
func PrintPerson(p *Person) ONLY receives the pointer address
(reference)
I don't understand why I would only want to send a pointer address as a parameter.
First, Go technically has only pass-by-value. When passing a pointer to an object, you're passing a pointer by value, not passing an object by reference. The difference is subtle but occasionally relevant. For example, you can overwrite the pointer value which has no impact on the caller, as opposed to dereferencing it and overwriting the memory it points to.
// *int means you *must* pass a *int (pointer to int), NOT just an int!
func someFunc(x *int) {
*x = 2 // Whatever variable caller passed in will now be 2
y := 7
x = &y // has no impact on the caller because we overwrote the pointer value!
}
As to your question "Why do we need to have the asterisk in front of the type?": The asterisk indicates that the value is of type pointer to sql.DB, rather than a value of type sql.DB. These are not interchangeable!
Why would you want to send a pointer address? So that you can share the value between the caller of a function and the function body, with changes made inside the function reflected in the caller (for example, a pointer is the only way that a "setter" method can work on an object). While Java passes objects by reference always, Go passes by value always (i.e. it creates a copy of the value in the function); if you pass something to a function, and that function modifies that value, the caller won't see those changes. If you want changes to propogate outside the function, you must pass a pointer.
See also: the Go tour section on Pointers, the Go spec section on pointers, the Go spec section on the address operators
The purpose of reference semantics is to allow a function to manipulate data outside its own scope. Compare:
func BrokenSwap(a int, b int) {
a, b = b, a
}
func RealSwap(a *int, b *int) {
*a, *b = *b, *a
}
When you call BrokenSwap(x, y), there is no effect, because the function receives and manipulates a private copy of the data. By contrast, when you call RealSwap(&x, &y), you actually exchange the values of the caller's x and y. Taking the address of the variables explicitly at the call site informs the reader that those variables may be mutated.
Pass by Reference :-
When you pass a same variable into a function by different name.
Below example from C++ (as Go doesnt have this concept), where a and a1 are same variable.
void swap(int& a1, int& b1)
{
int tmp = a1;
a1 = b1;
b1 = tmp;
}
int main()
{
int a = 10, b = 20;
swap(a, b);
cout << "a " << a << " b " << b ;
}
Go passes everything as data( means it copies the data from current active frame to new active frame of new function). So if you pass values it copies the value and advantage is safety from accidental modification. And when it passes address of variable its copied also into the new pointer variables but has advantage of efficiency since size of pointer is smaller.

X does not implement Y (... method has a pointer receiver)

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

Why should constructor of Go return address?

I understand that Go doesn't have any constructors and a New func is used in its place, but according to this example.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := File{fd, name, nil, 0}
return &f
}
They always return &f. Why just simply returning File isn't suffice?
Update
I've tried returning the created object for a simple struct and it's fine. So, I wonder if returning an address is a standard way of constructor or something.
Thanks.
As mentioned, yes, the spec allows you to return either values (as non-pointers) or pointers. It's just a decision you have to make.
When to return pointer?
Usually if the value you return is "more useful" as a pointer. When is it more useful?
For example if it has many methods with pointer receiver. Yes, you could store the return value in a variable and so it will be addressable and you can still call its methods that have pointer receivers. But if a pointer is returned right away, you can "chain" method calls. See this example:
type My int
func (m *My) Str() string { return strconv.Itoa(int(*m)) }
func createMy(i int) My { return My(i) }
Now writing:
fmt.Println(createMy(12).Str())
Will result in error: cannot call pointer method on createMy(12)
But if works if you return a pointer:
func createMy(i int) *My { return (*My)(&i) }
Also if you store the returned value in a data structure which is not addressable (map for example), you cannot call methods on values by indexing a map because values of a map are not addressable.
See this example: My.Str() has pointer receiver. So if you try to do this:
m := map[int]My{0: My(12)}
m[0].Str() // Error!
You can't because "cannot take the address of m[0]". But the following works:
m := map[int]*My{}
my := My(12)
m[0] = &my // Store a pointer in the map
m[0].Str() // You can call it, no need to take the address of m[0]
// as it is already a pointer
And another example for pointers being useful is if it is a "big" struct which will be passed around a lot. http.Request is a shining example. It is big, it is usually passed around a lot to other handlers, and it has methods with pointer receiver.
If you return a pointer, that usually suggests that the returned value is better if stored and passed around as a pointer.
Pointer receiver accepts both pointer and value types, as long as it matches the data type.
type User struct {
name string
email string
age int
}
// NewUserV returns value ... ideally for a User we should not be
// returning value
func NewUserV(name, email string, age int) User {
return User{name, email, age}
}
// NewUserP returns pointer ...
func NewUserP(name, email string, age int) *User {
return &User{name, email, age}
}
// ChangeEmail ...
func (u *User) ChangeEmail(newEmail string) {
u.email = newEmail
}
func main() {
// with value type
usr1 := NewUserV("frank", "frank#camero.com", 22)
fmt.Println("Before change: ", usr1)
usr1.ChangeEmail("frank#gmail.com")
fmt.Println("After change: ", usr1)
// with pointer type
usr2 := NewUserP("john", "john#liliput.com", 22)
fmt.Println("Before change: ", usr2)
usr2.ChangeEmail("john#macabre.com")
fmt.Println("After change: ", usr2)
}
In addition to what icza mentioned about the big struct being passed around. Pointer values are a way of saying that pointer semantics are at play and who ever uses the particular type should not make copy of the value which is being shared by the pointer.
If you look at the struct of File or http type, it maintains channels or some other pointer types which is unique to that value. Make a copy of the value (given to you by the pointer) would lead to hard to find bugs since the copied value might end up writing or reading to the pointer types of the original value.

Cast a struct pointer to interface pointer in Golang

I have a function
func doStuff(inout *interface{}) {
...
}
the purpose of this function is to be able to treat a pointer of any type as input.
But when I want to call it with a the pointer of a struct I have an error.
type MyStruct struct {
f1 int
}
When calling doStuff
ms := MyStruct{1}
doStuff(&ms)
I have
test.go:38: cannot use &ms (type *MyStruct) as type **interface {} in argument to doStuff
How can I cast &ms to be compatible with *interface{}?
There is no such thing as a "pointer to an interface" (technically, you can use one, but generally you don't need it).
As seen in "what is the meaning of interface{} in golang?", interface is a container with two words of data:
one word is used to point to a method table for the value’s underlying type,
and the other word is used to point to the actual data being held by that value.
So remove the pointer, and doStuff will work just fine: the interface data will be &ms, your pointer:
func doStuff(inout interface{}) {
...
}
See this example:
ms := MyStruct{1}
doStuff(&ms)
fmt.Printf("Hello, playground: %v\n", ms)
Output:
Hello, playground: {1}
As newacct mentions in the comments:
Passing the pointer to the interface directly works because if MyStruct conforms to a protocol, then *MyStruct also conforms to the protocol (since a type's method set is included in its pointer type's method set).
In this case, the interface is the empty interface, so it accepts all types anyway, but still.

Resources