美文网首页
golang reflect笔记

golang reflect笔记

作者: guonaihong | 来源:发表于2019-05-31 14:50 被阅读0次

最近有大量用到reflect,给开源项目gin贡献的pr就是这方面的技巧,也在自己的开源项目中使用了大量使用reflect简化接口开发。鉴于reflect的接口特别难用,特别容易忘记,记录下。

判断类型
// 提取类型信息到变量里
var stringSliceType = reflect.TypeOf([]string{})
var intSliceType = reflect.TypeOf([]int{})
var int32SliceType = reflect.TypeOf([]int32{})

func typeCheck(x interface{}) {
    // 提取interface{}里面的类型信息
    vt := reflect.ValueOf(x).Type()
    switch vt {
    case stringSliceType:
        fmt.Printf("[]string{}\n")
    case intSliceType:
        fmt.Printf("[]int{}\n")
    case int32SliceType:
        fmt.Printf("[]int32{}\n")
    default:
        fmt.Printf("unkown type\n")
    }   
}

func main() {
    typeCheck([]string{})
    typeCheck([]int{})
    typeCheck([]int32{})
    typeCheck(0)
}
// 输出
// []string{}
// []int{}
// []int32{}
// unkown type

判断指针类型和空指针
func checkPtrAndNil(x interface{}) {
    v := reflect.ValueOf(x)
    if v.Kind() == reflect.Ptr {
        fmt.Printf("%v is pointer\n", v.Type())
        if v.IsNil() {
            fmt.Printf("%v is is a null pointer\n", v.Type())
            return
        }

    }   

    fmt.Printf("%v is value\n", v.Type())
}

func main() {
    var ip *int
    var sp *string
    var i32p *int32

    checkPtrAndNil(ip)
    checkPtrAndNil(sp)
    checkPtrAndNil(i32p)
    checkPtrAndNil(3)
}
// 输出
// *int is pointer
// *int is is a null pointer
// *string is pointer
// *string is is a null pointer
// *int32 is pointer
// *int32 is is a null pointer
// int is value

类型空值

效果相当于var t Type

package main

import (
    "fmt"
    "reflect"
)

type test struct {
    X int 
    Y int 
}

func zeroValue(x interface{}) {
    v := reflect.Zero(reflect.ValueOf(x).Type())
    fmt.Printf("%v zero (%v)\n", x, v)
}

func main() {
    zeroValue("string")
    zeroValue(3)
    zeroValue(1.1)
    zeroValue(test{3, 4}) 
}
// 输出如下
// string zero ()
// 3 zero (0)
// 1.1 zero (0)
// {3 4} zero ({0 0})

解引用

package main

import (
    "fmt"
    "reflect"
)

func elem(x interface{}) {
    v := reflect.ValueOf(x)
    fmt.Printf("1.value type = %v\n", v.Type())
    if v.Kind() == reflect.Ptr {
        v = v.Elem()
    }

    fmt.Printf("2.value type = %v\n", v.Type())
}

func main() {
    var i int
    var f float64

    elem(&i)
    elem(&f)
}
// 输出
// 1.value type = *int
// 2.value type = int
// 1.value type = *float64
// 2.value type = float64

get interface

package main

import (
    "fmt"
    "reflect"
)

func getInterface(x interface{}) {
    x1 := reflect.ValueOf(x).Interface()
    fmt.Printf("x %v, x1 %v\n", x, x1)
}

func main() {
    getInterface(3)
}
// 输出
// x 3, x1 3

遍历结构体

package main

import (
    "fmt"
    "reflect"
)

type test2 struct {
    X1 int 
    F1 float64
}

type Test struct {
    X int 
    F float64
    test2
}

func rangeStructCore(v reflect.Value) {

    if v.Kind() == reflect.Struct {
        tValue := v.Type()

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

            if sf.PkgPath != "" && !sf.Anonymous {
                continue
            }

            if v.Field(i).Kind() == reflect.Struct {
                rangeStructCore(v.Field(i))
                continue
            }
            fmt.Printf("sf = %v: %v, %t, %v\n", sf, sf.PkgPath, sf.Anonymous, v.Field(i))
        }
    }   
}

func rangeStruct(x interface{}) {
    rangeStructCore(reflect.ValueOf(x))
}

func main() {
    rangeStruct(Test{X: 3, F: 4, test2: test2{X1: 5, F1: 6}})
}
// 输出 
// sf = {X  int  0 [0] false}: , false, 3
// sf = {F  float64  8 [1] false}: , false, 4
// sf = {X1  int  0 [0] false}: , false, 5
// sf = {F1  float64  8 [1] false}: , false, 6

利用反射修改结构体的值

package main

import (
        "fmt"
        "reflect"
)

type Test struct {
        X int
}

func modifyValue(x interface{}) {

        v := reflect.ValueOf(x)
        if v.Kind() == reflect.Ptr {
                v = v.Elem()
        }

        for i := 0; i < v.NumField(); i++ {
                //sf := v.Type().Field(i)
                sv := v.Field(i)
                //fmt.Printf("%v#%v#%t\n", sf, sv, sv.CanAddr())
                px := sv.Addr().Interface().(*int)
                *px = 4
        }
}

func main() {
        t := Test{X: 3}
        fmt.Printf("before:%#v\n", t)
        modifyValue(&t)
        fmt.Printf("after:%#v\n", t)

}
// 输出
// before:main.Test{X:3}
// after:main.Test{X:4}

相关文章

  • Golang 反射实现依赖注入

    Golang 反射实现依赖注入 Coding/Golang #Golang #Golang/reflect 依赖注...

  • golang reflect笔记

    最近有大量用到reflect,给开源项目gin贡献的pr就是这方面的技巧,也在自己的开源项目中使用了大量使用ref...

  • n2n

    reflect: https://blog.golang.org/laws-of-reflectionregexp...

  • reflect反射的实际中的应用及畅想

    原文地址[https://mojotv.cn/go/golang-reflect-string] 1. ? 解决了...

  • gorm出现reflect.Value.Addr of unad

    golang使用gorm时出现这样的错误: panic: reflect.Value.Addr of unaddr...

  • golang:reflect反射

    reflect反射 1.使用场景 当一些类型未知,有多种类型需要统一处理时,考虑使用反射来做多种情况的统一判断处理...

  • golang-reflect

    reflect 示例0 reflect示例1 reflect 示例2 通过反射修改对象属性 reflect 示例3...

  • Golang反射reflect

    reflect反射,可以通过reflect反射结构体所包含的属性和方法,然后进行一些赋值和方法的调用,灵活度比较高...

  • Golang之reflect

    前言 反射 —— 如果你之前学过一些别的语言,比如java可能就会了解,反射是一个传说中很厉害的操作,算是一个高级...

  • golang的reflect

    编程语言中反射的概念 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机...

网友评论

      本文标题:golang reflect笔记

      本文链接:https://www.haomeiwen.com/subject/sxgwtctx.html