Cast a struct pointer to interface pointer in Golang - pointers

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.

Related

How to get pointer to interface in GO

I would like to get rid of the variable temp in the following code:
type myinterface interface {
f1()
}
type a struct {
val int
}
type b struct {
mi *myinterface
}
func (a) f1() {
}
func demo() {
a1 := a{3}
var temp myinterface = a1
b1 := b{&temp}
fmt.Println(b1)
But if I try to write
b1 := b{&myinterface(a1)}
I get the message
cannot take the address of myinterface(a1) ( undefined )
what is the correct way to do this?
Update:
I did not a pointer to an interface, since an interface can hold a struct or a pointer to a struct, as also detailed in this question:
"<type> is pointer to interface, not interface" confusion
Let me know if this is what you are looking for:
https://play.golang.org/p/ZGRyIqN7bPR
Full code:
package main
import (
"fmt"
)
type myinterface interface {
f1()
}
type a struct {
val int
}
type b struct {
mi myinterface
}
func (a) f1() {}
func main() {
fmt.Println("Hello, playground")
a1 := &a{3}
b1 := b{a1}
fmt.Println(b1)
}
You almost never need a pointer to an interface, since interfaces are just pointers themselves.
So just change the struct b to:
type b struct {
mi myinterface
}
myinterface(a1) is a type conversion, it converts a1 to type myinteface.
Type conversion expressions are not addressable, so you cannot take the address of it. What is addressable is listed explicitly in the Spec: Address operators:
The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x [in the expression of &x] may also be a (possibly parenthesized) composite literal.
This related answer lists several options how to obtain the address of such expressions: How do I do a literal *int64 in Go?
For example if you use a composite literal to create a slice of type []myinterface and put a1 in it, you can take the address of its first element (which will be of type *myinterface):
b1 := b{&[]myinterface{a1}[0]}
And it will work (try it on the Go Playground):
a1 := a{3}
b1 := b{&[]myinterface{a1}[0]}
fmt.Println(b1)
But know that using pointers to interfaces is very rarely needed, so is a field of type *myinterface really what you want in the first place?
Interface values can be nil, and also nil values (e.g. nil pointers) can also be wrapped in interfaces, so most likely you don't need a pointer to interface. We would have to know your "wider" goal to tell if this is what you really need.

pointer to interface is not an interface error?

The following code works:
type Brace interface {}
type Round struct {
prev_ Brace
}
type Square struct {}
func main() {
var r Round
var s Square
r.prev_ = s
}
Is it true that r.prev_ is now a copy of s? How can I change it that Round will contain a pointer to Brace? This code doesn't work:
type Brace interface {}
type Round struct {
prev_ *Brace
}
type Square struct {}
func main() {
var r Round
var s Square
r.prev_ = &s
}
because of the error:
cannot use &s (type *Square) as type *Brace in assignment:
*Brace is pointer to interface, not interface
As the error says:
cannot use &s (type *Square) as type *Brace in assignment: *Brace is
pointer to interface, not interface
An interface can wrap any type of value. But you are wraping the struct inside pointer type interface not an interface. That's not how interface works in golang.
If you wants to pass the address of an struct. An interface can wrap the pointer to struct directly. There is no need of creating a pointer to an interface to achieve that.
type Brace interface {}
type Round struct {
prev_ Brace
}
type Square struct {}
func main() {
var r Round
var s Square
r.prev_ = &s
fmt.Printf("%#v", r)
}
Playground Example
In Golang you should avoid passing a pointer to interface as:
The compiler will complain about this error but the situation can
still be confusing, because sometimes a pointer is necessary to
satisfy an interface. The insight is that although a pointer to a
concrete type can satisfy an interface, with one exception a pointer
to an interface can never satisfy an interface.
Consider the variable declaration,
var w io.Writer
The printing function fmt.Fprintf takes as its first argument a value that satisfies io.Writer—something that implements the canonical Write method. Thus we can write
fmt.Fprintf(w, "hello, world\n")
If however we pass the address of w, the program will not compile.
fmt.Fprintf(&w, "hello, world\n") // Compile-time error.
The one exception is that any value, even a pointer to an interface,
can be assigned to a variable of empty interface type (interface{}).
Even so, it's almost certainly a mistake if the value is a pointer to
an interface; the result can be confusing.
Check it on Go playground. You will find the same error you are getting in your code snippet when trying to pass pointer to interface.

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

Pointer to a struct (or lack thereof)

Let's say I have defined this struct:
type Vertex struct {
X, Y float64
}
now it's perfectly legal Go to use it like this:
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := &Vertex{3, 4}
fmt.Println(v.Abs())
}
but it's also ok not to use a pointer:
func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs())
}
The results in both cases is the same, but how are they different, internally? Does the use of pointer makes the program run faster?
PS. I get it that the Abs() function needs a pointer as a receiver. That explains the reason why a pointer has been used later in the main function. But why doesn't the program spit out an error when I don't use a pointer and directly call Abs() on a struct instance?
why doesn't the program spit out an error when I don't use a pointer and directly call Abs() on a struct instance?
Because you can get the pointer to (address of) a struct instance.
As mentioned in "What do the terms pointer receiver and value receiver mean in Golang?"
Go will auto address and auto-dereference pointers (in most cases) so m := MyStruct{}; m.DoOtherStuff() still works since Go automatically does (&m).DoOtherStuff() for you.
As illustrated by "Don't Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang" or "Go 101: Methods on Pointers vs. Values", using a pointer receiver (v *Vertex) is great to avoid copy, since Go passes everything by value.
The spec mentions (Method values):
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.

Pointer operator -> for golang

It seems golang does not have the pointer operator -> as C and C++ have. Now let's say I have a function looks something like this: myfun(myparam *MyType), inside the function, if I want to access the member variables of MyType, I have to do (*myparam).MyMemberVariable. It seems to be a lot easier to do myparam->MyMemberVariable in C and C++.
I'm quite new to go. Not sure if I'm missing something, or this is not the right way to go?
Thanks.
In Go, both -> and . are represented by .
The compiler knows the types, and can dereference if necessary.
package main
import "fmt"
type A struct {
X int
}
func main() {
a0, a1 := A{42}, &A{27}
fmt.Println(a0.X, a1.X)
}
You can do myparam.MyMemberValue, pointers are automatically dereferenced
Go spec:
Selectors automatically dereference pointers to structs. If x is a pointer to a struct, x.y is shorthand for (x).y; if the field y is also a pointer to a struct, x.y.z is shorthand for ((*x).y).z, and so on. If x contains an anonymous field of type *A, where A is also a struct type, x.f is shorthand for (*x.A).f.
Hummm, this automatic dereferencing can be very confusing (for old programmers like me)
If you learn programmation with GOLANG, no problem, it is practical.
If you pass from C to GOLANG, this will seem strange, you will probably prefer (at the beginning at least) to keep the "(*my_var).my_field" expression instead of "my_var.myfield"
If you pass from GOLANG to C, you will get many compilation errors.
Goes uses -> for passing data by using channels.
package main
import "fmt"
type Person struct {
Name string
}
func (p *Person) printName() {
p.Name = "brian"
}
func main() {
// obj
brian := Person{""}
// prints obj default value
fmt.Println("No pointer", brian.Name)
// it access the method with the pointer
brian.printName()
// prints the result
fmt.Println("With a pointer", brian.Name)
}

Resources