A good article for reference here
Some takeaways:
1. Define A Interface.
- An Interface is basically a set of methods required to implement this interface.
- An Interface can embed other interfaces, either defined in the same package or imported from other packages. (Using qualified name (packagename.interfacename))
- Circular embedding of interfaces is disallowed and will be detected while compilation.
- Interface methods must have unique names, no matter where they comes from.
2. Values of An Interface Type
- Variable of interface type I can hold any value implementing I.
- Interface itself is a static type (Specified when declaration && no change).
- The assigned value of an interface is a dynamic type.
- Zero value of an interface is nil.
- Get dynamic type of the value of an interface type:
fmt.Println(reflect.TypeOf(i).PkgPath(), reflect.TypeOf(i).Name()) fmt.Println(reflect.TypeOf(i).String())
or
fmt.Printf("%T\n", i)
Note: Under the hood it uses reflect package though but this method works even when i is nil.
3. More About Interface Type Value
Interface type value consists of two components:
- dynamic type
- dynamic value
Interface type value is nil iff both dynamic value and dynamic type are nil.
4. Empty Interface
A prominent use of empty interface exists in variadic function fmt.Println.
func Println(a ...interface{}) (n int, err error)
package main
import (
"fmt"
)
func main() {
const name, age = "Kim", 22
fmt.Println(name, "is", age, "years old.")
// It is conventional not to worry about any
// error returned by Println.
}
5. Finally
- Every type which implements all interface’s method automatically satisfies such interface. ==> This is more flexible, since we can create interface that was implemented by exist types without change these types.
- A type satisfied an interface can have other methods which are not required by the interface. And interface type value gives access ONLY to methods of its interface type.