patterngoCritical
What's the meaning of interface{}?
Viewed 0 times
meaninginterfacewhatthe
Problem
I'm new to interfaces and trying to do SOAP request by github
I don't understand the meaning of
in this code:
I've observed the same syntax in
but don't understand what's being achieved by
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.Printlnbut don't understand what's being achieved by
interface{}Solution
Note: Go 1.18 (Q1 2022) does rename
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:
The
Since there is no implements keyword, all types implement at least zero methods, and satisfying an interface is done automatically, therefore all types satisfy the empty interface.
That means that if you write a function that takes an
(That is what
Here’s where it gets confusing:
inside of the
Beginner gophers are led to believe that “
When passing a value into the
All values have exactly one type at runtime, and
An interface value is constructed of two words of data:
Addendum: This is were Russ's article is quite complete regarding an interface structure:
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
The second word in the interface value points at the actual data, in this case a copy of
The assignment
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
Russ Cox explains:
-
'
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.
-
'
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 '
-
If we allow '
Some code using
Rewriting it one way or another to remove the text '
That thread also includes an explanation about
It's not a special design, but a logical consequence of Go's
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, therefore 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
Context
Stack Overflow Q#23148812, score: 251
Revisions (0)
No revisions yet.