interface
In the Golang
world, there is interface
something called magic.
First, the data type interface {}
If you don't know what data type a variable is before, whether it is an integer or a string, but you still want to use it.
Golang
interface{}
A data type called "name" is generated , indicating that it does not know what type it is. for example:
package main
import (
"fmt"
"reflect"
)
func print(i interface{}) {
fmt.Println(i)
}
func main() {
// 声明一个未知类型的 a,表明不知道是什么类型
var a interface{}
a = 2
fmt.Printf("%T,%v\n", a, a)
// 传入函数
print(a)
print(3)
print("i love you")
// 使用断言,判断是否是 int 数据类型
v, ok := a.(int)
if ok {
fmt.Printf("a is int type,value is %d\n", v)
}
// 使用断言,判断变量类型
switch a.(type) {
case int:
fmt.Println("a is type int")
case string:
fmt.Println("a is type string")
default:
fmt.Println("a not type found type")
}
// 使用反射找出变量类型
t := reflect.TypeOf(a)
fmt.Printf("a is type: %s", t.Name())
}
Output:
int,2
2
3
i love you
a is int type,value is 2
a is type int
a is type: int
1.1. Basic use
We use interface{}
to declare a variable of unknown type a
:
// 声明一个未知类型的 a,表明不知道是什么类型
var a interface{}
a = 2
fmt.Printf("%T,%v\n", a, a)
Then assign an integer to the variable: a=2
At this time, a
it is still an unknown type. Use the placeholder %T
to print the true type of the variable, and the placeholder to %v
print the value. At this time fmt.Printf
, the type will be judged internally.
We can also set the parameters of the function interface
as the same as the definition of the variable:
func print(i interface{}) {
fmt.Println(i)
}
when using it:
// 传入函数
print(a)
print(3)
print("i love you")
print
The parameters we pass into the function can be of any type, such as integers 3
or strings i love you
. After entering the function, the variable in the function i
loses its type and is an unknown type. This feature makes it unnecessary for us to write multiple functions if we want to process different types of data.
Of course, the fields in the structure can also be interface{}
:
type H struct {
A interface{}
B interface{}
}
1.2. Determine the specific type
We defined it interface{}
, but in actual use, we have a need to judge the type. There are two ways to judge.
Use assertions:
// 使用断言,判断是否是 int 数据类型
v, ok := a.(int)
if ok {
fmt.Printf("a is int type,value is %d\n", v)
}
Used directly after the variable .(int)
, two return values v, ok
will be returned. ok
If it true
indicates that it is indeed an integer type, this integer will be assigned v
, and then we can v
play happily. Otherwise, ok
as false
, v
to a null value, which is the default value of 0.
If we use it this way every time, it will be uncomfortable, because a interface{}
type of variable, the data type may be .(int)
, may be .(string)
, can be used switch
to simplify:
// 使用断言,判断变量类型
switch a.(type) {
case int:
fmt.Println("a is type int")
case string:
fmt.Println("a is type string")
default:
fmt.Println("a not type found type")
}
In swicth
, the assertion is no longer used .(具体类型)
, but a.(type)
.
Finally, there is a way to use the reflection package reflect
to determine the data type:
// 使用反射找出变量类型
t := reflect.TypeOf(a)
fmt.Printf("a is type: %s", t.Name())
This package will directly use non-secure pointers to get the real data type:
func TypeOf(i interface{}) Type {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
}
For general daily development, reflection packages are rarely used.
2. Interface structure
We are all functional programming or structural method programming now. Isn't there the object-oriented, object inheritance characteristic of other languages? Yes, the Golang
language is called interface-oriented programming.
package main
import (
"fmt"
"reflect"
)
// 定义一个接口,有一个方法
type A interface {
Println()
}
// 定义一个接口,有两个方法
type B interface {
Println()
Printf() int
}
// 定义一个结构体
type A1Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a1 *A1Instance) Println() {
fmt.Println("a1:", a1.Data)
}
// 定义一个结构体
type A2Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a2 *A2Instance) Println() {
fmt.Println("a2:", a2.Data)
}
// 结构体实现了Printf()方法,现在它是一个 B 接口,它既是 A 又是 B 接口
func (a2 *A2Instance) Printf() int {
fmt.Println("a2:", a2.Data)
return 0
}
func main() {
// 定义一个A接口类型的变量
var a A
// 将具体的结构体赋予该变量
a = &A1Instance{Data: "i love you"}
// 调用接口的方法
a.Println()
// 断言类型
if v, ok := a.(*A1Instance); ok {
fmt.Println(v)
} else {
fmt.Println("not a A1")
}
fmt.Println(reflect.TypeOf(a).String())
// 将具体的结构体赋予该变量
a = &A2Instance{Data: "i love you"}
// 调用接口的方法
a.Println()
// 断言类型
if v, ok := a.(*A1Instance); ok {
fmt.Println(v)
} else {
fmt.Println("not a A1")
}
fmt.Println(reflect.TypeOf(a).String())
// 定义一个B接口类型的变量
var b B
//b = &A1Instance{Data: "i love you"} // 不是 B 类型
b = &A2Instance{Data: "i love you"}
fmt.Println(b.Printf())
}
Output:
a1: i love you
&{i love you}
*main.A1Instance
a2: i love you
not a A1
*main.A2Instance
a2: i love you
0
We can define an interface type, use type 接口名 interface
, this time is no longer interface{}
:
// 定义一个接口,有一个方法
type A interface {
Println()
}
// 定义一个接口,有两个方法
type B interface {
Println()
Printf() int
}
It can be seen that the interface A
and B
is an abstract structure. Each interface has some methods in it. As long as the structure struct
implements these methods, then these structures are the type of this interface. Such as:
// 定义一个结构体
type A1Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a1 *A1Instance) Println() {
fmt.Println("a1:", a1.Data)
}
// 定义一个结构体
type A2Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a2 *A2Instance) Println() {
fmt.Println("a2:", a2.Data)
}
// 结构体实现了Printf()方法,现在它是一个 B 接口,它既是 A 又是 B 接口
func (a2 *A2Instance) Printf() int {
fmt.Println("a2:", a2.Data)
return 0
}
We require that the structure must implement certain methods, so we can define a variable of the interface type, and then assign the structure to it:
// 定义一个A接口类型的变量
var a A
// 将具体的结构体赋予该变量
a = &A1Instance{Data: "i love you"}
// 调用接口的方法
a.Println()
If the structure does not implement this method, the compilation will fail and the binary cannot be compiled.
Of course, you can also use assertions and reflection to determine which actual structure the interface type belongs to struct
.
// 断言类型
if v, ok := a.(*A1Instance); ok {
fmt.Println(v)
} else {
fmt.Println("not a A1")
}
fmt.Println(reflect.TypeOf(a).String())
Golang
It is very smart to determine whether the structure implements the interface method. If it is implemented, then the structure is the interface type. We flexibly use the characteristics of the interface structure, and use the combined form to develop more flexible programs.
Series article entry
I am the star Chen, Welcome I have personally written data structures and algorithms (Golang achieve) , starting in the article to read more friendly GitBook .
- Data structure and algorithm (Golang implementation) (1) A simple introduction to Golang-Preface
- Data structures and algorithms (Golang implementation) (2) A simple introduction to Golang-packages, variables and functions
- Data structure and algorithm (Golang implementation) (3) A simple introduction to Golang-flow control statement
- Data structures and algorithms (Golang implementation) (4) A simple introduction to Golang-structures and methods
- Data structure and algorithm (Golang implementation) (5) A simple introduction to Golang-interface
- Data structure and algorithm (Golang implementation) (6) A simple introduction to Golang-concurrency, coroutines and channels
- Data structure and algorithm (Golang implementation) (7) A simple introduction to Golang-standard library
- Data Structure and Algorithm (Golang Implementation) (8.1) Basic Knowledge-Preface
- Data Structure and Algorithm (Golang Implementation) (8.2) Basic Knowledge-Divide and Conquer and Recursion
- Data structure and algorithm (Golang implementation) (9) Basic knowledge-algorithm complexity and progressive symbol
- Data structure and algorithm (Golang implementation) (10) Basic knowledge-the main method of algorithm complexity
- Data Structures and Algorithms (Golang Implementation) (11) Common Data Structures-Preface
- Data structures and algorithms (Golang implementation) (12) Common data structures-linked lists
- Data structures and algorithms (Golang implementation) (13) Common data structures-variable-length arrays
- Data structures and algorithms (Golang implementation) (14) Common data structures-stack and queue
- Data Structures and Algorithms (Golang Implementation) (15) Common Data Structures-List
- Data Structures and Algorithms (Golang Implementation) (16) Common Data Structures-Dictionary
- Data structures and algorithms (Golang implementation) (17) Common data structures-trees
- Data Structure and Algorithm (Golang Implementation) (18) Sorting Algorithm-Preface
- Data structure and algorithm (Golang implementation) (19) Sorting algorithm-bubble sorting
- Data structure and algorithm (Golang implementation) (20) Sorting algorithm-selection sorting
- Data structure and algorithm (Golang implementation) (21) Sorting algorithm-insertion sort
- Data structure and algorithm (Golang implementation) (22) Sorting algorithm-Hill sorting
- Data structure and algorithm (Golang implementation) (23) Sorting algorithm-merge sorting
- Data structure and algorithm (Golang implementation) (24) Sorting algorithm-priority queue and heap sorting
- Data structure and algorithm (Golang implementation) (25) Sorting algorithm-quick sorting
- Data Structure and Algorithm (Golang Implementation) (26) Lookup Algorithm-Hash Table
- Data structure and algorithm (Golang implementation) (27) Search algorithm-binary search tree
- Data structure and algorithm (Golang implementation) (28) Search algorithm-AVL tree
- Data structure and algorithm (Golang implementation) (29) Finding algorithm-2-3 tree and left-leaning red-black tree
- Data structure and algorithm (implemented by Golang) (30) Finding algorithm-2-3-4 tree and ordinary red-black tree