go reflect 反射的使用

參考 :http://c.biancheng.net/view/4407.html

反射是指在程序運行期對程序本身進行訪問和修改的能力篓像,程序在編譯時變量被轉換為內存地址阀趴,變量名不會被編譯器寫入到可執(zhí)行部分,在運行程序時程序無法獲取自身的信息

舉個例子說明啥是反射呢袒啼?

就是比如 python getattr 函數(shù)類似茄蚯,通過字段屬性名 拿到字段對應的值。
或者 a = "xxx"
js 里面 map.xxx 也可以 map[a]

go 里面什么情況用反射

我現(xiàn)在想通過字段名的 字符串變量运翼,獲取結構體對應的字段值岁钓, 貌似只能用 xxx_struct.xxx 而不能像 js 里面那樣 xxx_struct["xxx"] , 那就只能用 反射了激涤。

go 怎么實現(xiàn) 反射

使用 內置包 reflect
reflect 定義了兩個重要的類型 Type 和 Value 任意接口值在反射中都可以理解為由 reflect.Type 和 reflect.Value 兩部分組成

reflect 反射 練習
  • 反射獲取信息 reflect.TypeOf

返回的是 reflect.Type 類型
reflect.Type 對象可以訪問任意值的類型信息, 有兩個重要的 函數(shù)累提, Name() 返回Type 和 Kind() 返回 Kind 種類
reflect.TypeOf (xxx interface{}).Name() 返回定義
int尘喝、string、bool斋陪、float32 以及 使用 type 定義的類型名
reflect.TypeOf (xxx interface{}).Kind() 返回定義
int朽褪、string、bool无虚、float32 struct func 這種原始的類型名

普通類型獲取反射類型

type A struct{} 
var a A
reflect.TypeOf(a).Name()   // A
reflect.TypeOf( a ).Kind()   //  struct

指針類型獲取 反射類型

reflect.TypeOf(a).Elem().Name()/Kind() 

獲取結構體的成員類型信息
(只是信息缔赠,并不能取到對應的值)
針對結構體,即如果 反射的 Kind() 返回的 是 struct ,那可以通過一下函數(shù)友题,獲取它成員的信息

  • reflect.TypeOf (xxx interface{}).NumField()
    返回結構體成員字段數(shù)量
NumField() int  

  • reflect.TypeOf (xxx interface{}).Field()
    返回索引對應的結構體字段的信息
Field(i int) StructField
  • reflect.TypeOf (xxx interface{}).FieldByName()
    返回字符串對應的結構體字段的信息
FieldByName(name string) (StructField, bool)
  • reflect.TypeOf (xxx interface{}).FieldByIndex()
    多層成員訪問時嗤堰,根據(jù) []int 提供的每個結構體的字段索引,返回字段的信息
FieldByIndex(index []int) StructField
  • reflect.TypeOf (xxx interface{}).FieldByNameFunc()
    根據(jù)匹配函數(shù)匹配需要的字段
FieldByNameFunc(match func(string) bool) (StructField,bool)

說明一下度宦, 上面函數(shù)返回為 StructField 對象(Field, FieldByName, FieldByIndex, FieldByNameFunc )踢匣,StructField 對象具有以下屬性

StructField 對象結構體字段

type StructField struct {
    Name string          // 字段名
    PkgPath string       // 字段路徑
    Type      Type       // 字段反射類型對象,  字段本身的反射類型對象,類型為 
// reflect.Type戈抄,可以進一步獲取字段的類型信息, 像遞歸了
    Tag       StructTag  // 字段的結構體標簽
    Offset    uintptr    // 字段在結構體中的相對偏移
    Index     []int      // Type.FieldByIndex中的返回的索引值
    Anonymous bool       // 是否為匿名字段
}

舉個例子說明獲取結構體的字段信息

func main(){
    type girl struct{
        name string `json:"nikname"`
        age int
        high int

    }
    var a = girl{"小蓮", 28, 165}
    reflect_type := reflect.TypeOf(a)
    fmt.Println( "Name():", reflect_type.Name(), "kind():", reflect_type.Kind())

    kind := reflect_type.Kind()
    if kind == reflect.Struct{
        fmt.Printf("是結構體\n")
        // 遍歷獲取名稱离唬, Field 通常和 NumField 以前搭配使用, 遍歷結構體划鸽, 這
// 里僅獲取結構體成員信息输莺,并沒有獲取值
        for i := 0; i < reflect_type.NumField(); i++{
            fmt.Printf("index: %v, file name: %v\n", i, reflect_type.Field(i).Name)
        }

        // 通過字段名字獲取字段信息.
        if info, ok := reflect_type.FieldByName("name"); ok{
            fmt.Printf("name is :%v, tag is: %v \n", info.Name, info.Tag.Get("json"))
        }

    }

}

>
Name(): girl kind(): struct
是結構體
index: 0, file name: name
index: 1, file name: age
index: 2, file name: high
name is :name, tag is: nikname 

上面提到了 結構體的反射對象 StructField 里面有個 Struct Tag, 我們來看看這個 TAG 里面是神馬東西把:

字段的額外信息漾稀, 這些信息都是靜態(tài)的模闲,無須實例化結構體,可以通過反射獲取到

