当前位置:网站首页>5. golang generics and reflection

5. golang generics and reflection

2022-06-10 18:46:00 He Yi Qingfeng

1. Generic

1.1 Definition

  • Generic Life cycle Only at compile time , Designed to generate code for programmers , Reduce the duplication of code
  • When comparing the size of two numbers , When there are no generics , Only the incoming type is different , We're going to write an identical function , If you have generics, you can reduce this kind of code

1.2 Example

// SumInts  take map The value of the combined , If the data types to be added are different , Then you need to define two 
func SumInts(m map[string]int64) int64 {
    
    var s int64
    for _, v := range m {
    
        s += v
    }
    return s
}

func SumFloats(m map[string]float64) float64 {
    
    var s float64
    for _, v := range m {
    
        s += v
    }
    return s
}

If you use generics, you only need to define generic methods ( If you report a compilation error , yes idea Version is too low , Upgrade the version , But there's no problem running )

 Insert picture description here

func main() {
    
	ints := make(map[string]int64, 5)
	ints["name"] = 5
	ints["value"] = 6

	floats := make(map[string]float64, 5)
	floats["name"] = 5.6
	floats["value"] = 6.5
	fmt.Printf("Gnneric sums: %v and %v\n", 
		SumIntsOrFloats[string, int64](ints), 
		SumIntsOrFloats[string, float64](floats))
    // You can delete the type 
    fmt.Printf("Gnneric sums: %v and %v\n", 
		SumIntsOrFloats(ints), 
		SumIntsOrFloats(floats))
}
//SumIntsOrFloats  Define generic methods 
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
    
	var s V
	for _, v := range m {
    
        s += v
    }
	return s
}

1.3 Custom generic types

  • any: representative go All the built-in types , Equivalent to interface {}
  • comparable: representative go Built in comparable types :int、uint、float、bool、struct、 Pointer and other comparable types
  • ~ Symbol : A derived type used to represent a modified type
// Type constraint 
type Number interface {
    
	int64 | float64
}
// The current class can be used for type constraints 
func SumIntsNumbers[K comparable, V Number](m map[K]V) V {
    
	var s V
	for _, v := range m {
    
        s += v
	}
	return s
}

1.4 Generics and switch Use a combination of

func main() {
    
	fmt.Println(Get(12))
}
//go You cannot directly associate generics with switch Use 
func Get[T any](t T) T {
    
	var ti interface{
    } = &t
	switch v := ti.(type) {
    
	case *int:
		*v = 18
	}
	return t
}

1.5 Generic combat

1.5.1 Use generic definitions Json analytic method

// Get the type and value through reflection according to the incoming type 
func typeFunc[E any](v any, e *E) *E {
    
	valueOf := reflect.ValueOf(v)
	typeOf := reflect.TypeOf(v)
	if k := typeOf.Kind(); k == reflect.Slice {
    
		json.Unmarshal(valueOf.Bytes(), e)
	}
	return e
}

func main() {
    
    user1 := &User{
    }
	user1 = typeFunc[User](marshal, user1)
	fmt.Printf("%+v", user1)
}

2. Reflection

2.1 Definition

Golang Provides a mechanism , At compile time Without knowing the type , can Update variables 、 Runtime Check the value Calling method And directly to them Operate on the layout The mechanism of , It's called reflection .

2.2 Method

Method explain return
reflect.ValueOf() Get the value of the data in the input parameter interface , If it is not empty, it returns 0, Note that the current method will make the object escape into heap space The return is Value object
reflect.TypeOf() Dynamically obtain the type of value in the input parameter interface , If it is empty, return nil The return is Type object
  • Value

    type Value struct {
          
    	typ *rtype
        // Save the value of the type 
    	ptr unsafe.Pointer
        // Pointer types 
    	flag
        // Get the pointing address of the value , Used to modify values by reflection 
        Elem() Type
        // to value Set the value 
        Set()
    }
    
  • Type

    type Type interface {
          
        // Get the method according to the index 
    	Method(int) Method
        // Get the method by name 
    	MethodByName(string) (Method, bool)
        // Get the number of methods 
    	NumMethod() int
        // Get structure name 
    	Name() string
        // Get package path 
    	PkgPath() string
        // Get the current type 
    	Kind() Kind
        // Determine whether the current type implements the interface 
    	Implements(u Type) bool
        // Returns... Of type in bits x
    	Bits() int
        // Get the type of property value , Type must be :Array、Chan、Map、Pointer、Slice, Otherwise, the report will be wrong 
    	Elem() Type
        // Get the specified value 
    	Field(i int) StructField
        // Get the nested fields of the corresponding index 
    	FieldByIndex(index []int) StructField
    	// Get the corresponding field by name 
    	FieldByName(name string) (StructField, bool)
    	FieldByNameFunc(match func(string) bool) (StructField, bool)
    
        .....
    }
    

2.3 Reflection reading

func stringReflect() {
    
	name := " This is the first reflection string "
	valueOf := reflect.ValueOf(name)
	typeOf := reflect.TypeOf(name)
	fmt.Println(valueOf)
	fmt.Println(typeOf)
}

 Insert picture description here

type Name struct {
    
	Name string
	Age string `use:"Ok"`
}

func (n Name) Show()  {
    
	fmt.Println(n.Name)
}

func structReflect() {
    
	name := Name{
    
		Name: " This is a reflective structure ",
	}
	valueOf := reflect.ValueOf(name)
	typeOf := reflect.TypeOf(name)
	fmt.Printf("value value :%+v\n", valueOf)
	fmt.Printf(" Type the name :%s\n", typeOf.Name())
	methodNum := typeOf.NumMethod()
	fmt.Printf(" Get the number of methods :%d", methodNum)
	for i := 0; i < methodNum; i++ {
    
		method := typeOf.Method(i)
		fmt.Printf("%v\t", method.Name)
	}
	fmt.Println()
	methodByName, _ := typeOf.MethodByName("Show")
	fmt.Printf(" according to Show Find the specified method :%v\n", methodByName)
	// Determine whether the current interface is implemented , Because the interface type cannot create an instance , So the  nil  Force to  *IName  type 
	implements := typeOf.Implements(reflect.TypeOf((*IName)(nil)).Elem())
	fmt.Printf(" Current type :%s, Whether the interface is implemented :%s,%v\n", typeOf.Name(), "IName", implements)

	fieldNum := typeOf.NumField()
	for i := 0; i < fieldNum; i++ {
    
		field := typeOf.Field(i)
		fmt.Printf(" Field name :%v\t", field.Name)
		if lookup, ok := field.Tag.Lookup("use") ; ok {
    
			fmt.Printf(" Get tag :%v", lookup)
		}
	}
}

2.4 Reflex action

func setValue() {
    
	name := Name{
    
		Name: " This is a reflective structure ",
	}
	valueOf := reflect.ValueOf(&name)
	fmt.Printf(" Before setting the value :%+v\n", valueOf)
	// Get the address value 
	valueOf = valueOf.Elem()
	name1 := Name{
    
		Name: " This is the value set by reflection ",
	}
	valueOf.Set(reflect.ValueOf(name1))
	fmt.Printf(" After setting the value :%+v\n", valueOf)

	// Modify field values 
	fieldValueOf := valueOf.FieldByName("Name")
	fieldValueOf.SetString(" This is the value after modifying the field ")
	fmt.Printf(" After modifying the field :%v\n", name.Name)

	// Calling method 
	methodByName := valueOf.MethodByName("Show")
	values := make([]reflect.Value, 0)
	methodByName.Call(values)
}

2.5 Judge

func judgeType() {
    
	name := Name{
    Name: "123"}
	typeOf := reflect.TypeOf(name)
	switch typeOf.Kind() {
    
	case reflect.Slice:
		fmt.Println(" section ")
	case reflect.Array:
		fmt.Println(" Array ")
	case reflect.Struct:
		fmt.Println(" Structure ")
	}
    // Determine the specific type 
	var ti interface{
    } = &name
	switch ti.(type) {
    
	case *Name:
		fmt.Printf("%+v\n", ti)
	}
}
原网站

版权声明
本文为[He Yi Qingfeng]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/161/202206101801248574.html