Trying to do go koan, i got stuck in understanding the interface(struct) syntax, what exactly
does it do ?
I came up with following fun program, which has further confused me on how is interface casting working :
package main
import "fmt"
type foo interface{ fn() }
type t struct { }
type q struct { }
func (_i t ) fn() { fmt.Print("t","\n") }
func (_i q ) fn() { fmt.Print("q","\n")}
func main() {
_j := t{}
_q := q{}
// This is alright ..
fmt.Print( _j.fn,"\n") //0x4015e0
fmt.Print( _q.fn,"\n") //0x401610
_j.fn() //t
_q.fn() //q
// both pointers same .. why ?
fmt.Print( foo(_j).fn,"\n") //0x401640
fmt.Print( foo(_q).fn,"\n") //0x401640
// but correct fns called .. how ?
foo(_j).fn() //t
foo(_q).fn() //q
// same thing again ...
_fj := foo(_j).fn
_fq := foo(_q).fn
// both pointers same .. as above
fmt.Print( _fj,"\n") //0x401640
fmt.Print( _fq,"\n") //0x401640
// correct fns called .. HOW !
_fj() //t
_fq() //q
}
The pointer are what i'm getting my machin, YMMV.
My question is .. what exactly does interface(struct) returns ?
and how does interface(struct).func , finds the original struct ...
is there some thunk/stub magic going on here?
From here: http://research.swtch.com/interfaces
what exactly does interface(struct) return?
It creates a new interface value (like the one you see on top in the graphic), wrapping a concrete struct value.
how does interface(struct).func find the original struct?
See the data field in the graphic. Most of the time this will be a pointer to an existing value. Sometimes it will contain the value itself if it fits, though.
In the itable you'll see a function table (where fun[0] is).
I assume that on your machine 0x401640 is the address of the respective pointers to fn, which is in that table for foo. Although this is best verified by someone working on the GC compiler suite.
Note that the behaviour you discovered is not strictly defined to be so. Compiler builders can take other approaches to implementing Go interfaces if they like to, as long as the language semantics are preserved.
Edit to answer questions in the comments:
package main
import "fmt"
type foo interface {
fn()
}
type t struct{}
type q struct{}
func (_i t) fn() { fmt.Print("t", "\n") }
func (_i q) fn() { fmt.Print("q", "\n") }
func main() {
_j := t{}
_j1 := t{}
fmt.Println(foo(_j) == foo(_j)) // true
fmt.Println(foo(_j) == foo(_j1)) // true
}
On the diagram you see 3 blocks:
The one on the left side labeled Binary is a concrete type instance, like your struct instances _j and _j1.
The one on the top center is an interface value, this one wraps (read: points to) a concrete value.
The block on the right lower side is the interface definition for Binary underlyings. This is where the jump table / call forwarding table is (itable).
_j and _j1 are two instances of the concrete type t. So there are two of the lower-left blocks somewhere in memory.
Now you decide to wrap both _j and _j1 in interfaces values of type foo; now you have 2 of the top-center blocks somewhere in memory, pointing back at _j and _j1.
In order for the interface value to remember what its underlying type is and where the methods of those types are it keeps a single instance of the lower-right block in memory, to which both interface values for _j and _j1 respectively point to.
In that block you have a jump table to forward method calls made on the interface values to the concrete underlying type's implementation. That's why both are the same.
It's worth mentioning that unlike Java and C++ (not sure about Python), all Go methods are static and the dot-call notation is only syntactic sugar. So _j and _j1 don't have different fn methods, it's the same exact method called with another implicit first parameter which is the receiver on which the method is called.
Related
I'm probably not expressing this correctly in the question, but perhaps this code will make it clearer:
package main
import "fmt"
type Blob struct {
Message string
}
func assign1(bb **Blob) {
*bb = &Blob{"Internally created by assign1"}
}
func (b *Blob) assign2() {
*b = Blob{"Internally created by assign2"}
}
func main() {
x1 := &Blob{"Hello World"}
assign1(&x1)
fmt.Printf("x1 = %+v\n", *x1)
x2 := Blob{"Hello World"}
x2.assign2()
fmt.Printf("x2 = %+v\n", x2)
}
Produces, as desired:
x1 = {Message:Internally created by assign1}
x2 = {Message:Internally created by assign2}
I want to pass a reference (pointer to a pointer) into a function and have the function assign a new value to the pointer such that the calling scope will see that new value.
I've figured out the above two ways of doing this, but I'd like to know if they are actually correct or if there is some hidden flaw. Also, are either of them more idiomatic than the other?
Coming from Java, assign2 just seems wrong but I'm sure I've seen something similar in the encoding/json package. What is that actually doing?
Thanks!
James answers the mechanics of assign2. I'll touch a bit on when to use it.
Let's take a simpler example, first.
type Counter uint
func (c *Counter) Increment() {
*c += 1
}
In the counter example the entire state of the receiver is changing. Similarly for the encoding/json package the entire state of the receiver is changing. That's really the only time I would use that style.
One major advantage of the style: you can define an interface for the change, just like the GobDecoder does.
When I first saw the assign2 style it was a little grating. But then I remembered that (c *Counter) Increment gets translated to Increment(c *Counter) in the machine code and it didn't bother me anymore. I personally prefer assign1-style. (Though, there is no need for the double pointers as orignally posted.)
package main
import "fmt"
type Blob struct {
Message string
}
func assign1(b *Blob) {
*b = Blob{"Internally created by assign1"}
}
func main() {
x1 := Blob{"Hello World"}
assign1(&x1)
fmt.Printf("x1 = %+v\n", *x1)
}
Both forms are valid Go, as you've discovered.
For the assign2 case, the compiler finds that assign2 does not appear in Blob's method set, but it is part of *Blob's method set. It then converts the method call to:
(&x2).assign2()
While it can be confusing if a method then goes and changes x2 like in your example, there are a number of places in the standard library where this pattern is used. Probably the most common one is implementing custom decoding for a type with the encoding/json module: you implement the DecodeJSON method with a pointer receiver, and update the value being pointed to.
I want to compare 2 instance of the same struct to find out if it is equal, and got two different result.
comment the code // fmt.Println("%#v\n", a), the program output is "Equal"
Use the fmt to print variable "a", then I got the output "Not Equal"
Please help me to find out Why???
I use golang 1.2.1
package main
import (
"fmt"
)
type example struct {
}
func init() {
_ = fmt.Printf
}
func main() {
a := new(example)
b := new(example)
// fmt.Println("%#v\n", a)
if a == b {
println("Equals")
} else {
println("Not Equals")
}
}
There are several aspects involved here:
You generally cannot compare the value of a struct by comparing the pointers: a and b are pointers to example not instances of example. a==b compares the pointers (i.e. the memory address) not the values.
Unfortunately your example is the empty struct struct{} and everything is different for the one and only empty struct in the sense that it does not really exist as it occupies no space and thus all different struct {} may (or may not) have the same address.
All this has nothing to do with calling fmt.Println. The special behavior of the empty struct just manifests itself through the reflection done by fmt.Println.
Just do not use struct {} to test how any real struct would behave.
I'm new to interfaces and trying to do SOAP request by github
I don't understand the meaning of
Msg interface{}
in this code:
type Envelope struct {
Body `xml:"soap:"`
}
type Body struct {
Msg interface{}
}
I've observed the same syntax in
fmt.Println
but don't understand what's being achieved by
interface{}
Note: Go 1.18 (Q1 2022) does rename interface{} to any (alias for interface{}).
See issue 49884, CL 368254 and commit 2580d0e.
See the last part of this answer.
You can refer to the article "How to use interfaces in Go" (based on "Russ Cox’s description of interfaces"):
What is an interface?
An interface is two things:
it is a set of methods,
but it is also a type
The interface{} type (or any with Go 1.18+), the empty interface is the interface that has no methods.
Since there is no implements keyword, all types implement at least zero methods, and satisfying an interface is done automatically, all types satisfy the empty interface.
That means that if you write a function that takes an interface{} value as a parameter, you can supply that function with any value.
(That is what Msg represents in your question: any value)
func DoSomething(v interface{}) {
// ...
}
func DoSomething(v any) {
// ...
}
Here’s where it gets confusing:
inside of the DoSomething function, what is v's type?
Beginner gophers are led to believe that “v is of any type”, but that is wrong.
v is not of any type; it is of interface{} type.
When passing a value into the DoSomething function, the Go runtime will perform a type conversion (if necessary), and convert the value to an interface{} value.
All values have exactly one type at runtime, and v's one static type is interface{} (or any with Go 1.18+).
An interface value is constructed of 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.
Addendum: This is were Russ's article is quite complete regarding an interface structure:
type Stringer interface {
String() string
}
Interface values are represented as a two-word pair giving a pointer to information about the type stored in the interface and a pointer to the associated data.
Assigning b to an interface value of type Stringer sets both words of the interface value.
The first word in the interface value points at what I call an interface table or itable (pronounced i-table; in the runtime sources, the C implementation name is Itab).
The itable begins with some metadata about the types involved and then becomes a list of function pointers.
Note that the itable corresponds to the interface type, not the dynamic type.
In terms of our example, the itable for Stringer holding type Binary lists the methods used to satisfy Stringer, which is just String: Binary's other methods (Get) make no appearance in the itable.
The second word in the interface value points at the actual data, in this case a copy of b.
The assignment var s Stringer = b makes a copy of b rather than point at b for the same reason that var c uint64 = b makes a copy: if b later changes, s and c are supposed to have the original value, not the new one.
Values stored in interfaces might be arbitrarily large, but only one word is dedicated to holding the value in the interface structure, so the assignment allocates a chunk of memory on the heap and records the pointer in the one-word slot.
Issue 33232 seems to point out to any as an alias to interface{} in Go 1.18 (Q1 2022)
Russ Cox explains:
'any' being only for constraints is a detail that will be in every writeup of generics - books, blog posts, and so on.
If we think we are likely to allow it eventually, it makes sense to allow it from the start and avoid invalidating all that written material.
'any' being only for constraints is an unexpected cut-out that reduces generality and orthogonality of concepts.
It's easy to say "let's just wait and see", but prescribing uses tends to create much more jagged features than full generality. We saw this with type aliases as well (and resisted almost all the proposed cut-outs, thankfully).
If 'any' is allowed in generics but not non-generic code, then it might encourage people to overuse generics simply because 'any' is nicer to write than 'interface{}', when the decision about generics or not should really be made by considering other factors.
If we allow 'any' for ordinary non-generic usage too, then seeing interface{} in code could serve as a kind of signal that the code predates generics and has not yet been reconsidered in the post-generics world.
Some code using interface{} should use generics. Other code should continue to use interfaces.
Rewriting it one way or another to remove the text 'interface{}' would give people a clear way to see what they'd updated and hadn't. (Of course, some code that might be better with generics must still use interface{} for backwards-compatibility reasons, but it can still be updated to confirm that the decision was considered and made.)
That thread also includes an explanation about interface{}:
It's not a special design, but a logical consequence of Go's type declaration syntax.
You can use anonymous interfaces with more than zero methods:
func f(a interface{Foo(); Bar()}) {
a.Foo()
a.Bar()
}
Analogous to how you can use anonymous structs anywhere a type is expected:
func f(a struct{Foo int; Bar string}) {
fmt.Println(a.Foo)
fmt.Println(a.Bar)
}
An empty interface just happens to match all types because all types have at least zero methods.
Removing interface{} would mean removing all interface functionality from the language if you want to stay consistent / don't want to introduce a special case.
interface{} means you can put value of any type, including your own custom type. All types in Go satisfy an empty interface (interface{} is an empty interface).
In your example, Msg field can have value of any type.
Example:
package main
import (
"fmt"
)
type Body struct {
Msg interface{}
}
func main() {
b := Body{}
b.Msg = "5"
fmt.Printf("%#v %T \n", b.Msg, b.Msg) // Output: "5" string
b.Msg = 5
fmt.Printf("%#v %T", b.Msg, b.Msg) //Output: 5 int
}
Go Playground
There are already good answers here. Let me add my own too for others who want to understand it intuitively:
Interface
Here's an interface with one method:
type Runner interface {
Run()
}
So any type that has a Run() method satisfies the Runner interface:
type Program struct {
/* fields */
}
func (p Program) Run() {
/* running */
}
func (p Program) Stop() {
/* stopping */
}
Although the Program type has also a Stop method, it still satisfies the Runner interface because all that is needed is to have all of the methods of an interface to satisfy it.
So, it has a Run method and it satisfies the Runner interface.
Empty Interface
Here's a named empty interface without any methods:
type Empty interface {
/* it has no methods */
}
So any type satisfies this interface. Because, no method is needed to satisfy this interface. For example:
// Because, Empty interface has no methods, following types satisfy the Empty interface
var a Empty
a = 5
a = 6.5
a = "hello"
But, does the Program type above satisfy it? Yes:
a = Program{} // ok
interface{} is equal to the Empty interface above.
var b interface{}
// true: a == b
b = a
b = 9
b = "bye"
As you see, there's nothing mysterious about it but it's very easy to abuse. Stay away from it as much as you can.
https://play.golang.org/p/A-vwTddWJ7G
It's called the empty interface and is implemented by all types, which means you can put anything in the Msg field.
Example :
body := Body{3}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:3}
body = Body{"anything"}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:"anything"}
body = Body{body}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:main.Body{Msg:"anything"}}
This is the logical extension of the fact that a type implements an interface as soon as it has all methods of the interface.
From the Golang Specifications:
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. The value of an uninitialized variable of
interface type is nil.
A type implements any interface comprising any subset of its methods
and may therefore implement several distinct interfaces. For instance,
all types implement the empty interface:
interface{}
The concepts to graps are:
Everything has a Type. You can define a new type, let's call it T. Let's say now our Type T has 3 methods: A, B, C.
The set of methods specified for a type is called the "interface type". Let's call it in our example: T_interface. Is equal to T_interface = (A, B, C)
You can create an "interface type" by defining the signature of the methods. MyInterface = (A, )
When you specify a variable of type, "interface type", you can assign to it only types which have an interface that is a superset of your interface.
That means that all the methods contained in MyInterface have to be contained inside T_interface
You can deduce that all the "interface types" of all the types are a superset of the empty interface.
An example that extends the excellent answer by #VonC and the comment by #NickCraig-Wood. interface{} can point to anything and you need a cast/type assertion to use it.
package main
import (
. "fmt"
"strconv"
)
var c = cat("Fish")
var d = dog("Bone")
func main() {
var i interface{} = c
switch i.(type) {
case cat:
c.Eat() // Fish
}
i = d
switch i.(type) {
case dog:
d.Eat() // Bone
}
i = "4.3"
Printf("%T %v\n", i, i) // string 4.3
s, _ := i.(string) // type assertion
f, _ := strconv.ParseFloat(s, 64)
n := int(f) // type conversion
Printf("%T %v\n", n, n) // int 4
}
type cat string
type dog string
func (c cat) Eat() { Println(c) }
func (d dog) Eat() { Println(d) }
i is a variable of an empty interface with a value cat("Fish"). It is legal to create a method value from a value of interface type. See https://golang.org/ref/spec#Interface_types.
A type switch confirms i interface type is cat("Fish") . See https://golang.org/doc/effective_go.html#type_switch. i is then reassigned to dog("Bone"). A type switch confirms that i interface’s type has changed to dog("Bone") .
You can also ask the compiler to check that the type T implements the interface I by attempting an assignment: var _ I = T{}. See https://golang.org/doc/faq#guarantee_satisfies_interface and https://stackoverflow.com/a/60663003/12817546.
All types implement the empty interface interface{}. See https://talks.golang.org/2012/goforc.slide#44 and https://golang.org/ref/spec#Interface_types . In this example, i is reassigned, this time to a string "4.3".i is then assigned to a new string variable s with i.(string) before s is converted to a float64 type f using strconv. Finally f is converted to n an int type equal to 4. See What is the difference between type conversion and type assertion?
Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly. See https://golang.org/doc/faq#generics.
Interface is a type which is unknown at compile time
It is a contract between object and the struct type to satisfy with common functionality
or
common functionality acting on different types of struct objects
for example in the below code PrintDetails is a common functionality acting on different types of structs as Engineer,Manager,
Seniorhead
please find the example code
interface examplehttps://play.golang.org/p/QnAqEYGiiF7
A method can bind to any type(int, string, pointer, and so on) in GO
Interface is a way of declear what method one type should have, as long as A type has implement those methods, this can be assigned to this interface.
Interface{} just has no declear of method, so it can accept any type
this code works fine but the temp var used to call the function feels clunky
package main
import "fmt"
type Foo struct {
name string
value int
}
// SetName receives a pointer to Foo so it can modify it.
func (f *Foo) SetName(name string) {
f.name = name
}
var users = map[string]Foo{}
func main() {
// Notice the Foo{}. The new(Foo) was just a syntactic sugar for &Foo{}
// and we don't need a pointer to the Foo, so I replaced it.
// Not relevant to the problem, though.
//p := Foo{}
users["a"] = Foo{value: 1}
x := users["a"]
x.SetName("Abc")
users["a"] = x
fmt.Println(users)
}
http://play.golang.org/p/vAXthNBfdP
Unfortunately no. In Go typically pointers are transparent, and values get auto-addressed when you call pointer methods on them. You managed to find one of the few cases where they aren't. That case is map storage -- values in maps are not considered addressable. That is, you can never do val := &map[key].
When you have a value val := Typ{} and methods defined on *Typ, when you try to call val.Method() Go will super secretly do (&val).Method(). Since you can't do &map[key], then this doesn't work so that temporary variable dance you do is the only way.
As for why that's the case, the internals of a map are considered a bit secret to the user, since it's a hashmap it reserves the right to reallocate itself, shuffle around data, etc, allowing you to take the address of any value undermines that. There have been proposals considered to allow this specific case to work (that is: calling a method with a pointer receiver on it), since the fix is so easy, but none have been accepted yet. It may be allowed someday, but not right now.
Following Jsor’s detailed explanation: if you really need to call methods of map values, it seems the only way for now is to use pointers for values.
var users = make(map[string]*Foo)
func main() {
users["a"] = &Foo{value: 1}
users["a"].SetName("Abc")
fmt.Println(users["a"])
}
But that loses you, precisely, the ability to meaningfully print them (values are just memory addresses now). You’d need to write a custom printing function for *Foo:
func (f *Foo) String() string {
return fmt.Sprintf("%v", *f)
}
http://play.golang.org/p/6-y2ewdnre
The code below produces undesirable
[20010101 20010102].
When uncommenting the String func it produces better (but not my implementation):
[{20010101 1.5} {20010102 2.5}]
However that String func is never called.
I see that Date in DateValue is anonymous and therefore func (Date) String is being used by DateValue.
So my questions are:
1) Is this a language issue, a fmt.Println implementation issue, or
something else? Note: if I switch from:
func (*DateValue) String() string
to
func (DateValue) String() string
my function is at least called and panic ensues. So if I really want my method called I could do that, but assume DateValue is really a very large object which I only want to pass by reference.
2) What is a good strategy for mixing anonymous fields with
functionality like Stringer and json encoding that use reflection
under the covers? For example adding a String or MarshalJSON method
for a type that happens to be used as an anonymous field can cause
strange behavior (like you only print or encode part of the whole).
package main
import (
"fmt"
"time"
)
type Date int64
func (d Date) String() string {
t := time.Unix(int64(d),0).UTC()
return fmt.Sprintf("%04d%02d%02d", t.Year(), int(t.Month()), t.Day())
}
type DateValue struct {
Date
Value float64
}
type OrderedValues []DateValue
/*
// ADD THIS BACK and note that this is never called but both pieces of
// DateValue are printed, whereas, without this only the date is printed
func (dv *DateValue) String() string {
panic("Oops")
return fmt.Sprintf("DV(%s,%f)", dv.Date, dv.Value )
}
*/
func main() {
d1, d2 := Date(978307200),Date(978307200+24*60*60)
ov1 := OrderedValues{{ d1, 1.5 }, { d2, 2.5 }}
fmt.Println(ov1)
}
It's because you've passed in a slice of DateValues and not DateValue pointers. Since you've defined the String method for *DataValue, *DateValue is what fulfills the Stringer interface. This also prevents DateValue from fulfilling the Stringer interface via its anonymous Date member, because only one of either the value type (DateValue) or the pointer type (*DateValue) can be used to fulfill an interface. So, when fmt.Println is printing the contents of the slice, it sees that the elements are not Stringers, and uses the default struct formatting instead of the method you defined, giving [{20010101 1.5} {20010102 2.5}].
You can either make OrderedValues a []*DateValue or define func (dv DateValue) String() string instead of the pointer version.
Based on what #SteveM said, I distilled it to a simpler test case:
package main
import "fmt"
type Fooable interface {
Foo()
}
type A int
func (a A) Foo() { }
type B struct {
A
}
// Uncomment the following method and it will print false
//func (b *B) Foo() { }
func main() {
var x interface{} = B{}
_, ok := x.(Fooable)
fmt.Println(ok) // prints true
}
In other words, the Foo method is not part of the method set of B when the Foo method for *B is defined.
From reading the spec, I don't see a clear explanation of what is happening. The closest part seems to be in the section on selectors:
For a value x of type T or *T where T is not an interface type, x.f
denotes the field or method at the shallowest depth in T where there
is such an f.
The only way I can see this explaining what is going on is if when it is looking for a method Foo at shallowest depth in B, it takes into consideration the methods for *B too, for some reason (even though we are considering type B not *B); and the Foo in *B is indeed shallower than the Foo in A, so it takes that one as the candidate; and then it sees that that Foo doesn't work, since it's in *B and not B, so it gets rid of Foo altogether (even though there is a valid one inherited from A).
If this is indeed what is going on, then I agree with the OP in that this is very counter-intuitive that adding a method to *B would have the reverse consequence of removing a method from B.
Maybe someone more familiar with Go can clarify this.