golang基礎--reflect反射

來源:互聯網
上載者:User

反射的知識點比較晦澀,後期會對此知識點展開深入的分析及範例程式碼展示

  • 反射可達大提高程式的靈活性,使得inferface{}有更大的發揮餘地

  • 反射使用TypeOf和ValueOf函數從介面中擷取目標對象資訊:欄位屬性,方法資訊

    package mainimport (    "fmt"    "reflect")type User struct { //定義一個結構類型    Id   int    Name string    Age  int}func (u User) Hello() { //定義一個結構方法    fmt.Println("Hello world")}func Info(o interface{}) { //定義一個方法,參數為空白介面    t := reflect.TypeOf(o)         //擷取接收到的介面類型    fmt.Println("Type:", t.Name()) //擷取名稱    v := reflect.ValueOf(o) //擷取介面的欄位    fmt.Println("Fields:")    //擷取結構欄位    for i := 0; i < t.NumField(); i++ { //for迴圈,取出所擁有的欄位        f := t.Field(i)               //擷取值欄位        val := v.Field(i).Interface() //擷取欄位的值        fmt.Printf("%6s:%v=%v\n", f.Name, f.Type, val)    }    //通過介面擷取結構的方法    for i := 0; i < t.NumMethod(); i++ {        m := t.Method(i)        fmt.Printf("%6s:%v\n", m.Name, m.Type)    }}func main() {    u := User{1, "OK", 12} //執行個體化一個結構    Info(u)                //調用Info函數}/*輸出    Type: User    Fields:        Id:int=1      Name:string=OK       Age:int=12    Hello:func(main.User)*/
  • 反射會將匿名欄位作為獨立欄位(匿名欄位本質)

    package mainimport (    "fmt"    "reflect")type User struct { //定義一個結構類型    Id   int    Name string    Age  int}type Manager struct {    User  //嵌入User結構,User就是Manager結構的匿名欄位    title string}func main() {    m := Manager{User: User{1, "mm", 27}, title: "name"} //注意初始化方式    t := reflect.TypeOf(m)                               //傳遞結構    fmt.Printf("%#v\n", t.Field(0))                  //擷取索引為0的欄位資訊,即User欄位資訊    fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 0})) //根據索引取出ID的欄位資訊()} //{0,0}--User在Manager索引為0,ID在User索引為0/*output    reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x4ac220), Tag:"",    Offset:0x0, Index:[]int{0}, Anonymous:true}"Anonymous:true" 其中包含Anonymous(匿名)欄位*/
  • 想要利用反射修改對象狀態,前提是interface.data是settable,即pointer-interface(指標介面)

    • 樣本1
    //這是一個簡單的修改對象狀態package mainimport (    "fmt"    "reflect")func main() {    x := 123                    //底層類型是int類型    v := reflect.ValueOf(&x)    //傳遞x的指標     v.Elem().SetInt(999)        //通過方法修改x變數的值    fmt.Println(x)}/*輸出x--->  999*/
    • 樣本2
    //通過反射修改結構欄位package mainimport (    "fmt"    "reflect")type User struct {    Name string    ID   int    Age  int}func main() {    u := User{"MAOZI", 1, 22}    Set(&u)    fmt.Println(u)}func Set(o interface{}) {    v := reflect.ValueOf(o)    if v.Kind() != reflect.Ptr && !v.Elem().CanSet() { //判斷是否為反射typestring,且可以被修改        fmt.Println("fuck")        return    } else { //如果條件都滿足        v = v.Elem()    }    f := v.FieldByName("Name") //通過名欄位名找欄位    if !f.IsValid() {          //IsValid方法判斷是否找了欄位        fmt.Println("invalid")        return    }    if f.Kind() == reflect.String {        f.SetString("momo")    }}/*輸出{momo 1 22}*/
  • 通過反射可以"動態"調用方法

    //通過反射動態調用結構方法package mainimport (    "fmt"    "reflect")type User struct {    Name string    ID   int    Age  int}func (u User) Hello(name string) {    fmt.Println("Hello", name, ",my name is", u.Name)}func main() {    u := User{"Golang", 1, 22}    v := reflect.ValueOf(u)    mv := v.MethodByName("Hello") //反射:通過名字找結構欄位資訊    args := []reflect.Value{reflect.ValueOf("Python")}    mv.Call(args)}/*輸出Hello Python ,my name is Golang*/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.