Go語言中反射reflect的基礎使用

介紹

我們知道反射是可以在程序的運行期間獲取到變量或者結構體的一些元信息桥爽,能夠知道類型杠览,變量的值甚至修改值丰辣,執(zhí)行方法等

java中的反射應用非常廣泛写烤,基本上所有框架都用到了動態(tài)代理翼闽,而動態(tài)代理就是基于反射實現的。

在go中也專門提供了一個標準庫reflect洲炊,下面我們就基于這個庫來簡單使用下感局。

我們準備一個結構體Person,包含有屬性方法暂衡。

1 創(chuàng)建該結構體的一個對象询微,通過反射獲取到該對象的 結構體名稱、類型狂巢、各個字段的名字撑毛、各個字段的tag、獲取方法并執(zhí)行方法唧领。

2 通過反射構建一個該結構體實例藻雌,給每個字段填充值。

package main

import (
    "fmt"
    "reflect"
    "time"
)

type Person struct {
    Name      string    `json:"name"`
    Age       int       `json:"age"`
    Married   bool      `json:"married"`
    BirthTime time.Time `json:"birthTime"`
}

func (p *Person) Eat(name string) {
    fmt.Println("執(zhí)行:吃", name)
}

func main() {
    location, err := time.LoadLocation("Asia/Shanghai")
    if err != nil {
        return
    }
    //解析時間
    parse, err := time.ParseInLocation("2006-01-02 15:04:05", "1998-10-04 21:00:32", location)

    // 1 構建一個person指針對象
    person := &Person{Name: "wendell", Age: 20, Married: false, BirthTime: parse}

    // 拿到類型
    t := reflect.TypeOf(person)
    // 拿到value
    v := reflect.ValueOf(person)
    fmt.Printf("type:%s\nvalue:%v\n", t, v)

    // 判斷是否是指針類型斩个,一般反射我們都習慣操作指針
    fmt.Println("是否是指針類型", t.Kind() == reflect.Pointer)

    // 只有是指針或者interface才能調用該方法胯杭,返回具體的值
    // 如果說一開始操作的不是指針,那么這一步可以省略受啥,直接使用 t v 即可
    tElem := t.Elem()
    vElem := v.Elem()

    fmt.Println("對象名字:", tElem.Name())

    fmt.Println("字段個數:", tElem.NumField())
    for i := 0; i < tElem.NumField(); i++ {
        fmt.Printf("[%v]\t[%v]\t[%v]\t[%v]\n", tElem.Field(i).Name, tElem.Field(i).Tag, tElem.Field(i).Tag.Get("json"), vElem.Field(i).Interface())
    }

    // 獲取到方法做个,執(zhí)行方法
    method := v.MethodByName("Eat")
    args := make([]reflect.Value, 1)
    args[0] = reflect.ValueOf("蘋果")
    method.Call(args)
    fmt.Println("------------------------------------------")

    // 2 創(chuàng)建一個新的person對象
    value := reflect.New(t.Elem()).Interface()
    fmt.Println("構建新的對象", value)

    valueOf := reflect.ValueOf(value)
    elem := valueOf.Elem()

    name := reflect.ValueOf("juan")
    age := reflect.ValueOf(25)

    fmt.Println("name是否允許重新設置值:", elem.Field(0).CanSet())
    // 通過反射給對象設置值
    elem.Field(0).Set(name)
    fmt.Println("age是否允許重新設置值:", elem.Field(1).CanSet())
    elem.Field(1).Set(age)
    fmt.Println("反射設置值之后的", value)
}

執(zhí)行結果

type:*main.Person
value:&{wendell 20 false 1998-10-04 21:00:32 +0800 CST}
是否是指針類型 true
對象名字: Person
字段個數: 4
[Name]  [json:"name"]   [name]  [wendell]
[Age]   [json:"age"]    [age]   [20]
[Married]   [json:"married"]    [married]   [false]
[BirthTime] [json:"birthTime"]  [birthTime] [1998-10-04 21:00:32 +0800 CST]
執(zhí)行:吃 蘋果
------------------------------------------
構建新的對象 &{ 0 false 0001-01-01 00:00:00 +0000 UTC}
name是否允許重新設置值: true
age是否允許重新設置值: true
反射設置值之后的 &{juan 25 false 0001-01-01 00:00:00 +0000 UTC}

Process finished with the exit code 0

通過上面例子我們大概就清楚反射給我們提供了一些什么功能。那么實際框架中怎么應用呢滚局。加入你要做一個orm框架居暖。大概要做到如下程度。只需要打開一個session給出查詢條件執(zhí)行查詢就能返回需要的值藤肢,并且該值已經封裝成了user集合

u := &User{}
userList, err := DB.OpenSession().Like("user_id", "test").SelectAll(u)

那么我們都知道執(zhí)行一條查詢語句需要知道 表名太闺,字段名那么上面代碼都沒有設置如何獲取,這個時候我就可以形成一種規(guī)范嘁圈,結構體名字就是默認表名跟束,屬性名稱的下劃線形式就是默認字段名可以通過tag指定字段名叫啥莺奸。返回值我們可以通過傳入的類型New出一個結構體對象,通過該對象的屬性與表字段名的映射關系就可以自動將查詢出的結果設置到結構體中冀宴,
于是結構體可以這樣寫

type User struct {
    UserId      string `db:"user_id",primary:"true"`
    Username    string `db:"user_name"`
    Admin       bool
}

對應的sql語句

select user_id,username,admin from user_id like "%test%"

好了灭贷,反射的基本使用就到這里,后面會發(fā)布orm框架的簡單實現略贮。


歡迎關注甚疟,學習不迷路!

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末逃延,一起剝皮案震驚了整個濱河市览妖,隨后出現的幾起案子,更是在濱河造成了極大的恐慌揽祥,老刑警劉巖讽膏,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異拄丰,居然都是意外死亡府树,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門料按,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奄侠,“玉大人,你說我怎么就攤上這事载矿÷⒊保” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵闷盔,是天一觀的道長弯洗。 經常有香客問我,道長逢勾,這世上最難降的妖魔是什么涂召? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮敏沉,結果婚禮上,老公的妹妹穿的比我還像新娘炎码。我一直安慰自己盟迟,他們只是感情好,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布潦闲。 她就那樣靜靜地躺著攒菠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪歉闰。 梳的紋絲不亂的頭發(fā)上辖众,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天卓起,我揣著相機與錄音,去河邊找鬼凹炸。 笑死戏阅,一個胖子當著我的面吹牛,可吹牛的內容都是我干的啤它。 我是一名探鬼主播奕筐,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼变骡!你這毒婦竟也來了离赫?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤塌碌,失蹤者是張志新(化名)和其女友劉穎渊胸,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體台妆,經...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡翎猛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了频丘。 大學時的朋友給我發(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

推薦閱讀更多精彩內容