Go 언어에는 반영이 있습니다. Go 언어는 변수의 값을 업데이트하고 확인하는 메커니즘, 변수의 호출 메서드, 변수가 런타임에 지원하는 내장 작업을 제공하지만 이러한 변수의 특정 유형은 컴파일 타임에 알려지지 않습니다. 이 메커니즘을 리플렉션이라고 합니다. Go 언어의 리플렉션은 Type과 Value라는 두 가지 중요한 유형을 정의하는 Reflect 패키지에서 지원됩니다. 리플렉션의 모든 인터페이스 값은 Reflect.Type과 Reflect.Value의 두 부분으로 구성되는 것으로 이해될 수 있습니다.
이 튜토리얼의 운영 환경: 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()) }
실행 결과는 다음과 같습니다.
코드 설명은 다음과 같습니다.
라인 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()) }
运行结果如下:
代码说明如下:
第 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()) }
运行结果如下:
代码说明如下:
第 13 行,创建了 cat 结构体的实例,ins 是一个 *cat 类型的指针变量。
第 15 行,对指针变量获取反射类型信息。
第 17 行,输出指针变量的类型名称和种类。Go语言的反射中对所有指针变量的种类都是 Ptr,但需要注意的是,指针变量的类型名称是空,不是 *cat。
第 19 行,取指针类型的元素类型,也就是 cat 类型。这个操作不可逆,不可以通过一个非指针类型获取它的指针类型。
第 21 行,输出指针变量指向元素的类型名称和种类,得到了 cat 的类型名称(cat)和种类(struct)。
【相关推荐:Go视频教程】
위 내용은 Go 언어에는 반영이 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!