Golang反射reflect

reflect反射,可以通過reflect反射結構體所包含的屬性和方法撤卢,然后進行一些賦值和方法的調(diào)用,靈活度比較高

下面定律引用別人的博客:http://blog.csdn.net/wo198711203217/article/details/70213812感覺寫的還透徹

  • 反射定律一:反射可以將“接口類型變量”轉換為“反射類型對象”
    這里的反射類型指的是reflect.Type和reflect.Value
    將接口類型變量轉換為反射類型變量,是通過reflect包的TypeOf和ValueOf實現(xiàn)的。
  • 反射定律二: 反射可以將“反射類型對象”轉換為“接口類型變量
    根據(jù)一個 reflect.Value 類型的變量,我們可以使用 Interface 方法恢復其接口類型的值。事實上,這個方法會把 type 和 value 信息打包并填充到一個接口變量中寂祥,然后返回。
  • 反射定律三:如果要修改反射類型對象七兜,其值必須是“addressable”
    通過反射定義一可以知道丸凭,反射對象包含了接口變量中存儲的值以及類型。
    如果反射對象中包含的值是原始值腕铸,那么可以通過反射對象修改原始值惜犀;
    如果反射對象中包含的值不是原始值(反射對象包含的是副本值或指向原始值的地址),那么該反射對象是不可以修改的狠裹。
    通過CanSet函數(shù)可以判定反射對象是否可以修改
package my

import (
    ft "fmt"
    "reflect"
)

type User struct {
    Id   int
    Name string
}

func (user User) Print() {
    ft.Println("reflect Print()")
}

func Reflect(inter interface{}) {
    t := reflect.TypeOf(inter) //從接口中獲取結構的對象

    if k:=t.Kind();k!=reflect.Struct{//判斷傳入的是否是struce類型,而不是指針類型*User,指針類型報錯
        ft.Println("type is not true")
        return
    }
    ft.Println("類型名稱:", t.Name())
    v := reflect.ValueOf(inter) //從接口中獲取結構的值

    for i := 0; i < t.NumField(); i++ { //遍歷所包含的屬性字段
        f := t.Field(i) //獲取到字段
        val := v.Field(i).Interface()
        ft.Println("字段簽名:", f.Type, " 字段名稱:", f.Name, "  值:", val)
    }

    for i := 0; i < t.NumMethod(); i++ { //遍歷所綁定的方法
        m := t.Method(i) //獲取到方法
        ft.Println("方法名稱:", m.Name, " 方法簽名:", m.Type)
    }
}

  • 結構體嵌套的反射
package something

import (
    ft "fmt"
    "reflect"
)

type User struct {
    Id   int
    Name string
    Info
    Base
}

type Info struct {
    Age     int
    Address string
}

type Base struct {
    Sex int
}

func (user User) Printl(name string) {
    ft.Println("reflect Print()", name)
}

func Reflect(inter interface{}) {
    t := reflect.TypeOf(inter)  //從接口中獲取結構的對象
    v := reflect.ValueOf(inter) //從接口中獲取結構的值
    if t.Kind() == reflect.Ptr && v.Elem().CanSet() { //傳入的是指針,可以修改
        ft.Println("這里")
        v = v.Elem()

        if f := v.Kind(); f == reflect.Struct {
            if x := v.FieldByName("Age"); x.IsValid() {
                x.SetInt(888)
            }

            if x := v.FieldByName("Address"); x.IsValid() {
                x.SetString("深圳市")
            }

            if x := v.FieldByName("Sex"); x.IsValid() {
                x.SetInt(100001)
            }
        }

        if f := v.FieldByName("Name"); f.Kind() == reflect.String && f.IsValid() {
            f.SetString("haha")
        }

        if f := v.FieldByName("Id"); f.Kind() == reflect.Int && f.IsValid() {
            f.SetInt(99)
        }

        if f := v.MethodByName("Print"); f.IsValid() {
            args := []reflect.Value{reflect.ValueOf("測試")}
            f.Call(args)
        }
    }

    if k := t.Kind(); k != reflect.Struct { //判斷傳入的是否是struct類型
        ft.Println("type is not true")
        return
    }
    ft.Println("類型名稱:", t.Name())

    for i := 0; i < t.NumField(); i++ { //遍歷所包含的屬性字段
        f := t.FieldByIndex([]int{i}) //獲取到字段
        val := v.FieldByIndex([]int{i}).Interface()
        ft.Println("字段簽名:", f.Type, " 字段名稱:", f.Name, "  值:", val)
    }

    for i := 0; i < t.NumMethod(); i++ { //遍歷所綁定的方法
        m := t.Method(i) //獲取到方法
        ft.Println("方法名稱:", m.Name, " 方法簽名:", m.Type)
    }
}



  • Elem returns the value that the interface v contains or that the pointer v points to. It panics if v's Kind is not Interface or Ptr. It returns the zero Value if v is nil.
    解釋的大概意思是結構包含接口或指針指向的元素返回值,類型不能使沒有實現(xiàn)接口或者指針的結構,如果值是空的,則返回0
