成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一篇學(xué)會(huì)Go中reflect反射的詳細(xì)用法

開發(fā) 前端
在Go語(yǔ)言的反射機(jī)制中,任何接口值都由是一個(gè)具體類型和具體類型的值兩部分組成的(我們?cè)谏弦黄涌诘牟┛椭杏薪榻B相關(guān)概念)。

應(yīng)用場(chǎng)景

1.判斷函數(shù)變量是否否和標(biāo)準(zhǔn)

2.驗(yàn)證接口值是否合理如(是否為空,傳入的字段是否合規(guī))

3.獲取變量的類型進(jìn)行斷言等操作

在Go語(yǔ)言的反射機(jī)制中,任何接口值都由是一個(gè)具體類型和具體類型的值兩部分組成的(我們?cè)谏弦黄涌诘牟┛椭杏薪榻B相關(guān)概念)。 在Go語(yǔ)言中反射的相關(guān)功能由內(nèi)置的reflect包提供,任意接口值在反射中都可以理解為由reflect.Type和reflect.Value兩部分組成,并且reflect包提供了reflect.TypeOf和reflect.ValueOf兩個(gè)函數(shù)來(lái)獲取任意對(duì)象的Value和Type。

1.結(jié)構(gòu)體中使用反射

  • 獲取 2 種類型信息的方法:

reflect.TypeOf() 獲取類型信息,返回 Type 類型;

reflect.ValueOf() 獲取數(shù)據(jù)信息,返回 Value 類型。

反射中值的可設(shè)置性,可以用 CanSet 方法來(lái)判斷值是否可以設(shè)置。在 Go 中,函數(shù)參數(shù)的傳遞都是值拷貝,在反射中要修改值,必須傳遞指針,并且用 Elem() 方法獲取指針的值,然后進(jìn)行修改。

reflect.ValueOf() 返回的 Value 類型:

  • 它有一個(gè) Type() 方法,返回的是 reflect.Value 的 Type
  • 它有獲取 Value 類型值的方法如果我們知道是 float 類型,所以直接用 Float() 方法。如果不知道具體類型呢?由上面例子可知用 Interface() 方法,然后在進(jìn)行類型斷言 v.Interface().(float64) 來(lái)判斷獲取值

v.Kind() 和 v.Type() 區(qū)別:

在 type MyInt int 里,v.Kind() 與 v.Type() 返回了不同的類型值,Kind()返回的是 int,Type() 返回的是 MyInt。在 Go 中,可以用 type 關(guān)鍵字定義自定義類型,Kind() 方法返回底層類型。比如還有結(jié)構(gòu)體,指針等類型用 type 定義的,那么 Kind() 方法就可以獲取這些類型的底層類型。

案例使用方法

package main

import (
	"fmt"
	"reflect"
)

type Userinfo struct {
	Age      int `id:"iloveyou" num:"222"` //tag標(biāo)簽信息
	UserName string
}

func GetReflickInfo(i interface{}) {
	vl := reflect.ValueOf(i)
	//nii := 200
	fmt.Println("kind ======", vl.Kind())
	if vl.Kind() == reflect.Ptr { //如是指針類型,先取值
		vl = vl.Elem() //Elem方法就是取值操作
	}
	vlt := vl.Type() //獲取具體類型,如自定義結(jié)構(gòu)體的類型
	fmt.Println("kind ======type===", vl.Kind(), vlt)
	if vl.Kind() != reflect.Struct {
		fmt.Println("類型:", vlt, " 名字:", vlt.Name(), " 數(shù)值:", vl)
		//如是整數(shù)種類,又可以修改,CanSet屬性為true,則進(jìn)行修改。
		if vl.Kind() == reflect.Int || vl.Kind() == reflect.Int64 && vl.CanSet() {
			vl.SetInt(100)
			//reflect.New(vlt)是創(chuàng)建了一個(gè)vlt類型的指針變量。
			ni := reflect.New(vlt)
			//創(chuàng)建后的ni是reflect.Value對(duì)象,需要通過(guò)ValueOf來(lái)賦值
			ni = reflect.ValueOf(222)
			fmt.Println("修改后int數(shù)值:", vl, "新建數(shù)值:", ni)
		}
		//如是浮點(diǎn)數(shù)種類,又可以修改,CanSet屬性為true,則進(jìn)行修改。
		//可設(shè)置性檢查:vl.CanSet() 是一個(gè)方法,用于確認(rèn)vl的值是否可以被修改。在Go中,不是所有的反射值都能被設(shè)置,比如函數(shù)參數(shù)或者某些靜態(tài)類型就不能。如果vl的值可以被改變,CanSet()將返回true。
		if vl.Kind() == reflect.Float32 || vl.Kind() == reflect.Float64 && vl.CanSet() {
			vl.SetFloat(100.11) //調(diào)用vl.SetFloat(100.11)方法將變量vl的值設(shè)置為100.11。
			fmt.Println("修改后float數(shù)值:", vl)
		}
	} else {
		fmt.Println("結(jié)構(gòu)體類型:", vlt, " 名字:", vlt.Name())
		for i := 0; i < vl.NumField(); i++ {
			//vl是具體的值,這里vl.Field(i)就是枚舉出每一個(gè)成員的值
			//vlt是獲取的類型,vlt.Field(i).Name和.Type是枚舉出每一個(gè)成員的名字和類型
			//也可以使用FieldByName,從指定的成員名獲取具體值,vlret:= vl.FieldByName(vlt.Field(i).Name)
			fmt.Println("成員名:", vlt.Field(i).Name, " 類型:", vlt.Field(i).Type, " 數(shù)值:", vl.Field(i))
			//如是字符串種類,又可以修改,CanSet屬性為true,則進(jìn)行修改。
			if vl.Field(i).Kind() == reflect.String && vl.Field(i).CanSet() {
				vl.Field(i).SetString("new str")
				fmt.Println("string成員修改后數(shù)值:", vl.Field(i))
			}
			//而tag標(biāo)簽信息都是靜態(tài)的,無(wú)須實(shí)例化結(jié)構(gòu)體,通過(guò)類型vlt可以獲取到。
			//這句vlt.Field(i).Tag.Lookup("id")就是枚舉出每一個(gè)成員的tag標(biāo)簽,看里面是否有id這個(gè)key,并返回它的value值
			if idtag, b := vlt.Field(i).Tag.Lookup("id"); b {
				fmt.Println("tag id=", idtag)
			}
			if numtag, b := vlt.Field(i).Tag.Lookup("num"); b {
				fmt.Println("tag num=", numtag)
			}
		}
	}
}

