摘要:今天我们来学习一下 golang 中的反射,这个是 golang 语言中的一大利器。

什么是反射

  Go 语言提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制 --《Go 语言圣经》

为什么要用反射

需要使用反射的两个常见场景

  1:有时你需要编写一个函数,但是并不知道传给你的参数类型是什么,可能是没有约定好,也可能是穿入的类型很多,这些类型并不能统一表示,这个时候反射就会用得上了。

  2:有时候需要根据某些条件决定调用哪个函数,比如根据用户的输入来决定。这时就需要对函数和函数的参数进行反射,在运行期间动态的执行函数。

不使用反射的理由

  1:与反射相关的代码,经常是难于阅读的,会导致代码的可读性变差。

  2:Go 语言是一门静态语言,编译器在编译时期可以检查一些类型错误,但是对于反射代码是无能为力的,反射相关的代码通常只有运行的时候才会报错,可能会造成严重后果。

  3:反射对性能影响比较大,会比正常代码运行速度慢一到两个数量级。

反射是如何实现的

反射类型

  interface 是 Go 语言实现抽象的一个非常强大的工具。当向接口变量赋予一个实体类型的时候,接口会存储实体的类型信息,反射就是通过接口的类型信息实现的,反射建立在类型的基础上。Go 语言在 reflect 包里定义了各种类型,实现了反射的各种函数,通过它们可以在运行时检测类型的信息、改变类型的值。

  反射包中有两对非常重要的函数和类型:reflect.TypeOf 能获取类型信息, reflect.ValueOf 能获取数据的运行时表示,另外两个类型是 Type 和 Value, 它们与函数是一一对应关系。

1:Type 类型

type Type interface {
    // Methods applicable to all types.

    // Name returns the type's name within its package for a defined type.
    // For other (non-defined) types it returns the empty string.
    Name() string

    // PkgPath returns a defined type's package path, that is, the import path
    // that uniquely identifies the package, such as "encoding/base64".
    // If the type was predeclared (string, error) or not defined (*T, struct{},
    // []int, or A where A is an alias for a non-defined type), the package path
    // will be the empty string.
    PkgPath() string

    // Size returns the number of bytes needed to store
    // a value of the given type; it is analogous to unsafe.Sizeof.
    Size() uintptr

    // Kind returns the specific kind of this type.
    Kind() Kind

    // Implements reports whether the type implements the interface type u.
    Implements(u Type) bool

    // AssignableTo reports whether a value of the type is assignable to type u.
    AssignableTo(u Type) bool

    // Comparable reports whether values of this type are comparable.
    Comparable() bool

    // String returns a string representation of the type.
    // The string representation may use shortened package names
    // (e.g., base64 instead of "encoding/base64") and is not
    // guaranteed to be unique among types. To test for type identity,
    // compare the Types directly.
    String() string

    // Elem returns a type's element type.
    // It panics if the type's Kind is not Ptr.
    Elem() Type

    common() *rtype
    uncommon() *uncommonType
}
Type

相关文章: