最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang泛型與反射的應用詳解

 更新時間:2022年06月15日 08:35:30   作者:Golang泛型與反射  
如果我想編寫一個可以輸出任何給定類型的切片并且不使用反射的打印功能,則可以使用新的泛型語法。文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

1. 泛型

1.1 定義

  • 泛型生命周期只在編譯期,旨在為程序員生成代碼,減少重復代碼的編寫
  • 在比較兩個數(shù)的大小時,沒有泛型的時候,僅僅只是傳入類型不一樣,我們就要再寫一份一模一樣的函數(shù),如果有了泛型就可以減少這類代碼

1.2 例子

// SumInts 將map的值相加,如果需要添加的數(shù)據(jù)類型不同,那么就需要定義兩個
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
}

如果使用泛型的話只需要定義泛型方法即可(如果報一下編譯錯誤的話,是idea版本過低,升級版本即可,但是運行沒有問題)

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))
    //可以將類型刪除
    fmt.Printf("Gnneric sums: %v and %v\n", 
		SumIntsOrFloats(ints), 
		SumIntsOrFloats(floats))
}
//SumIntsOrFloats 定義泛型方法
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 自定義泛型類型

  • any:代表 go里面所有的內置類型,等價于 interface {}
  • comparable:代表go里面內置的可比較類型:int、uint、float、bool、struct、指針等一切可比較類型
  • ~ 符號:用來表示改類型的衍生類型
//類型約束
type Number interface {
	int64 | float64
}
//進行類型約束時就可以使用當前類
func SumIntsNumbers[K comparable, V Number](m map[K]V) V {
	var s V
	for _, v := range m {
        s += v
	}
	return s
}

1.4 泛型與switch結合使用

func main() {
	fmt.Println(Get(12))
}
//go中不能直接將泛型與switch使用
func Get[T any](t T) T {
	var ti interface{} = &t
	switch v := ti.(type) {
	case *int:
		*v = 18
	}
	return t
}

1.5 泛型實戰(zhàn)

使用泛型定義Json解析方法

//根據(jù)傳入的類型通過反射獲取到類型以及值
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. 反射

2.1 定義

Golang提供了一種機制,在編譯時不知道類型的情況下,可更新變量、運行時查看值、調用方法以及直接對他們的布局進行操作的機制,稱為反射。

2.2 方法

方法說明返回
reflect.ValueOf()獲取輸入?yún)?shù)接口中的數(shù)據(jù)的值,如果未空則返回 0,注意當前方法會使對象逃逸到堆空間當中返回的是 Value 對象
reflect.TypeOf()動態(tài)獲取輸入?yún)?shù)接口中的值的類型,如果為空則返回 nil返回的是 Type 對象

Value

type Value struct {
	typ *rtype
    //保存類型的值
	ptr unsafe.Pointer
    //指針類型
	flag
    //獲取到值的指向地址,用于通過反射修改值
    Elem() Type
    //給value設置值
    Set()
}

Type

type Type interface {
    //根據(jù)索引獲取到方法
	Method(int) Method
    //通過名稱獲取到方法
	MethodByName(string) (Method, bool)
    //獲取到方法的數(shù)量
	NumMethod() int
    //獲取結構名稱
	Name() string
    //獲取包路徑
	PkgPath() string
    //獲取到當前類型
	Kind() Kind
    //判斷當前類型是否實現(xiàn)了接口
	Implements(u Type) bool
    //以位為單位返回類型的x
	Bits() int
    //獲取到屬性值的類型,類型必須是:Array、Chan、Map、Pointer、Slice,否則報錯
	Elem() Type
    //獲取到指定所以的值
	Field(i int) StructField
    //獲取到對應索引的嵌套字段
	FieldByIndex(index []int) StructField
	//通過名稱獲取到對應的字段
	FieldByName(name string) (StructField, bool)
	FieldByNameFunc(match func(string) bool) (StructField, bool)
    .....
}

2.3 反射讀取

func stringReflect() {
	name := "這是第一個反射字符串"
	valueOf := reflect.ValueOf(name)
	typeOf := reflect.TypeOf(name)
	fmt.Println(valueOf)
	fmt.Println(typeOf)
}

type Name struct {
	Name string
	Age string `use:"Ok"`
}
func (n Name) Show()  {
	fmt.Println(n.Name)
}
func structReflect() {
	name := Name{
		Name: "這是反射結構",
	}
	valueOf := reflect.ValueOf(name)
	typeOf := reflect.TypeOf(name)
	fmt.Printf("value值:%+v\n", valueOf)
	fmt.Printf("類型名稱:%s\n", typeOf.Name())
	methodNum := typeOf.NumMethod()
	fmt.Printf("獲取到方法的數(shù)量:%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("根據(jù)Show查找指定方法:%v\n", methodByName)
	//判斷是否實現(xiàn)了當前接口,因為接口類型不能創(chuàng)建實例,所以把 nil 強制轉為 *IName 類型
	implements := typeOf.Implements(reflect.TypeOf((*IName)(nil)).Elem())
	fmt.Printf("當前類型:%s,是否實現(xiàn)接口:%s,%v\n", typeOf.Name(), "IName", implements)
	fieldNum := typeOf.NumField()
	for i := 0; i < fieldNum; i++ {
		field := typeOf.Field(i)
		fmt.Printf("字段名稱:%v\t", field.Name)
		if lookup, ok := field.Tag.Lookup("use") ; ok {
			fmt.Printf("獲取標簽:%v", lookup)
		}
	}
}

2.4 反射操作

func setValue() {
	name := Name{
		Name: "這是反射結構",
	}
	valueOf := reflect.ValueOf(&name)
	fmt.Printf("設置值之前:%+v\n", valueOf)
	//獲取到地址值
	valueOf = valueOf.Elem()
	name1 := Name{
		Name: "這是通過反射設置的值",
	}
	valueOf.Set(reflect.ValueOf(name1))
	fmt.Printf("設置值之后:%+v\n", valueOf)
	//修改字段值
	fieldValueOf := valueOf.FieldByName("Name")
	fieldValueOf.SetString("這是修改字段之后的值")
	fmt.Printf("修改字段之后:%v\n", name.Name)
	//調用方法
	methodByName := valueOf.MethodByName("Show")
	values := make([]reflect.Value, 0)
	methodByName.Call(values)
}

2.5 判斷

func judgeType() {
	name := Name{Name: "123"}
	typeOf := reflect.TypeOf(name)
	switch typeOf.Kind() {
	case reflect.Slice:
		fmt.Println("切面")
	case reflect.Array:
		fmt.Println("數(shù)組")
	case reflect.Struct:
		fmt.Println("結構體")
	}
    //判斷具體類型
	var ti interface{} = &name
	switch ti.(type) {
	case *Name:
		fmt.Printf("%+v\n", ti)
	}
}

到此這篇關于Golang泛型與反射的應用詳解的文章就介紹到這了,更多相關Golang泛型與反射內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • golang 字符串比較是否相等的方法示例

    golang 字符串比較是否相等的方法示例

    這篇文章主要介紹了golang 字符串比較是否相等的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • 線上golang grpc服務資源泄露問題排查

    線上golang grpc服務資源泄露問題排查

    這篇文章主要介紹了線上golang grpc服務資源泄露問題排查,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Go語言模擬while語句實現(xiàn)無限循環(huán)的方法

    Go語言模擬while語句實現(xiàn)無限循環(huán)的方法

    這篇文章主要介紹了Go語言模擬while語句實現(xiàn)無限循環(huán)的方法,實例分析了for語句模擬while語句的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 深入string理解Golang是怎樣實現(xiàn)的

    深入string理解Golang是怎樣實現(xiàn)的

    這篇文章主要為大家介紹了深入string理解Golang是怎樣實現(xiàn)的原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • go語言實現(xiàn)處理表單輸入

    go語言實現(xiàn)處理表單輸入

    本文給大家分享的是一個使用go語言實現(xiàn)處理表單輸入的實例代碼,非常的簡單,僅僅是實現(xiàn)了用戶名密碼的驗證,有需要的小伙伴可以自由擴展下。
    2015-03-03
  • CMD下執(zhí)行Go出現(xiàn)中文亂碼的解決方法

    CMD下執(zhí)行Go出現(xiàn)中文亂碼的解決方法

    需要在Go寫的服務里面調用命令行或者批處理,并根據(jù)返回的結果做處理。但是windows下面用cmd返回中文會出現(xiàn)亂碼,本文就詳細的介紹一下解決方法,感興趣的可以了解一下
    2021-12-12
  • Go語言如何使用 Viper 來管理配置

    Go語言如何使用 Viper 來管理配置

    在現(xiàn)代軟件開發(fā)中,良好的配置管理可以極大地提升應用的靈活性和可維護性,下面我們就來看看GO語言中如何使用 Viper 來管理配置吧
    2024-11-11
  • go mod 依賴管理的具體使用

    go mod 依賴管理的具體使用

    在Go語言開發(fā)中,依賴管理是一項非常重要的工作,Go mod作為官方的包管理工具已經成為了Go語言依賴管理的首選方式,本文就來介紹一下go mod 依賴管理的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Golang?單元測試和基準測試實例詳解

    Golang?單元測試和基準測試實例詳解

    這篇文章主要為大家介紹了Golang?單元測試和基準測試實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 解決panic: assignment to entry in nil map問題

    解決panic: assignment to entry in nil

    這篇文章主要介紹了解決panic: assignment to entry in nil map問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2008-01-01

最新評論

开封市| 扶余县| 阜南县| 涿鹿县| 常熟市| 边坝县| 敖汉旗| 沙坪坝区| 栾城县| 辽源市| 聊城市| 民权县| 云南省| 湘乡市| 会同县| 资溪县| 克什克腾旗| 九江县| 霍林郭勒市| 多伦县| 玛曲县| 海丰县| 盘锦市| 聊城市| 凯里市| 沾化县| 红安县| 富蕴县| 晋江市| 新龙县| 彭水| 修武县| 碌曲县| 南投市| 舒兰市| 台湾省| 惠来县| 镇江市| 浮梁县| 泌阳县| 高台县|