package main

import (
    f "fmt"
     "com.guo/mytest/something"
)

func main(){
    r:=something.User{1,"haha",something.Info{100,"廣州市"}}
    something.Reflect(&r)
    something.Reflect(r)
    f.Println("修改后結果:",r)
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虽界,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子涛菠,更是在濱河造成了極大的恐慌莉御,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俗冻,死亡現(xiàn)場離奇詭異礁叔,居然都是意外死亡,警方通過查閱死者的電腦和手機迄薄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門琅关,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人讥蔽,你說我怎么就攤上這事涣易。” “怎么了冶伞?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵都毒,是天一觀的道長。 經(jīng)常有香客問我碰缔,道長,這世上最難降的妖魔是什么戳护? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任金抡,我火速辦了婚禮,結果婚禮上腌且,老公的妹妹穿的比我還像新娘梗肝。我一直安慰自己,他們只是感情好铺董,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布巫击。 她就那樣靜靜地躺著禀晓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坝锰。 梳的紋絲不亂的頭發(fā)上粹懒,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音顷级,去河邊找鬼凫乖。 笑死,一個胖子當著我的面吹牛弓颈,可吹牛的內(nèi)容都是我干的帽芽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼翔冀,長吁一口氣:“原來是場噩夢啊……” “哼导街!你這毒婦竟也來了?” 一聲冷哼從身側響起纤子,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤搬瑰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后计福,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跌捆,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年象颖,在試婚紗的時候發(fā)現(xiàn)自己被綠了佩厚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡说订,死狀恐怖抄瓦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陶冷,我是刑警寧澤钙姊,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站埂伦,受9級特大地震影響煞额,放射性物質發(fā)生泄漏。R本人自食惡果不足惜沾谜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一膊毁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧基跑,春花似錦婚温、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荆秦。三九已至,卻和暖如春力图,著一層夾襖步出監(jiān)牢的瞬間步绸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工搪哪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留靡努,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓晓折,卻偏偏與公主長得像惑朦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子漓概,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 第一次知道反射的時候還是許多年前在學校里玩 C# 的時候漾月。那時總是弄不清楚這個復雜的玩意能有什么實際用途……然后發(fā)...
    勿以浮沙筑高臺閱讀 1,128評論 0 9
  • 一梁肿、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,265評論 0 16
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)觅彰,斷路器吩蔑,智...
    卡卡羅2017閱讀 134,660評論 18 139
  • 凌晨,恍惚中填抬,不確定時間了烛芬,只記得身著白色襯衣的你,走到我的桌旁飒责,令我很驚訝赘娄,問你干嘛呢?你好像說要走了宏蛉,然后就移...
    愛生活挺自己閱讀 235評論 0 0
  • 如果文字可以表達美好情感遣臼,那么請你去記錄! 如果文字可以傳遞深邃思想拾并,那么請你去記錄揍堰! 如果文字可以記錄甜蜜生活,...
    錦瑟了無痕閱讀 286評論 1 4