golang 中的Interface 和 反射

YuWenHaiBo · · 648 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

基础知识在这里学习:
资源一
资源二
看完这些基本的估计都有点朦朦胧胧,好文章是值得读好几遍的,这里我写一些例子,用来快速上手。

  reflect.Type 常用函数使用
type Type interface {
    Method(int) Method
    MethodByName(string) (Method, bool)
    NumMethod() int
    Name() string
    Size() uintptr
    String() string
    Kind() Kind
    Elem() Type
    Field(i int) StructField
    FieldByIndex(index []int) StructField
    FieldByName(name string) (StructField, bool)
    FieldByNameFunc(match func(string) bool) (StructField, bool)
    NumField() int
    ...
}

////////////////////////////////////////////////////////////////////////////////////////////////////

例子一:


package main

import (
    "fmt"
    "reflect"
)

type User struct {
    Id   int
    Name string
    Age  int
}

type Manager struct {
    User  //反射会将匿名字段作为一个独立字段来处理
    Title string
}


func main() {
    
    m := Manager{User: User{1, "Jack", 12}, Title: "123"}
    t := reflect.TypeOf(m)
    fmt.Printf("%#v\n", t.Field(0))                   //#号会将reflect的struct的详情页打印出来,可以看出来这是一个匿名字段
    fmt.Printf("%#v \n", t.Field(1))
    fmt.Printf("%#v \n", t.FieldByIndex([]int{0, 0}))
    fmt.Printf("%#v \n", t.FieldByIndex([]int{0, 1}))
    fmt.Printf("%#v \n", t.FieldByIndex([]int{0, 2}))
  
    v := reflect.ValueOf(m)
    fmt.Printf("%v\n", v.Field(0))
    fmt.Printf("%v\n", v.FieldByIndex([]int{0, 0}))
    fmt.Printf("%v\n", v.FieldByIndex([]int{0, 1}))
    fmt.Printf("%v\n", v.FieldByIndex([]int{0, 2}))
    fmt.Printf("%v\n", v.Field(1))
    
    
}

例子二:


package main

import (
    "fmt"
    "reflect"
)
type MyInt int
type Users struct {
    Id   int
    Name string
    Age  MyInt
}

func (u Users) ReflectCallFunc() {
    fmt.Println("Hello World")
}

func main() {
    user := Users{1, "Allen.Wu", 25}
    ShowUserInfo(user)
    SetUserName(&user)
    ShowUserInfo(&user)



}

func ShowUserInfo(input interface{}) {


    getType := reflect.TypeOf(input)
    getValue := reflect.ValueOf(input)
    if getValue.Kind() == reflect.Ptr {
        getValue = getValue.Elem()
        getType = getType.Elem()
    }

    fmt.Println("reflect.Type :", getType)
    fmt.Println("reflect.name :", getType.Name())
    fmt.Println("reflect.Type :", getType.Kind())
    fmt.Println("get all Fields is:", getValue)
    fmt.Println("reflect.value:", getValue.String())
    for i := 0; i < getValue.NumField(); i++ {
        field := getType.Field(i)
        value := getValue.Field(i)
        fmt.Printf("%s: %v = %v\n", field.Name, field.Type, value.Interface())
        fmt.Println( "field canset()",value.CanSet())
    }
    // 获取方法
    // 1. 先获取interface的reflect.Type,然后通过.NumMethod进行遍历
    for i := 0; i < getType.NumMethod(); i++ {
        m := getType.Method(i)
        fmt.Printf("%s: %v\n", m.Name, m.Type)
    }

}


func SetUserName(input interface{}){
    v := reflect.ValueOf(input)
    if v.Kind() == reflect.Ptr && !v.Elem().CanSet() {
        fmt.Println("can't hava permission")
        return
    } else {
        v = v.Elem()
    }
    f := v.FieldByName("Name")
    if !f.IsValid() {
        fmt.Println("没有这个字段")
    }
    if f.Kind() == reflect.String {
        f.SetString("jACK")
    }

    for i := 0; i < v.NumField(); i++ {

        value := v.Field(i)
        vtype := v.Type().Field(i)
        if  vtype.Name ==  "Id"  {
            value.SetInt(33);
        }
        if vtype.Name ==  "Age" {
            value.SetInt(13);
        }
    }

}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:YuWenHaiBo

查看原文:golang 中的Interface 和 反射

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

648 次点击  ∙  1 赞  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传