长沙制作营销型网站项目实例的疑问?

摘要:长沙营销型网站制作,制作网站项目实例,2023能用的磁力搜索引擎,彩票开奖网站建设目录一、构造函数二、继承与重写三、泛型四、反射1 - 反射的基本概念2 - 反射的基础数据类型3 - 反射APIa - 获取Type类型b - 获取struc
长沙营销型网站制作,制作网站项目实例,2023能用的磁力搜索引擎,彩票开奖网站建设目录一、构造函数二、继承与重写三、泛型四、反射1 - 反射的基本概念2 - 反射的基础数据类型3 - 反射APIa - 获取Type类型b - 获取struct成员变量的信息c - 获取struct成员方法的信息d - 获取函数的信息e - 判断类型是否实现了某接口五、reflect.Valuea - 空value判断b - 获取V… 目录一、构造函数二、继承与重写三、泛型四、反射1 - 反射的基本概念2 - 反射的基础数据类型3 - 反射APIa - 获取Type类型b - 获取struct成员变量的信息c - 获取struct成员方法的信息d - 获取函数的信息e - 判断类型是否实现了某接口五、reflect.Valuea - 空value判断b - 获取Valuec - 指针Value和非指针Value互相转换d - 获取Value对应的原始数据e - 通过Value修改原始数据的值f - 通过Value修改sliceg - 通过Value修改map六、反射创建对象七、反射调用函数和成员方法一、构造函数 定义User结构体 type User struct {Name string //表示未知Age int //-1表示未知Sex byte //1男2女3未知 }func main() {u : User{} //构造一个空的User各字段都取相应数据类型的默认值up : new(User) //构造一个空的User并返回其指针 }自定义构造函数 func NewDefaultUser() *User {return User{Name: ,Age: -1,Sex: 3,} }func NewUser(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未知 }func NewDefaultUser() *User {return User{Name: ,Age: -1,Sex: 3,} }var (sUser *UseruOnce sync.Once )func GetUserInstance() *User {uOnce.Do(func() { //确保即使在并发的情况下下面的3行代码在整个go进程里只会被执行一次if sUser nil {sUser NewDefaultUser()}})return sUser }func main() {//调用GetUserInstance()得到的是同一个User实例su1 : GetUserInstance()su2 : GetUserInstance()//修改su1会影响su2fmt.Println(su1.Age, su2.Age) //-1 -1su1.Age 20fmt.Println(su2.Age) //20 }二、继承与重写 继承的实现通过嵌入匿名结构体变相实现“继承”的功能因为访问匿名成员时可以跳过成员名直接访问它的内部成员 type Plane struct {color string } type Bird struct {Plane }func main() {bird : Bird{}bird.Plane.color redfmt.Println(bird.color) //red }重写的实现 type Plane struct {color string }func (pl Plane) fly() {fmt.Println(plane fly) }type Bird struct {Plane }func (bd Bird) fly() {fmt.Println(bird fly) }func main() {bird : Bird{}bird.Plane.color redfmt.Println(bird.Plane.color) //redfmt.Println(bird.color) //redbird.Plane.fly() //plane flybird.fly() //bird fly }组合严格意义上来说Go语言并不支持继承它只是支持组合 type Plane struct{} type Car struct{}//Bird组合了Plane和Car的功能 type Bird struct {PlaneCar }三、泛型 使用泛型之前在有泛型之前同样的功能需要为不同的参数类型单独实现一个函数 func add4int(a, b int) int {return a b } func add4float32(a, b float32) float32 {return a b } func add4string(a, b string) string {return a b }使用泛型之后 type Addable interface { //类型约束int | string }func add[T Addable](a, b T) T {return a b }func main() {fmt.Println(add(1, 2)) //3fmt.Println(add(hello, world)) //helloworld }四、反射 1 - 反射的基本概念 什么是反射反射就是在运行期间不是编译期间探知对象的类型信息和内存结构、更新变量、调用它们的方法反射的使用场景 函数的参数类型是interface{}需要在运行时对原始类型进行判断针对不同的类型采取不同的处理方式。比如json.Marshal(v interface{})在运行时根据某些条件动态决定调用哪个函数比如根据配置文件执行相应的算子函数 反射的弊端 代码难以阅读难以维护编译期间不能发现类型错误覆盖测试难度很大有些bug需要到线上运行很长时间才能发现可能会造成严重用后反射性能很差通常比正常代码慢一到两个数量级。在对性能要求很高或大量反复调用的代码块里建议不要使用反射 2 - 反射的基础数据类型 反射的基础数据类型 reflect.Type用于获取类型相关的信息 type Type interface {Method(int) Method //第i个方法MethodByName(string) (Method, bool) //根据名称获取方法NumMethod() int //方法的个数Name() string //获取结构体名称PkgPath() string //包路径Size() uintptr //占用内存的大小String() string //获取字符串表述Kind() Kind //数据类型Implements(u Type) bool //判断是否实现了某接口AssignableTo(u Type) bool //能否赋给另外一种类型ConvertibleTo(u Type) bool //能否转换为另外一种类型Elem() Type //解析指针Field(i int) StructField //第i个成员FieldByIndex(index []int) StructField //根据index路径获取嵌套成员FieldByName(name string) (StructField, bool) //根据名称获取成员FieldByNameFunc(match func(string) bool) (StructField, bool) //根据匹配函数匹配需要的字段Len() int //容器的长度NumIn() int //输出参数的个数NumOut() int //返回参数的个数 }reflect.Value用于修改原始数据类型里的值 type Value struct {typ *rtype // 代表的数据类型ptr unsafe.Pointer // 指向原始数据的指针 }3 - 反射API a - 获取Type类型 type User struct {age int64Gender bool json:sexuint8 }type Student struct {User }func get_type() {typeI : reflect.TypeOf(2)typeS : reflect.TypeOf(abc)fmt.Println(typeI) //int - reflect.Typefmt.Printf(%s %T\n, typeI, typeI) //int *reflect.rtypefmt.Println(typeI.String()) //int - stringfmt.Println(typeS) //string - reflect.Typefmt.Println(typeI.Kind() reflect.Int) //true - reflect.Kindfmt.Println(typeS.Kind() reflect.String) //true - reflect.Kindfmt.Println(-------------------)user : User{}typeUser : reflect.TypeOf(user)fmt.Println(typeUser) //*main.Userfmt.Println(typeUser.Elem()) //main.Userfmt.Println(typeUser.Elem().Name()) //Userfmt.Println(typeUser.Kind() reflect.Ptr) //true - ptrfmt.Println(typeUser.Elem().Kind() reflect.Struct) //true - structfmt.Println(-------------------)user2 : User{}typeUser2 : reflect.TypeOf(user2)fmt.Println(typeUser2.Size())fmt.Println(typeUser2.PkgPath()) }b - 获取struct成员变量的信息 type User struct {age int64Gender bool json:sexuint8 }type Student struct {Name stringuser User }func get_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:sexuint8 }type Student struct {Name stringuser User }func (*Student) Examine1(a int, b float32) (byte, string) {return byte(3), abc }func (Student) Examine2(a int, b float32) (byte, string) {return byte(3), abc }func get_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())} }func foreachMethod(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 - 获取函数的信息 func Add(a, b int) int {return a b }func main() {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:sexuint8 }type Student struct {Name stringuser User }func (*Student) Examine1(a int, b float32) (byte, string) {return byte(3), abc }func convert() {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 }func impl() {//接口类型获取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判断 func is_empty() {var i interface{}vl : reflect.ValueOf(i)fmt.Println(vl) //invalid reflect.Valuefmt.Println(vl.IsValid()) //falsevar user *User //nilvl reflect.ValueOf(user)fmt.Println(vl) //nilif 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}}b - 获取Value type User struct {age int64Gender bool json:sexuint8 }func main() {iValue : reflect.ValueOf(1)sValue : reflect.ValueOf(hello)fmt.Println(iValue) //1fmt.Println(sValue) //hellofmt.Println(iValue.Kind() reflect.Int) //true - intfmt.Println(sValue.Kind() reflect.String) //true - string// Value转TypeiType : iValue.Type()sType : sValue.Type()fmt.Println(iType.Kind() reflect.Int) //true - intfmt.Println(sType.Kind() reflect.String) //true - string }c - 指针Value和非指针Value互相转换 type User struct {age int64Gender bool json:sexuint8 }func main() {userPtrValue : reflect.ValueOf(User{3, true, 6})userValue : userPtrValue.Elem() //Elem() 指针Value转为非指针Valuefmt.Println(userValue.Kind(), userPtrValue.Kind()) //struct ptruserPtrValue2 : userValue.Addr() //Addr() 非指针Value转为指针Valuefmt.Println(userValue.Kind(), userPtrValue2.Kind()) //struct ptr}d - 获取Value对应的原始数据 - 通过Interface()函数把Value转为interface{}再从interface{}强制类型转换转为原始数据类型 - 在Value上直接调用Int()、String()等type User struct {age int64Gender bool json:sexuint8 }func main() {iValue : reflect.ValueOf(1)sValue : reflect.ValueOf(hello)fmt.Printf(origin value iValue is %d %d\n, iValue.Interface().(int), iValue.Int()) //origin value iValue is 1 1fmt.Printf(origin value sValue is %s %s\n, sValue.Interface().(string), sValue.String()) //origin value sValue is hello hellouserValue : reflect.ValueOf(User{3, true, 6})user : userValue.Interface().(User)fmt.Printf(age%d gender%t uint%d\n, user.age, user.Gender, user.uint8) //age3 gendertrue uint6userPtrValue : reflect.ValueOf(User{2, false, 5})user2 : userPtrValue.Interface().(*User)fmt.Printf(age%d gender%t uint%d\n, user2.age, user2.Gender, user2.uint8) //age2 genderfalse uint5}e - 通过Value修改原始数据的值 通过反射修改原始数据的值 要想修改原始数据的值给ValueOf传的必须是指针而指针Value不能调用Set和FieldByName方法所以得先通过Elem()转为非指针Value未导出成员的值不能通过反射进行修改所以在修改前需要先进行CanSet判断 func main() {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:sexuint8 }func main() {users : make([]*User, 1, 5) //len1cap5users[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:sexuint8 }func main() {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:sexuint8 }func main() {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:sexuint8 }func main() {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:sexName string }func main() {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 }七、反射调用函数和成员方法 反射调用函数 func Add(a, b int) int {return a b }func main() {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) //sum6}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) //sum7} }反射调用成员方法 type User struct {Id intage int64Gender bool json:sexName string }func (u *User) GetAge() int64 {return u.age }func (u User) Think() {fmt.Printf(%s is in Think\n, u.Name) }func main() {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) //GetAge18//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 }