書寫結構:

`key1:"value1" key2:"value2"`

結構體標簽由一個或多個鍵值對組成崭捍;鍵與值使用冒號分隔尸折,值用雙引號括起來;鍵值對之間使用一個空格分隔殷蛇, 這個格式很嚴格实夹,有地方多一個空格都不會是期望的結果

取出 key 對應值:

reflect_type.FieldByName("xx").Tag.Get("json")   

判斷 key 是不是存在:
Lookup(key)

func (tag StructTag) Lookup(key string) (value string, ok bool)
reflect_type.FieldByName("xx").Tag.Lookup("json")   
  • 反射獲取值 reflect.ValueOf

普通類型獲取反射類型

value := reflect.ValueOf(rawValue)

返回 reflect.Value 類型
reflect.Value 是一些反射操作的重要類型橄浓,如反射調用函數(shù)

reflect.Value 對象所具有的方法

  • 將值以 interface{} 類型返回
Interface() interface {}
  • 將值以 int 類型返回(所有有符號整型均可以此方式返回)
Int() int64
  • 值以 uint 類型返回(所有無符號整型均可以此方式返回)
Uint() uint64
  • 值以雙精度(float64)類型返回,所有浮點數(shù)(float32亮航、float64)均可以此方式返回
Float() float64
  • 將值以 bool 類型返回
Bool() bool
  • 將值以字節(jié)數(shù)組 []bytes 類型返回
Bytes() []bytes
  • 將值以字符串類型返回
String() string 

結構體反射獲取值
方法如下荸实, 和獲取信息的一樣,子不過缴淋,獲取的 是 Value 對象准给,不是 StructField 對象

  • Field(i int) Value
  • NumField() int
  • FieldByName(name string) Value
  • FieldByIndex(index []int) Value
  • FieldByNameFunc(match func(string) bool) Value

關于 值類型的方法參考:
https://golang.google.cn/pkg/reflect/#Value

反射修改值

reflect.Value 修改值得方法(和 獲取值是對應的):

Setlnt(x int64)   SetUint(x uint64)  SetFloat(x float64) SetBool(x bool)  
SetBytes(x []byte   SetString(x string)  

可以被修改的條件:

傳入地址
var a int = 1024
valueOfA := reflect.ValueOf(&a)
valueOfA = valueOfA.Elem()
valueOfA.SetInt(1)

結構體成員中,字段可導出
type dog struct {
            LegCount int
    }
valueOfDog := reflect.ValueOf(&dog{})
valueOfDog = valueOfDog.Elem()
vLegCount := valueOfDog.FieldByName("LegCount")
vLegCount.SetInt(4)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末重抖,一起剝皮案震驚了整個濱河市露氮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钟沛,老刑警劉巖畔规,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異恨统,居然都是意外死亡叁扫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門畜埋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莫绣,“玉大人,你說我怎么就攤上這事由捎⊥米郏” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵狞玛,是天一觀的道長软驰。 經(jīng)常有香客問我,道長心肪,這世上最難降的妖魔是什么锭亏? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮硬鞍,結果婚禮上慧瘤,老公的妹妹穿的比我還像新娘。我一直安慰自己固该,他們只是感情好锅减,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伐坏,像睡著了一般怔匣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桦沉,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天每瞒,我揣著相機與錄音金闽,去河邊找鬼。 笑死剿骨,一個胖子當著我的面吹牛代芜,可吹牛的內容都是我干的。 我是一名探鬼主播浓利,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼挤庇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荞膘?” 一聲冷哼從身側響起罚随,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎羽资,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遵班,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡屠升,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了狭郑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腹暖。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翰萨,靈堂內的尸體忽然破棺而出脏答,到底是詐尸還是另有隱情,我是刑警寧澤亩鬼,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布殖告,位于F島的核電站,受9級特大地震影響雳锋,放射性物質發(fā)生泄漏黄绩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一玷过、第九天 我趴在偏房一處隱蔽的房頂上張望爽丹。 院中可真熱鬧,春花似錦辛蚊、人聲如沸粤蝎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽初澎。三九已至,卻和暖如春飞蛹,著一層夾襖步出監(jiān)牢的瞬間谤狡,已是汗流浹背灸眼。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留墓懂,地道東北人焰宣。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像捕仔,于是被迫代替她去往敵國和親匕积。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內容

  • reflection 反射(reflection)是程序在運行時通過檢查其定義的變量和值獲得對應的真實類型榜跌。 在計...
    JunChow520閱讀 1,762評論 0 5
  • 目錄 通過反射獲取類型信息[https://www.cnblogs.com/itbsl/p/10551880.ht...
    gurlan閱讀 525評論 0 0
  • reflect概述 反射是一種檢查存儲在 接口變量中的<值,類型>對 的機制闪唆,借助go反射包提供的reflect....
    斯嘎啦閱讀 1,065評論 0 0
  • 一、認識反射 維基百科中的定義:在計算機科學中钓葫,反射是指計算機程序在運行時(Run time)可以訪問悄蕾、檢測和修改...
    Every_dawn閱讀 1,580評論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭础浮,有人歡樂有人憂愁帆调,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,528評論 28 53