Definition of interface (Entry 1 of 2) 1a : the place at which independent and often unrelated systems meet and act on or communicate with each other the man-machine interface. b : the means by which interaction or communication is achieved at an interface.
The type interface{} applies to any value. A variable declared as interface{} can hold a string value, an integer, any kind of struct, a pointer to an os. File , or indeed anything you can think of.
Why do we use an Interface? It is used to achieve total abstraction. Since java does not support multiple inheritances in the case of class, by using an interface it can achieve multiple inheritances. It is also used to achieve loose coupling.
An interface in Go is a type defined using a set of method signatures. The interface defines the behavior for similar type of objects. An interface is declared using the type keyword, followed by the name of the interface and the keyword interface . Then, we specify a set of method signatures inside curly braces.
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 (orany
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 aninterface{}
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 isv
'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 ofinterface{}
type.When passing a value into the
DoSomething
function, the Go runtime will perform a type conversion (if necessary), and convert the value to aninterface{}
value.
All values have exactly one type at runtime, andv
's one static type isinterface{}
(orany
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 forStringer
holding type Binary lists the methods used to satisfy Stringer, which is justString
: Binary's other methods (Get
) make no appearance in theitable
.The second word in the interface value points at the actual data, in this case a copy of
b
.
The assignmentvar s Stringer = b
makes a copy ofb
rather than point atb
for the same reason thatvar c uint64 = b
makes a copy: ifb
later changes,s
andc
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 seeinginterface{}
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 usinginterface{}
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 useinterface{}
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
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.
There are already good answers here. Let me add my own too for others who want to understand it intuitively:
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.
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
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:
T
has 3 methods: A
, B
, C
.T_interface = (A, B, C)
MyInterface = (A, )
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With