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,}}
单例模式:确保在并发的情况下,整个进程里只会创建struct的一个实例
type User struct{
Name string//""表示未知
Age int//-1表示未知
Sex byte//1男,2女,3未知}funcNewDefaultUser()*User {return&User{
Name:"",
Age:-1,
Sex:3,}}var(
sUser *User
uOnce sync.Once
)funcGetUserInstance()*User {
uOnce.Do(func(){//确保即使在并发的情况下,下面的3行代码在整个go进程里只会被执行一次if sUser ==nil{
sUser =NewDefaultUser()}})return sUser
}funcmain(){//调用GetUserInstance()得到的是同一个User实例
su1 :=GetUserInstance()
su2 :=GetUserInstance()//修改su1会影响su2
fmt.Println(su1.Age, su2.Age)//-1 -1
su1.Age =20
fmt.Println(su2.Age)//20}
type Plane struct{}type Car struct{}//Bird组合了Plane和Car的功能type Bird struct{
Plane
Car
}
三、泛型
使用泛型之前:在有泛型之前,同样的功能需要为不同的参数类型单独实现一个函数
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))//3
fmt.Println(add("hello","world"))//helloworld}
type User struct{
age int64
Gender bool`json:"sex"`uint8}type Student struct{
Name string
user User
}funcget_field(){
typeUser := reflect.TypeOf(User{})//需要用struct的Type,不能用指针的Type
fieldNum := 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"))//获取成员变量后面``里面定义的tag
fmt.Println("------------------")}//获取指定成员变量的信息if field, ok := typeUser.FieldByName("Gender"); ok {
fmt.Println(field.Name)//Gender
fmt.Println(field.Offset)//8
fmt.Println(field.Anonymous)//false
fmt.Println(field.Type)//bool
fmt.Println(field.IsExported())//true
fmt.Println(field.Tag.Get("json"))//sex
fmt.Println("------------------")}else{
fmt.Println("结构体中没有名为Gender的成员变量")}//根据index获取成员变量信息
field := typeUser.FieldByIndex([]int{0})//使用切片可以兼容嵌套
fmt.Println(field.Name)//age
fmt.Println(field.Offset)//0
fmt.Println(field.Anonymous)//false
fmt.Println(field.Type)//int64
fmt.Println(field.IsExported())//false
fmt.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 int64
Gender bool`json:"sex"`uint8}type Student struct{
Name string
user 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)//true
argInNum := 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 int64
Gender bool`json:"sex"`uint8}type Student struct{
Name string
user 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))//false
fmt.Println(studentType.AssignableTo(userType))//false
fmt.Println(userType.ConvertibleTo(studentType))//false
fmt.Println(studentType.ConvertibleTo(userType))//false
userType2 := reflect.TypeOf(User{})
fmt.Println(userType.AssignableTo(userType2))//true
fmt.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))//false
fmt.Println(studentType.Implements(peopleType))//false
fmt.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 //nil
vl = reflect.ValueOf(user)
fmt.Println(vl)//<nil>if vl.IsValid(){
fmt.Println(vl.IsNil())//true}var u User
vl = reflect.ValueOf(u)
fmt.Println(vl)//{0 false 0}if vl.IsValid(){
fmt.Println(vl.IsZero())//true}}
b - 获取Value
type User struct{
age int64
Gender bool`json:"sex"`uint8}funcmain(){
iValue := reflect.ValueOf(1)
sValue := reflect.ValueOf("hello")
fmt.Println(iValue)//1
fmt.Println(sValue)//hello
fmt.Println(iValue.Kind()== reflect.Int)//true -> int
fmt.Println(sValue.Kind()== reflect.String)//true -> string// Value转Type
iType := iValue.Type()
sType := sValue.Type()
fmt.Println(iType.Kind()== reflect.Int)//true -> int
fmt.Println(sType.Kind()== reflect.String)//true -> string}
c - 指针Value和非指针Value互相转换
type User struct{
age int64
Gender bool`json:"sex"`uint8}funcmain(){
userPtrValue := reflect.ValueOf(&User{3,true,6})
userValue := userPtrValue.Elem()//Elem() 指针Value转为非指针Value
fmt.Println(userValue.Kind(), userPtrValue.Kind())//struct ptr
userPtrValue2 := userValue.Addr()//Addr() 非指针Value转为指针Value
fmt.Println(userValue.Kind(), userPtrValue2.Kind())//struct ptr}
funcmain(){var i int=18
iValue := reflect.ValueOf(&i)
iValue.Elem().SetInt(28)
fmt.Println(i)//28
user := User{10,true,3}
userValue := reflect.ValueOf(&user)
fieldGenderValue := userValue.Elem().FieldByName("Gender")
fieldGenderValue.SetBool(false)
fmt.Println(user.Gender)//false
fieldAgeValue := 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 int64
Gender bool`json:"sex"`uint8}funcmain(){
users :=make([]*User,1,5)//len=1,cap=5
users[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的len
sliceValue.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 5
sliceValue.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 int64
Gender bool`json:"sex"`uint8}funcmain(){
u1 :=&User{1,true,2}
u2 :=&User{3,true,5}
userMap :=make(map[int]*User,5)
userMap[0]= u1
mapValue := 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 int64
Gender bool`json:"sex"`uint8}funcmain(){
userType := reflect.TypeOf(User{1,false,2})
value := reflect.New(userType)//根据reflect.Type创建一个对象,得到该对象的指针,再根据指针提到reflect.Value
value.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 int64
Gender 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)//1
fmt.Printf("2st user Gender %t\n", users[1].Gender)//true}
通过反射创建map
type User struct{
Id int
age int64
Gender bool`json:"sex"`
Name string}funcmain(){var userMap map[int]*User
mapType := 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取出对应的map
userMap = 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 int
age int64
Gender 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 Think
valueUser2 := reflect.ValueOf(user)
thinkMethod = valueUser2.MethodByName("Think")
thinkMethod.Call([]reflect.Value{})//jack is in Think}
Activity Results APIActivity Result API提供了用于注册结果、启动结果以及在系统分派结果后对其进行处理的组件。—Google官方文档https://developer.android.google.cn/training/basics/intents/result?hlzh-cn一句话解释:官方Jetpack组件用于代替startActivity…