type User struct{Name string//""表示未知Age int//-1表示未知Sex byte//1男,2女,3未知}funcmain(){u := User{}//构造一个空的User,各字段都取相应数据类型的默认值up :=new(User)//构造一个空的User,并返回其指针}
自定义构造函数
funcNewDefaultUser()*User {return&User{Name:"",Age:-1,Sex:3,}}funcNewUser(name string, age int, sex byte)*User {return&User{Name: name,Age: age,Sex: sex,}}
type Plane struct{}type Car struct{}//Bird组合了Plane和Car的功能type Bird struct{PlaneCar
}
三、泛型
使用泛型之前:在有泛型之前,同样的功能需要为不同的参数类型单独实现一个函数
funcadd4int(a, b int)int{return a + b
}funcadd4float32(a, b float32)float32{return a + b
}funcadd4string(a, b string)string{return a + b
}
使用泛型之后:
type Addable interface{//类型约束int|string}func add[T Addable](a, b T) T {return a + b
}funcmain(){fmt.Println(add(1,2))//3fmt.Println(add("hello","world"))//helloworld}
type User struct{age int64Gender bool`json:"sex"`uint8}type Student struct{Name stringuser User
}funcget_field(){typeUser := reflect.TypeOf(User{})//需要用struct的Type,不能用指针的TypefieldNum := typeUser.NumField()//成员变量的个数for i :=0; i < fieldNum; i++{field := typeUser.Field(i)fmt.Println(field.Name)//变量名称fmt.Println(field.Offset)//相对于结构体首地址的内存偏移量,string类型会占据16个字节fmt.Println(field.Anonymous)//是否为匿名成员fmt.Println(field.Type)//数据类型,reflect.Type类型fmt.Println(field.IsExported())//包外是否可见(即是否以大写字母开头)fmt.Println(field.Tag.Get("json"))//获取成员变量后面``里面定义的tagfmt.Println("------------------")}//获取指定成员变量的信息if field, ok := typeUser.FieldByName("Gender"); ok {fmt.Println(field.Name)//Genderfmt.Println(field.Offset)//8fmt.Println(field.Anonymous)//falsefmt.Println(field.Type)//boolfmt.Println(field.IsExported())//truefmt.Println(field.Tag.Get("json"))//sexfmt.Println("------------------")}else{fmt.Println("结构体中没有名为Gender的成员变量")}//根据index获取成员变量信息field := typeUser.FieldByIndex([]int{0})//使用切片可以兼容嵌套fmt.Println(field.Name)//agefmt.Println(field.Offset)//0fmt.Println(field.Anonymous)//falsefmt.Println(field.Type)//int64fmt.Println(field.IsExported())//falsefmt.Println(field.Tag.Get("json"))fmt.Println("------------------")//使用切片可以兼容嵌套typeStudent := reflect.TypeOf(Student{})fieldUser := typeStudent.FieldByIndex([]int{1,0})fmt.Println(fieldUser.Name)//age}
c - 获取struct成员方法的信息
type User struct{age int64Gender bool`json:"sex"`uint8}type Student struct{Name stringuser User
}func(*Student)Examine1(a int, b float32)(byte,string){returnbyte(3),"abc"}func(Student)Examine2(a int, b float32)(byte,string){returnbyte(3),"abc"}funcget_method_info(){typeStudent := reflect.TypeOf(Student{})foreachMethod(typeStudent)//Examine2 -> 不会取到指针的方法ptypeStudent := reflect.TypeOf(&Student{})foreachMethod(ptypeStudent)//Examine1 //Examine2 -> Examine2也属于指针的方法//根据名称获取if method, ok := typeStudent.MethodByName("Examine2"); ok {fmt.Println(method.Name)fmt.Println(method.Type)fmt.Println(method.IsExported())fmt.Println(method.Type.NumIn())fmt.Println(method.Type.NumOut())}}funcforeachMethod(rt reflect.Type){methodNum := rt.NumMethod()for i :=0; i < methodNum; i++{method := rt.Method(i)fmt.Println(method.Name)fmt.Println(method.Type)fmt.Println(method.IsExported())fmt.Println(method.Type.NumIn())fmt.Println(method.Type.NumOut())fmt.Println("-------------")}}
d - 获取函数的信息
funcAdd(a, b int)int{return a + b
}funcmain(){addType := reflect.TypeOf(Add)fmt.Printf("is function type %t\n", addType.Kind()== reflect.Func)//trueargInNum := addType.NumIn()//输入参数的个数argOutNum := addType.NumOut()//输出参数的个数for i :=0; i < argInNum; i++{argTyp := addType.In(i)fmt.Printf("第%d个输入参数的类型%s\n", i, argTyp)}for i :=0; i < argOutNum; i++{argTyp := addType.Out(i)fmt.Printf("第%d个输出参数的类型%s\n", i, argTyp)}}
e - 判断类型是否实现了某接口
type People interface{Examine1(a int, b float32)(byte,string)}type User struct{age int64Gender bool`json:"sex"`uint8}type Student struct{Name stringuser User
}func(*Student)Examine1(a int, b float32)(byte,string){returnbyte(3),"abc"}funcconvert(){userType := reflect.TypeOf(User{})studentType := reflect.TypeOf(Student{})fmt.Println(userType.AssignableTo(studentType))//falsefmt.Println(studentType.AssignableTo(userType))//falsefmt.Println(userType.ConvertibleTo(studentType))//falsefmt.Println(studentType.ConvertibleTo(userType))//falseuserType2 := reflect.TypeOf(User{})fmt.Println(userType.AssignableTo(userType2))//truefmt.Println(userType2.ConvertibleTo(userType))//true}funcimpl(){//接口类型获取type的实现方法,nil可以理解为People指针的实例peopleType := reflect.TypeOf((*People)(nil)).Elem()userType := reflect.TypeOf(User{})studentType := reflect.TypeOf(Student{})pstudentType := reflect.TypeOf(&Student{})fmt.Println(userType.Implements(peopleType))//falsefmt.Println(studentType.Implements(peopleType))//falsefmt.Println(pstudentType.Implements(peopleType))//true Student的指针才实现了People的接口}
五、reflect.Value
a - 空value判断
funcis_empty(){var i interface{}vl := reflect.ValueOf(i)fmt.Println(vl)//<invalid reflect.Value>fmt.Println(vl.IsValid())//falsevar user *User //nilvl = reflect.ValueOf(user)fmt.Println(vl)//<nil>if vl.IsValid(){fmt.Println(vl.IsNil())//true}var u Uservl = reflect.ValueOf(u)fmt.Println(vl)//{0 false 0}if vl.IsValid(){fmt.Println(vl.IsZero())//true}}
funcmain(){var i int=18iValue := reflect.ValueOf(&i)iValue.Elem().SetInt(28)fmt.Println(i)//28user := User{10,true,3}userValue := reflect.ValueOf(&user)fieldGenderValue := userValue.Elem().FieldByName("Gender")fieldGenderValue.SetBool(false)fmt.Println(user.Gender)//falsefieldAgeValue := userValue.Elem().FieldByName("age")//age是未导出的,所以我们需要先使用CanSet判断是否导出再进行设置值//fieldAgeValue.SetInt(8) //reflect: reflect.Value.SetInt using value obtained using unexportedif fieldAgeValue.CanSet(){fieldAgeValue.SetInt(8)}else{fmt.Println("age成员未导出,不可以set")//以小写字母开头的成员相当于是私有成员}}
f - 通过Value修改slice
type User struct{age int64Gender bool`json:"sex"`uint8}funcmain(){users :=make([]*User,1,5)//len=1,cap=5users[0]=&User{18,true,8}sliceValue := reflect.ValueOf(&users)//准备通过Value修改users,所以传users的地址if sliceValue.Elem().Len()>0{//取得slice的长度sliceValue.Elem().Index(0).Elem().FieldByName("Gender").SetBool(false)fmt.Printf("1st user Gender change to %t\n", users[0].Gender)//1st user Gender change to false}//修改slice的lensliceValue.Elem().SetLen(2)//调用reflect.Value的Set()函数修改其底层指向的原始数据sliceValue.Elem().Index(1).Set(reflect.ValueOf(&User{10,false,3}))fmt.Printf("2nd user age %d\n", users[1].age)//2nd user age 10//修改slice的cap,新的cap必须位于原始的len到cap之间,即只能把cap改小fmt.Printf("slice old cap is %d\n",cap(users))//slice old cap is 5sliceValue.Elem().SetCap(3)fmt.Printf("slice new cap is %d\n",cap(users))//slice new cap is 3}
g - 通过Value修改map
反射修改map
Value.SetMapIndex()函数:往map里添加一个key-value对
Value.MapIndex()函数: 根据Key取出对应的map
type User struct{age int64Gender bool`json:"sex"`uint8}funcmain(){u1 :=&User{1,true,2}u2 :=&User{3,true,5}userMap :=make(map[int]*User,5)userMap[0]= u1mapValue := reflect.ValueOf(&userMap)//传userMap的地址mapValue.Elem().SetMapIndex(reflect.ValueOf(1), reflect.ValueOf(u2))for k, user :=range userMap {fmt.Printf("key = %d, user age = %d\n", k, user.age)}mapValue.Elem().MapIndex(reflect.ValueOf(0)).Elem().FieldByName("Gender").SetBool(false)fmt.Println("u1 Gender = ", u1.Gender)//u1 age = false}
六、反射创建对象
通过反射创建struct
type User struct{age int64Gender bool`json:"sex"`uint8}funcmain(){userType := reflect.TypeOf(User{1,false,2})value := reflect.New(userType)//根据reflect.Type创建一个对象,得到该对象的指针,再根据指针提到reflect.Valuevalue.Elem().FieldByName("Gender").SetBool(true)if userOrign, ok := value.Interface().(*User); ok {//把反射类型转成go原始数据类型Call([]reflect.Value{})fmt.Println(userOrign.Gender)//true}}
通过反射创建slice
type User struct{age int64Gender bool`json:"sex"`uint8}funcmain(){sliceType := reflect.TypeOf([]User{})sliceValue := reflect.MakeSlice(sliceType,2,3)sliceValue.Index(0).Set(reflect.ValueOf(User{1,false,2}))sliceValue.Index(1).Set(reflect.ValueOf(User{3,true,5}))users := sliceValue.Interface().([]User)fmt.Printf("1st user age %d\n", users[0].age)//1fmt.Printf("2st user Gender %t\n", users[1].Gender)//true}
通过反射创建map
type User struct{Id intage int64Gender bool`json:"sex"`Name string}funcmain(){var userMap map[int]*UsermapType := reflect.TypeOf(userMap)// mapValue:=reflect.MakeMap(mapType)mapValue := reflect.MakeMapWithSize(mapType,10)user :=&User{1,1,false,"Jack"}key := reflect.ValueOf(user.Id)mapValue.SetMapIndex(key, reflect.ValueOf(user))//SetMapIndex 往map里添加一个key-value对mapValue.MapIndex(key).Elem().FieldByName("Name").SetString("Tom")//MapIndex 根据Key取出对应的mapuserMap = mapValue.Interface().(map[int]*User)fmt.Printf("user name %s %s\n", userMap[1].Name, user.Name)//user name Tom Tom}
七、反射调用函数和成员方法
反射调用函数
funcAdd(a, b int)int{return a + b
}funcmain(){valueFunc := reflect.ValueOf(Add)//函数也是一种数据类型typeFunc := reflect.TypeOf(Add)argNum := typeFunc.NumIn()//函数输入参数的个数args :=make([]reflect.Value, argNum)//准备函数的输入参数for i :=0; i < argNum; i++{if typeFunc.In(i).Kind()== reflect.Int {args[i]= reflect.ValueOf(3)//给每一个参数都赋3}}sumValue := valueFunc.Call(args)//返回[]reflect.Value,因为go语言的函数返回可能是一个列表if typeFunc.Out(0).Kind()== reflect.Int {sum := sumValue[0].Interface().(int)//从Value转为原始数据类型fmt.Printf("sum=%d\n", sum)//sum=6}sumValue = valueFunc.Call([]reflect.Value{reflect.ValueOf(3), reflect.ValueOf(4)})if typeFunc.Out(0).Kind()== reflect.Int {sum := sumValue[0].Interface().(int)//从Value转为原始数据类型fmt.Printf("sum=%d\n", sum)//sum=7}}
反射调用成员方法
type User struct{Id intage int64Gender bool`json:"sex"`Name string}func(u *User)GetAge()int64{return u.age
}func(u User)Think(){fmt.Printf("%s is in Think\n", u.Name)}funcmain(){user :=&User{7,18,false,"jack"}valueUser := reflect.ValueOf(user)//必须传指针,因为GetAge()在定义的时候它是指针的方法bmiMethod := valueUser.MethodByName("GetAge")//MethodByName()通过Name返回类的成员变量resultValue := bmiMethod.Call([]reflect.Value{})//无参数时传一个空的切片result := resultValue[0].Interface().(int64)fmt.Printf("GetAge=%d\n", result)//GetAge=18//Think()在定义的时候用的不是指针,valueUser可以用指针也可以不用指针thinkMethod := valueUser.MethodByName("Think")thinkMethod.Call([]reflect.Value{})//jack is in ThinkvalueUser2 := reflect.ValueOf(user)thinkMethod = valueUser2.MethodByName("Think")thinkMethod.Call([]reflect.Value{})//jack is in Think}