This paper mainly introduces the concept and use of interface in Go language. If there is any wrong or unreasonable description in the article, please leave a message. I will check and correct it in time every day.
concept
- Represents a “protocol” or “convention” and is a collection of method declarations
- Interfaces do not depend on types
define
- An interface must include a method signature, which must contain the method name, parameters, and return values. Interfaces cannot have fields and cannot define their own methods.
// Animaler Indicates the Animaler interface name
type Animaler interface {
eat(food string) string
sleep()
}
Copy the code
Basic Application Scenarios
Implement polymorphic functions
package main
import (
"fmt"
)
// Animaler interface: All compliance with this interface protocol, need to implement the speak,eat method
type Animaler interface {
speak() string
eat(foot string) string
}
func anmialSpeak(animaler Animaler) string {
return animaler.speak()
}
func anmialEat(animaler Animaler, food string) string {
return animaler.eat(food)
}
/ / Dog class
type Dog struct {
name string
}
// Speak Dog method
func (d Dog) speak(a) string {
return "Wang wang"
}
// Eat Dog
func (d Dog) eat(foot string) string {
return fmt.Sprintf("%s: eat %s", d.name, foot)
}
/ / the Cat
type Cat struct {
age int
}
// Speak Cat method
func (c Cat) speak(a) string {
return "Meow"
}
// Eat the Cat method
func (c Cat) eat(foot string) string {
return fmt.Sprintf("%d cat eat %s", c.age, foot)
}
func test004(a) {
dog := Dog{name : "White"}
cat := Cat{age: 2}
fmt.Println(anmialSpeak(dog)) / / wang wang
fmt.Println(anmialSpeak(cat)) / / meow meow
fmt.Println(anmialEat(dog, "Pork")) // Baymax: Eat pork
fmt.Println(anmialEat(cat, "Cat food")) // 2 Cat eat
}
func main(a) {
test004()
}
Copy the code
Empty interface
- If the interface does not have any method declarations, it is one
Empty interface (interface{})
, which serves a similar purpose to Object, the root type in Object, and can be assigned toAny type of object (value)
. - All types are implemented
Empty interface
interface{}
It’s not just any type, it’s justinterface{}
type
// Remember that v is not of any type, but of interface{} type; If the GO runtime needs to convert the execution type to interface{}, and all values have only one type at runtime, that is, type static.
func do(v interface{}){}func done(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}
}
func test007(a) {
vals := []string {"conk"."pht"."nimibox"}
Cannot use vals (type []string) as type []interface {} in argument to done
done(vals)
}
func test008(a) {
vals := []string {"conk"."pht"."nimibox"}
newVals := make([]interface{}, len(vals))
for index, v := range vals {
newVals[index] = v
}
done(newVals)
}
Copy the code
Use of Pointers in interfaces
- The interface definition does not specify whether an implementer should use one
Pointer receiver
Or aValue of the receiver
To implement the interface - A pointer type can access the methods of a value type through its associated value type, but not the other way around
- Everything in Go is passed by value. Each time a function is called, the incoming data is copied. For methods that have a value receiver, the value is copied when the method is called.
/ / Dog class
type Dog struct {
name string
}
// Speak Dog method
func (d Dog) speak(a) string {
return "Wang wang"
}
func (d Dog) eat(foot string) string {
return fmt.Sprintf("%s: eat %s", d.name, foot)
}
/ / the Cat
type Cat struct {
age int
}
// Speak Cat method
func (c *Cat) speak(a) string {
return "Meow"
}
func (c *Cat) eat(foot string) string {
return fmt.Sprintf("%d cat eat %s", c.age, foot)
}
// Any value of Cat may have many *Cat Pointers to it. If we try to call the *Cat method from a value of Cat, we will not know which pointer is corresponding
func test009(a) {
Cannot use Cat literal (type Cat) as type Animaler in slice literal: Cat does not implement Animaler (eat method has pointer receiver)
animals := []Animaler {Dog{"White"}, Cat{18}}}func test010(a) {
// Pay attention to the details: the Dog class instantiates two objects, one pointer and one value; But the compilation is fine
anmials := []Animaler {Dog{"White"}, &Cat{18}}, &Dog{"Black"}}
for _, animal := range anmials {
fmt.Println(animal.speak())
}
}
Copy the code
Type conversion
Ok - the idiom mode
package main
import (
"fmt"
)
type data int
func (d data) String(a) string {
return fmt.Sprintf("data : %d\n", d)
}
func test001(a) {
// Create an instance of type data
var d data = 10
// Create an interface instance
var inter interface{} = d
fmt.Printf("%T\n", inter) // main.data
// Determine the more specific interface type of inter: initialize to interface{} Empty interface type more specific to fmt.Stringer interface type
if x, ok := inter.(fmt.Stringer); ok {
fmt.Println(x) // data: 10
}
// Determine the original type of inter
if y, ok := inter.(data); ok {
fmt.Println(y) // data: 10
}
// panic: interface conversion: main.data is not error: missing method Error
e := inter.(error) // Do not use ok-idiom mode, conversion failure will cause panic
fmt.Println(e)
}
func main(a) {
test001()
}
Copy the code
Type checking
package main
import (
"fmt"
)
// A generic interface type check function
func inspect(inter interface{}) {
switch v := inter.(type) {
case nil:
fmt.Println("nil")
case *int:
fmt.Println(*v)
case func(int) string:
fmt.Println(v(100))
case fmt.Stringer:
fmt.Println(v)
default:
println("not support")}}func test002(a) {
var inter interface{} = func(num int) string {
return fmt.Sprintf("num: %d\n", num)
}
inspect(inter)
}
func main(a) {
test002()
}
Copy the code
Variable length type check
// Can pass n unlimited number of arguments
func inspect(inters ...interface{}) {
for index, inter := range(inters): {
switch v := inter.(type) {
case nil:
fmt.Println("nil")
case *int:
fmt.Println(*v)
case func(int) string:
fmt.Println(v(100))
case fmt.Stringer:
fmt.Println(v)
default:
println("not support")}}}Copy the code
Interface Common pits
Interface variables default to nil
func test005(a) {
var inter1, inter2 interface{}
fmt.Println(inter1 == nil, inter1 == inter2) // true true
inter1, inter2 = 1.1
fmt.Println(inter1 == inter2) // true
inter1, inter2 = map[string]int{}, map[string]int{}
// panic: runtime error: comparing uncomparable type map[string]int
fmt.Println(inter1 == inter2)
}
Copy the code
Comparison operations
If you implement interface type support, you can do equalityCopy the code
Nested interface
type stringer interface {
string(a)string
}
type tester interface {
stringer
test()
}
// The target type method set must have all methods including embedded interface methods to implement the interface
type person struct {}
func (p person) string(a) string {
return "String formatting"
}
func (p person) test(a) {
fmt.Println("Test method")}func test006(a) {
var p person
var t tester = p
t.test() / / test methods
fmt.Println(t.string()) // String formatting
}
Copy the code
Self test
var i interface{}
i = "hello"
// What does this mean? Judging the original type of Inter, are your answers correct? ☺ ️
s := i.(string)
fmt.Println(s) // hello
Copy the code