Intro
We declare an Interface much like as we define a user defined type. Interfaces decouple different types from each other so we can create more maintainable programs.
More:
An
Interfaceis aProtocol, aContract.Bigger the
Interfacethe weaker theabstraction. –>Rob PikeIt’s an
abstract type. It doesn’t have any implementation. It only describesthe expected behavior.The opposite of
Abstract TypeisConcrete Type.All the
typesin Go exceptInterfaceare ofConcrete Type.For e.g. Following are
Concrete Types:
// Concrete Types
int
string
float64
array
struct
slice
map
chan
func
The Interface only defines the expected behavior.
Go does not have an implements keyword.
A Type satisfies an Interface automaticallywhen it hasall the methods of the Interfacewithout explicitely specifying it.Interfacevalues arecomparable.Go interfacesareimplicit. The implementing types don’t need to specify that they implement an interface.
Interface declaration example
type MyInterface interface {
foo() int
bar() float64
baz() string
}
Interface Example
Interface is a reference type which contains some method definitions. Any type which implements all the methods defined by a reference type will satisfy this interface type automatically. Through interface, you can approach object-oriented programming. Check the following example:
package main
import "fmt"
type Foo interface {
foo()
}
type A struct {
}
func (a A) foo() {
fmt.Println("A foo")
}
func (a A) bar() {
fmt.Println("A bar")
}
func callFoo(f Foo) {
f.foo()
}
func main() {
var a A
callFoo(a)
}
The running result is:
A foo
Let’s analyze the code detailedly:
(1)
type Foo interface {
foo()
}
The above code defines a interface Foo which has only one method: foo().
(2)
type A struct {
}
func (a A) foo() {
fmt.Println("A foo")
}
func (a A) bar() {
fmt.Println("A bar")
}
struct A has 2 methods: foo() and bar(). Since it already implements foo() method, it satisfies Foo interface.
(3)
func callFoo(f Foo) {
f.foo()
}
func main() {
var a A
callFoo(a)
}
callFoo requires a variable whose type is Foo interface, and passing A is OK. The callFoo will use A’s foo() method, and “A foo” is printed.
Implementing interface with pointer receiver
Let’s change the main() function:
func main() {
var a A
callFoo(&a)
}
This time, the argument of callFoo() is &a, whose type is *A. Compile and run the program, you may find it also outputs: “A foo”. So *A type has all the methods which A has. But the reverse is not true:
package main
import "fmt"
type Foo interface {
foo()
}
type A struct {
}
func (a *A) foo() {
fmt.Println("A foo")
}
func (a *A) bar() {
fmt.Println("A bar")
}
func callFoo(f Foo) {
f.foo()
}
func main() {
var a A
callFoo(a)
}
Compile the program:
example.go:26: cannot use a (type A) as type Foo in argument to callFoo:
A does not implement Foo (foo method has pointer receiver)
You can see also *A type has implemented foo() and bar() methods, it doesn’t mean A type has both methods by default.
Empty Interface
Every type in Go implements the empty interface: interface{}. It doesn’t have any methods.
Eg.
type someInterface interface {
}
Note:
Do not use
Empty Interfaceunless really necessary.It can represent any
TypeofValue.We can’t directly use the
dynamic valueof anempty interface value.
Using the empty interface value
To use a
valuefromEmpty Interface, we first need toextractit usingType Assertion.Empty Interface Slicecontains theEmpty Interface Values.Example use cases of empty interfaces:
- A function that returns a value of
interface{}can return anytype. - We can store heterogeneous values in an
array,slice, ormapusing the emptyinterface{} type.
- A function that returns a value of
Interface as nil
The interface type is actually a tuple which contains 2 elements: <type, value>:
- A dynamic
Value-valuepoints to the actual value - A dynamic
Type-typeidentifies the type of the variable which stores in the interface
The default value of an interface type is nil, which means both type and value are nil: <nil, nil>. When you check whether an interface is empty or not:
var err error
if err != nil {
...
}
You must remember only if both type and value are nil means the interface value is nil.
Reference:
The Go Programming Language.
https://github.com/NanXiao/golang-101-hacks