>  기사  >  백엔드 개발  >  Go 언어에는 반영이 있나요?

Go 언어에는 반영이 있나요?

青灯夜游
青灯夜游원래의
2022-11-25 16:56:143514검색

Go 언어에는 반영이 있습니다. Go 언어는 변수의 값을 업데이트하고 확인하는 메커니즘, 변수의 호출 메서드, 변수가 런타임에 지원하는 내장 작업을 제공하지만 이러한 변수의 특정 유형은 컴파일 타임에 알려지지 않습니다. 이 메커니즘을 리플렉션이라고 합니다. Go 언어의 리플렉션은 Type과 Value라는 두 가지 중요한 유형을 정의하는 Reflect 패키지에서 지원됩니다. 리플렉션의 모든 인터페이스 값은 Reflect.Type과 Reflect.Value의 두 부분으로 구성되는 것으로 이해될 수 있습니다.

Go 언어에는 반영이 있나요?

이 튜토리얼의 운영 환경: Windows 7 시스템, GO 버전 1.18, Dell G3 컴퓨터.

Go 언어는 변수의 값을 업데이트하고 확인하는 메커니즘, 변수의 메서드 호출, 변수가 런타임에 지원하는 내장 연산을 제공하지만 이러한 변수의 특정 유형은 컴파일 타임에 알려지지 않습니다. 이 메커니즘을 리플렉션이라고 합니다. 또한 리플렉션을 사용하면 유형 자체를 일류 값 유형으로 처리할 수 있습니다.

Go 언어의 리플렉션

리플렉션은 프로그램 실행 중에 프로그램 자체에 액세스하고 수정하는 기능을 의미합니다. 프로그램이 컴파일되면 변수가 메모리 주소와 변수 이름으로 변환됩니다. 실행 부분에는 프로그램이 실행될 때 자체 정보를 얻을 수 없습니다.

리플렉션을 지원하는 언어는 프로그램 컴파일 중에 필드 이름, 유형 정보, 구조 정보 등 변수의 리플렉션 정보를 실행 파일에 통합하고 프로그램에 리플렉션 정보에 접근할 수 있는 인터페이스를 제공할 수 있습니다. , 프로그램이 실행될 수 있도록 유형 반영 정보에 대한 액세스 및 수정 기능을 제공합니다.

C/C++ 언어는 반사 기능을 지원하지 않으며 typeid를 통해 매우 약한 프로그램 런타임 유형 정보만 제공할 수 있습니다. Java 및 C#과 같은 언어는 모두 Lua 및 JavaScript와 같은 완전한 동적 언어를 지원합니다. 이를 통해 코드는 런타임에 프로그램 자체의 값과 유형 정보에 액세스할 수 있으므로 리플렉션 시스템이 필요하지 않습니다.

Go 언어 프로그램의 반영 시스템은 실행 파일 공간이나 패키지에서 모든 유형의 정보를 얻을 수 없습니다. 소스 코드 처리를 수행하려면 표준 라이브러리의 해당 어휘, 구문 분석기 및 추상 구문 트리(AST)를 사용해야 합니다. . 이 정보를 얻으려면 스캔하세요.

Go 언어는 프로그램의 리플렉션 정보에 액세스할 수 있는 Reflect 패키지를 제공합니다.

reflect 패키지

Go 언어의 Reflection은 Type과 Value라는 두 가지 중요한 유형을 정의하는 Reflect 패키지에서 지원됩니다. Reflection의 모든 인터페이스 값은 Reflection으로 이해될 수 있습니다. Type과 Reflect는 다음과 같이 구성됩니다. 두 부분으로 구성되어 있으며, Reflect 패키지는 모든 객체의 Value 및 Type을 얻기 위해 Reflect.TypeOf 및 Reflect.ValueOf라는 두 가지 함수를 제공합니다.

Reflected 유형 객체(reflect.Type)

Go 언어 프로그램에서는 Reflect.TypeOf() 함수를 사용하여 프로그램이 액세스할 수 있는 유형 객체(reflect.Type)를 얻을 수 있습니다. 다음은 해당 값의 유형 정보입니다. 다음은 유형 객체를 얻는 과정을 이해하기 위한 예입니다.

package main
import (
    "fmt"
    "reflect"
)
func main() {
    var a int
    typeOfA := reflect.TypeOf(a)
    fmt.Println(typeOfA.Name(), typeOfA.Kind())
}

실행 결과는 다음과 같습니다.

Go 언어에는 반영이 있나요?

코드 설명은 다음과 같습니다.

  • 라인 9는 int 유형의 변수를 정의합니다.

  • 10행에서는 변수 a의 유형 객체 typeOfA가 Reflect.TypeOf()를 통해 얻어지며 유형은 Reflect.Type()입니다.

  • 11번째 줄에서는 typeOfA 타입 객체의 멤버 함수를 통해 typeOfA 변수의 타입 이름을 각각 int로 얻을 수 있고, 타입(Kind)은 int이다.

Reflection의 유형과 종류

Reflection을 사용할 때는 먼저 Type과 Kind의 차이점을 이해해야 합니다. 프로그래밍에서는 가장 일반적으로 사용되는 타입이 타입이지만, 반영적으로 매우 다양한 타입을 구분해야 할 때에는 종류(Kind)를 사용합니다. 예를 들어, 포인터를 타입별로 통일적으로 판단해야 하는 경우에는 종류(Kind) 정보를 활용하는 것이 더 편리합니다.

