Golang之反射(重点!!)

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

1、反射:可以在运行时动态获取变量的相关信息

Import(“reflect”)

两个函数:

reflect.TypeOf()//获取变量的类型,返回reflect.Type类型
reflect.ValueOf()//获取变量的值,返回reflect.Value类型
reflect.Value.Kind()//获取变量的类别,返回一个常量
reflect.Value.Interface()//转换成interface{}类型

可逆状态

示例用法

package main

import (
    "fmt"
    "reflect"
)

type Student struct {
    Name  string
    Age   int
    Score float32
}

func test(b interface{}) {
    t := reflect.TypeOf(b)
    fmt.Println(t)

    v := reflect.ValueOf(b)
    k := v.Kind()
    fmt.Println(k)

    iv := v.Interface()
    stu, ok := iv.(Student)
    if ok {
        fmt.Printf("%v %T\n", stu, stu)
    }
}
func testInt(b interface{}) {
    val := reflect.ValueOf(b)
    c := val.Int()
    fmt.Printf("get value interface{} %d\n", c)
}

func main() {
    var a Student = Student{
        Name:  "stu01",
        Age:   18,
        Score: 92,
    }
    test(a)
    testInt(1234)
}
反射用法
package main

import (
    "fmt"
    "reflect"
)
func main(){
    var x float64=3.4
    fmt.Println("type:",reflect.TypeOf(x))

    v:=reflect.ValueOf(x)
    fmt.Println("value:",v)
    fmt.Println("type:",v.Type())
    fmt.Println("kind:",v.Kind())
    fmt.Println("value:",v.Float())

    fmt.Println(v.Interface())
    fmt.Printf("value is %5.2e\n",v.Interface())
    y:=v.Interface().(float64)
    fmt.Println(y)
}
反射练习

 获取变量的值

reflect.ValueOf(x).Float()
reflect.ValueOf(x).Int()
reflect.ValueOf(x).String()
reflect.ValueOf(x).Bool()

反射之elem()修改指针的方法

package main

//通过反射动态修改变量的值
import (
    "fmt"
    "reflect"
)

type Student struct {
    Name  string
    Age   int
    Score float32
}

func test(b interface{}) {
    t := reflect.TypeOf(b)
    fmt.Println(t)

    v := reflect.ValueOf(b)
    k := v.Kind()
    fmt.Println(k)

    iv := v.Interface()
    stu, ok := iv.(Student)
    if ok {
        fmt.Printf("%v %T\n", stu, stu)
    }
}

func testInt(b interface{}) {
    val := reflect.ValueOf(b)
    val.Elem().SetInt(100) //val.Elem().Setint()相当于指针操作

    c := val.Elem().Int()
    fmt.Printf("get value interface{}%d\n", c)
    fmt.Printf("string val:%d\n", val.Elem().Int())
}
func main() {
    var a Student = Student{
        Name:  "stu01",
        Age:   18,
        Score: 92,
    }
    test(a)
    var b int = 1
    b = 200
    testInt(&b)
    fmt.Println(b)
}
val.Elem().SetInt()

 用反射操作结构体

reflect.Value.NumField()获取结构体中字段的个数
reflect.Value.Method(n).Call来条用结构体中的方法

反射取得结构体方法个数,字段数

package main

//通过反射动态修改变量的值
import (
    "fmt"
    "reflect"
)

type Student struct {
    Name  string
    Age   int
    Score float32
    Sex   string
}

func (s Student) Set(name string, age int, score float32, sex string) {
    s.Name = name
    s.Age = age
    s.Score = score
    s.Sex = sex
}

func TestStruct(a interface{}) {
    val := reflect.ValueOf(a)
    kd := val.Kind()
    if kd != reflect.Struct {
        fmt.Println("expect struct")
        return
    }
    num := val.NumField()
    fmt.Printf("struct has %d fields\n", num)

    numOfMethod := val.NumMethod()
    fmt.Printf("struct has %d methods\n", numOfMethod)
}

func main() {
    var a Student
    a = Student{
        Name:  "stu01",
        Age:   18,
        Score: 92.8,
    }
    TestStruct(a)
    fmt.Println(a)
}
代码在这

 反射练习

package main

//通过反射动态修改变量的值
import (
    "fmt"
    "reflect"
)

type NotKnownType struct {
    s1 string
    s2 string
    s3 string
}

//定义一个String方法
func (n NotKnownType) String() string {
    return n.s1 + "-" + n.s2 + "-" + n.s3
}

var secret interface{} = NotKnownType{"Ada", "Go", "Oberon"}

func main() {
    value := reflect.ValueOf(secret) //<main.NotKnownType Value>
    typ := reflect.TypeOf(secret)    //main.NotKnownType
    fmt.Println(typ)
    knd := value.Kind() //struct
    fmt.Println(knd)
    for i := 0; i < value.NumField(); i++ {
        fmt.Printf("Field %d:%v\n", i, value.Field(i))
    }
    results := value.Method(0).Call(nil)
    fmt.Println(results)//[Ada-Go-Oberon]
}
反射练习

通过反射修改结构体

package main

import (
    "fmt"
    "reflect"
)

type T struct {
    A int
    B string
}

func main() {
    t := T{23, "skidoo"}
    s := reflect.ValueOf(&t).Elem()
    typeOfT := s.Type()
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        fmt.Printf("%d:%s %s=%v\n",
            i, typeOfT.Field(i).Name, f.Type(), f.Interface())
    }
    s.Field(0).SetInt(77)
    s.Field(1).SetString("Sunset Strip")
    fmt.Println("t is now", t)
}
反射修改结构体

 


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

本文来自:博客园

感谢作者:pyyu

查看原文:Golang之反射(重点!!)

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

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