接口
Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。
- 初始化
type example interface{
Method1(参数列表) 返回值列表
Method2(参数列表) 返回值列表
…
}
package main
import(
"fmt"
)
// 学生
type Student struct{
name string
age int
sorce int
}
// 老师
type Teacher struct{
name string
age int
}
type ClassAction interface{
Say()
AfterClass()
}
// 学生继承接口(接口的2个函数 需要全部实例化才行)
func (stu Student)Say() {
fmt.Println("my name is",stu.name)
}
func (stu Student)AfterClass() {
fmt.Println("Go Home")
}
// 老师继承接口
func (tea Teacher)Say() {
fmt.Println("my name is",tea.name)
}
func (tea Teacher)AfterClass() {
fmt.Println("Go to Office")
}
func testInterface() {
// 定义学生和老师
var tea Teacher = Teacher{
name:"波多野结衣",
age:22,
}
var stu Student = Student{
name:"程序员",
age:18,
sorce:100,
}
// 定义一个接口
var t ClassAction
// 接口指向学生
t = stu
// 使用接口里面的函数
t.Say()
t.AfterClass()
// 改变接口指向老师并使用
t = tea
t.Say()
t.AfterClass()
// 打印看看是什么东西
fmt.Println(t)
}
func main() {
testInterface()
}
- 输出
my name is 程序员
Go Home
my name is 波多野结衣
Go to Office
{波多野结衣 22}
判断一个变量是否实现了指定接口
var f int
var b interface{}
b = f
// 判断一个变量是否实现了指定接口
v,ok:=b.(ReadFile)
多态
- 接口通过指向不同的结构体,从而实现多态,例如上面的学生和老师,同时实现Action。
类型断言
-
类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,需要类型断言
初始化的两种方式:
var t int
var x interface{}
x = t
y = x.(int) //转成int
var t int
var x interface{}
x = t
y, ok = x.(int) //转成int,带检查
反射
-
reflect.TypeOf,获取变量的类型,返回reflect.Type类型
-
reflect.ValueOf,获取变量的值,返回reflect.Value类型
- 获取变量的值:reflect.ValueOf(x).Int()
-
reflect.Value.Kind,获取变量的类别,返回一个常量
-
reflect.Value.Interface(),转换成interface{}类型
type和kind的区别 大多数情况下会一直,但假如自定义一个结构Student,type是main.Student,而kind是struct
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
fmt.Println("type:", reflect.TypeOf(x))
v := reflect.ValueOf(x)
fmt.Println("value:", v)
fmt.Println("type:", v.Type())
fmt.Println("kind:", v.Kind())
fmt.Println("value:", v.Float())
fmt.Println(v.Interface())
fmt.Printf("value is %5.2e\n", v.Interface())
y := v.Interface().(float64)
fmt.Println(y)
}
- 输出
type: float64
value: 3.4
type: float64
kind: float64
value: 3.4
3.4
value is 3.40e+00
3.4 - 通过反射的来改变变量的值
- reflect.Value.SetXX相关方法,例如:
reflect.Value.SetInt(),设置整数
- reflect.Value.SetXX相关方法,例如:
func main() {
var a float64
fv := reflect.ValueOf(a)
fv.SetFloat(3.3)
fmt.Printf("%v\n", a)
}
上面会修改失败,因为是值类型,如果需要修改,则用fv := reflect.ValueOf(&a)
即是一个指针,则需要加*来修改,但是反射里面没有*的操作,所以要用 fv.Elem()的操作,即fv.Elem().SetFloat(3.3)
用反射操作结构体
- reflect.Value.NumField()获取结构体中字段的个数
- reflect.Value.Method(n).Call来调用结构体中的方法
反射示范代码1
package main
import (
"fmt"
"reflect"
)
type NotknownType struct {
s1 string
s2 string
s3 string
}
func (n NotknownType) String() string {
return n.s1 + "-" + n.s2 + "-" + n.s3
}
var secret interface{} = NotknownType{"Ada", "Go", "Oberon"}
func main() {
value := reflect.ValueOf(secret) // <main.NotknownType Value>
typ := reflect.TypeOf(secret) // main.NotknownType
fmt.Println(typ)
knd := value.Kind() // struct
fmt.Println(knd)
// 遍历结构体的字段
for i := 0; i < value.NumField(); i++ {
fmt.Printf("Field %d: %v\n", i, value.Field(i))
}
results := value.Method(0).Call(nil)
fmt.Println(results) // [Ada - Go - Oberon]
}
- 输出
main.NotknownType
struct
Field 0: Ada
Field 1: Go
Field 2: Oberon
[Ada-Go-Oberon]