1) 반사 유형(Kind) 정의

Go 언어 프로그램에서 유형(Type)은 int, string, bool, float32 및 기타 유형과 같은 시스템 기본 데이터 유형과 다음을 사용하여 정의된 유형을 의미합니다. type 키워드 이름이 유형 자체의 이름인 유형입니다. 예를 들어 A 유형의 struct{}를 사용하여 구조를 정의하는 경우 A는 struct{}의 유형입니다.

Kind는 Reflect 패키지에 다음과 같이 정의된 객체의 유형을 나타냅니다.

type Kind uint
const (
    Invalid Kind = iota  // 非法类型
    Bool                 // 布尔型
    Int                  // 有符号整型
    Int8                 // 有符号8位整型
    Int16                // 有符号16位整型
    Int32                // 有符号32位整型
    Int64                // 有符号64位整型
    Uint                 // 无符号整型
    Uint8                // 无符号8位整型
    Uint16               // 无符号16位整型
    Uint32               // 无符号32位整型
    Uint64               // 无符号64位整型
    Uintptr              // 指针
    Float32              // 单精度浮点数
    Float64              // 双精度浮点数
    Complex64            // 64位复数类型
    Complex128           // 128位复数类型
    Array                // 数组
    Chan                 // 通道
    Func                 // 函数
    Interface            // 接口
    Map                  // 映射
    Ptr                  // 指针
    Slice                // 切片
    String               // 字符串
    Struct               // 结构体
    UnsafePointer        // 底层指针
)

Map, Slice 및 Chan은 참조 유형으로 사용 중인 포인터와 유사하지만 유형 상수 정의에서는 여전히 독립적입니다. 카테고리는 Ptr에 속하지 않습니다. A 유형 struct{}로 정의된 구조는 Struct 유형에 속하고 *A는 Ptr에 속합니다.

2) 타입 객체에서 타입 이름과 타입을 가져옵니다.

Go 언어에서 타입 이름에 해당하는 리플렉션 획득 방법은 Reflect.Type의 Name() 메서드로, 타입 이름을 나타내는 문자열을 반환합니다. ; 해당 유형이 속함 Kind(Kind)는 Reflect.Type의 Kind() 메소드를 사용하고 Reflect.Kind 유형의 상수를 반환합니다.

下面的代码中会对常量和结构体进行类型信息获取。

package main
import (
    "fmt"
    "reflect"
)
// 定义一个Enum类型
type Enum int
const (
    Zero Enum = 0
)
func main() {
    // 声明一个空结构体
    type cat struct {
    }
    // 获取结构体实例的反射类型对象
    typeOfCat := reflect.TypeOf(cat{})
    // 显示反射类型对象的名称和种类
    fmt.Println(typeOfCat.Name(), typeOfCat.Kind())
    // 获取Zero常量的反射类型对象
    typeOfA := reflect.TypeOf(Zero)
    // 显示反射类型对象的名称和种类
    fmt.Println(typeOfA.Name(), typeOfA.Kind())
}

运行结果如下:

Go 언어에는 반영이 있나요?

代码说明如下:

  • 第 17 行,声明结构体类型 cat。

  • 第 20 行,将 cat 实例化,并且使用 reflect.TypeOf() 获取被实例化后的 cat 的反射类型对象。

  • 第 22 行,输出 cat 的类型名称和种类,类型名称就是 cat,而 cat 属于一种结构体种类,因此种类为 struct。

  • 第 24 行,Zero 是一个 Enum 类型的常量。这个 Enum 类型在第 9 行声明,第 12 行声明了常量。如没有常量也不能创建实例,通过 reflect.TypeOf() 直接获取反射类型对象。

  • 第 26 行,输出 Zero 对应的类型对象的类型名和种类。

指针与指针指向的元素

Go语言程序中对指针获取反射对象时,可以通过 reflect.Elem() 方法获取这个指针指向的元素类型,这个获取过程被称为取元素,等效于对指针类型变量做了一个*操作,代码如下:

package main
import (
    "fmt"
    "reflect"
)
func main() {
    // 声明一个空结构体
    type cat struct {
    }
    // 创建cat的实例
    ins := &cat{}
    // 获取结构体实例的反射类型对象
    typeOfCat := reflect.TypeOf(ins)
    // 显示反射类型对象的名称和种类
    fmt.Printf("name:'%v' kind:'%v'\n", typeOfCat.Name(), typeOfCat.Kind())
    // 取类型的元素
    typeOfCat = typeOfCat.Elem()
    // 显示反射类型对象的名称和种类
    fmt.Printf("element name: '%v', element kind: '%v'\n", typeOfCat.Name(), typeOfCat.Kind())
}

运行结果如下:

Go 언어에는 반영이 있나요?

代码说明如下:

  • 第 13 行,创建了 cat 结构体的实例,ins 是一个 *cat 类型的指针变量。

  • 第 15 行,对指针变量获取反射类型信息。

  • 第 17 行,输出指针变量的类型名称和种类。Go语言的反射中对所有指针变量的种类都是 Ptr,但需要注意的是,指针变量的类型名称是空,不是 *cat。

  • 第 19 行,取指针类型的元素类型,也就是 cat 类型。这个操作不可逆,不可以通过一个非指针类型获取它的指针类型。

  • 第 21 行,输出指针变量指向元素的类型名称和种类,得到了 cat 的类型名称(cat)和种类(struct)。

【相关推荐:Go视频教程

위 내용은 Go 언어에는 반영이 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.