func main() {
	var price float64 = 3.14
	var age int64 = 5
	bd := Userinfo{100, "andy"}
	ns := struct { //定義一個(gè)無(wú)名結(jié)構(gòu)體
		id   int
		addr string
	}{2, "aa"}
	GetReflickInfo(price)
	GetReflickInfo(&age) //把變量地址傳遞,所以可以修改。
	GetReflickInfo(&bd)  //把結(jié)構(gòu)體地址傳遞,所以可以修改。
	fmt.Println(bd)      //打印出修改后的結(jié)構(gòu)體變量
	GetReflickInfo(ns)
}


責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2021-08-12 07:49:24

SQL遞歸用法

2022-05-17 08:02:55

GoTryLock模式

2021-07-16 22:43:10

Go并發(fā)Golang

2022-06-09 08:41:17

Go網(wǎng)絡(luò)庫(kù)Gnet

2021-04-30 09:04:11

Go 語(yǔ)言結(jié)構(gòu)體type

2023-12-05 07:14:27

AIGo

2021-11-15 10:29:39

Go語(yǔ)言類型

2022-01-02 08:43:46

Python

2022-02-07 11:01:23

ZooKeeper

2020-12-31 09:06:44

Go語(yǔ)言Reflect

2022-06-30 22:53:18

數(shù)據(jù)結(jié)構(gòu)算法

2021-08-01 07:19:16

語(yǔ)言OpenrestyNginx

2021-04-20 06:12:09

Swift 反射 Mirror反射機(jī)制

2021-10-26 10:40:26

代理模式虛擬

2021-12-04 22:05:02

Linux

2021-05-11 08:54:59

建造者模式設(shè)計(jì)

2021-07-02 09:45:29

MySQL InnoDB數(shù)據(jù)

2021-07-06 08:59:18

抽象工廠模式

2023-01-03 08:31:54

Spring讀取器配置

2022-08-26 09:29:01

Kubernetes策略Master
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美一级免费看 | 999久久精品 | 国产精品a久久久久 | 日本亚洲一区 | 久久伊人亚洲 | 成人妇女免费播放久久久 | 网站黄色在线 | 日韩黄色av | 久久久91 | 国产精品91久久久久久 | 一级片在线播放 | 国产草草视频 | 91精品在线播放 | 久久99久久99精品免视看婷婷 | 久久综合一区二区三区 | 中国大陆高清aⅴ毛片 | 正在播放国产精品 | 日韩精品免费视频 | 一级毛片在线看 | 精品欧美一区二区中文字幕视频 | 久久久久1 | 成人免费大片黄在线播放 | 国产精品激情 | 日韩h| 亚洲 成人 在线 | 日韩一区二区三区精品 | 精品视频一区二区 | 亚洲成av人片在线观看无码 | 久久久久亚洲av毛片大全 | 久久久国产一区二区三区四区小说 | 午夜精品一区二区三区在线视频 | 成在线人视频免费视频 | 国产99久久精品一区二区300 | 天天综合久久 | 日韩一区二区三区视频在线播放 | 国产在线一区二 | 久久99精品久久 | 成人av免费在线观看 | 久久久久久久成人 | 国产精品国产成人国产三级 | 欧美一区二区三区在线看 |