reflect.Value
객체의 CanSet
를 호출하여 쓰기 가능한지 확인할 수 있습니다. 즉, 다시 쓰자. 쓸 수 없으면 쓰지 마세요. 그렇지 않으면 패닉 상태가 됩니다🎜🎜

reflect.Value
의 특정 데이터 포인터는 약간 더 복잡한 경우 reflect.Value
의 🎜Elem🎜 메서드를 사용할 수 있습니다. , 이렇게 단순한 경우라고 생각하실 수도 있고, 시연만 하면 괜찮겠지만, 직장에서 사용하면 바로 크래쉬가 납니다. 당연히 아직 완전히 이해되지는 않았습니다. 잘 소화되지 않았습니다. 작업에 대한 또 다른 예가 있습니다🎜🎜🎜구조에는 맵이 있고 맵의 키는 문자열이며 값은 []string🎜🎜🎜🎜입니다. 요구 사항은 🎜1🎜번째에 액세스하는 것입니다. 맵 키 🎜sport🎜를 사용하여 구조에서 취미 분야에 해당하는 슬라이스 요소를 추가하고 🎜 hellolworld🎜🎜🎜rrreee🎜🎜🎜로 수정합니다.可以看到上述案例运行之后有时可以运行成功,有时会出现 panic 的情况,相信细心的 xdm 就可以看出来,是因为 map 中的 key 是 无序的导致的,此处也提醒一波,使用 map 的时候要注意这一点
看上述代码,是不是就能够明白咱们使用反射去找到对应的数据类型,然后按照数据类型进行处理数据的过程了呢
有需要的话,可以慢慢的去熟练反射包中涉及的函数,重点是要了解其三个规则,对象转换方式,访问方式,以及数据修改方式
反射原理
那么通过上述案例,可以知道关于反射中数据类型和数据指针对应的值是相当重要的,不同的数据类型能够用哪些函数这个需要注意,否则用错直接就会 panic
TypeOf" >법칙 3의 경우 반사 유형 객체를 수정하세요🎜🎜먼저 살펴보겠습니다 책의 데모 코드에서 🎜TypeOf🎜 및 🎜ValueOf🎜에 전달된 변수는 실제로 복사본이므로 리플렉션 유형 개체에서 해당 값을 수정하려면 특정 변수의 주소를 가져온 다음 수정해야 합니다. 🎜이 변수는 쓰기 가능하다는 전제가 있습니다🎜🎜🎜예제를 보면 알 수 있습니다🎜rrreee🎜
🎜🎜먼저 reflect.Value
객체의 CanSet
를 호출하여 쓰기 가능한지 확인할 수 있습니다. 즉, 다시 쓰자. 쓸 수 없으면 쓰지 마세요. 그렇지 않으면 패닉 상태가 됩니다🎜🎜
🎜🎜그럼 전달된 변수의 주소를 수정할 수 있다는 건가요? ? 🎜🎜
🎜🎜들어오는 주소가 있습니다 아이디어에는 문제가 없지만 값을 설정하는 방식에 문제가 있으므로 위에서 언급한 패닉 상황도 발생하게 됩니다. 여기서 잘 살펴보면 반영된 객체 v가 당연히 수정 불가능하다는 것을 알 수 있습니다. reflect.Value
의 특정 데이터 포인터는 약간 더 복잡한 경우 reflect.Value
의 🎜Elem🎜 메서드를 사용할 수 있습니다. , 이렇게 단순한 경우라고 생각하실 수도 있고, 시연만 하면 괜찮겠지만, 직장에서 사용하면 바로 크래쉬가 납니다. 당연히 아직 완전히 이해되지는 않았습니다. 잘 소화되지 않았습니다. 작업에 대한 또 다른 예가 있습니다🎜🎜🎜구조에는 맵이 있고 맵의 키는 문자열이며 값은 []string🎜🎜🎜🎜입니다. 요구 사항은 🎜1🎜번째에 액세스하는 것입니다. 맵 키 🎜sport🎜를 사용하여 구조에서 취미 분야에 해당하는 슬라이스 요소를 추가하고 🎜 hellolworld🎜🎜🎜rrreee🎜🎜🎜로 수정합니다.
可以看到上述案例运行之后有时可以运行成功,有时会出现 panic 的情况,相信细心的 xdm 就可以看出来,是因为 map 中的 key 是 无序的导致的,此处也提醒一波,使用 map 的时候要注意这一点
看上述代码,是不是就能够明白咱们使用反射去找到对应的数据类型,然后按照数据类型进行处理数据的过程了呢
有需要的话,可以慢慢的去熟练反射包中涉及的函数,重点是要了解其三个规则,对象转换方式,访问方式,以及数据修改方式
反射原理
那么通过上述案例,可以知道关于反射中数据类型和数据指针对应的值是相当重要的,不同的数据类型能够用哪些函数这个需要注意,否则用错直接就会 panic
TypeOf
Golang의 리플렉션을 자세히 설명하는 기사
이 글에서는 당신에 대한 새로운 이해를 얻기 위해 GolangMedium Reflection에 대해 주로 이야기할 것입니다.
많은 사람들이 Go 언어를 일정 기간 사용해왔고, 심지어 1~2년 정도 사용한 사람도 있지만, 여전히 Go 언어에 대한 성찰에 대해 모호하고 자신감이 별로 없습니다. 그것을 사용할 때. [관련 권장사항: Go 비디오 튜토리얼, 프로그래밍 교육]
게다가 반사도 거의 사용하지 않습니다. 물론 직장에서 사용하는 것이 가장 간단하고 효율적입니다. 확장 가능하고 성능이 좋습니다. 일부 고급 사용법을 기계적으로 복사할 필요가 없습니다. 우리는 많은 것을 실험할 수 있습니다. 이번에는 성찰 놀이 방법에 대해 자세히 살펴보겠습니다
기사
- 다음 다섯 가지 측면에서 성찰이란 무엇입니까?
- 성찰의 규칙
- 사용 사례 및 유연한 적용
- Reflection 원리
- Summary
간단히 말하면, Reflection은
간단히 말해서, Reflection은 프로그램이 실행되는 동안 프로그램 자체에 액세스하고 수정하는 기능입니다. 예를 들어 프로그램이 실행 중일 때 프로그램의 필드 이름과 필드 값을 수정할 수 있으며, 프로그램 정보 등에 대한 인터페이스 액세스를 제공할 수도 있습니다.
이것은 Go 언어에서 제공되는 메커니즘입니다. . Go 언어 공용 라이브러리에서 Reflect의 사용에 대해 많이 볼 수 있습니다.
예를 들어 일반적으로 사용되는 fmt 패키지, commonly Used json 시퀀스 물론 앞서 언급한 gorm 라이브러리에서도 Reflection을 사용합니다. 그런데 왜 우리는 일반적으로 리플렉션을 사용합니까?
반사 능력을 바탕으로 당연히 우리가 제공하는 인터페이스는 들어오는 데이터 유형이 무엇인지 모르기 때문에 특정 데이터 유형은 프로그램이 실행될 때만 알 수 있습니다
그래서 사용하려면
어디에 반영되나요? 들어오는 데이터 유형이 무엇인지 확실하지 않기 때문에 이를 인터페이스로 설계했습니다{}. 인터페이스의 특성과 사용법에 대해 잘 모르는 경우 다음 기사를 확인하세요.
인터페이스{}에 관해 어떤 점에 주의해야 합니까?
인터페이스{}에 관해 어떤 점에 주의해야 합니까? 다음으로
- 먼저 세 가지 중요한 반성의 법칙에 주의하세요.
- 규칙에 따라 플레이하면 문제가 없을 것입니다 . 우리는 규칙을 모릅니다. 항상 절이 트리거되면 이상한 문제가 발생합니다
Reflection은 인터페이스 유형 변수를 반사 유형 객체로 변환할 수 있습니다
Reflection은 반사 유형 객체를 인터페이스 유형 변수로 변환할 수 있습니다We 만약 당신이 런타임에 리플렉션 유형 개체를 수정하려면 이 개체에 해당하는 값을 쓸 수 있어야 합니다. 위의 세 가지 규칙도 비교적 이해하기 쉽습니다.
우리는 일반적으로 사용하는 데이터 유형을 패키지(예: 안전하지 않은 패키지 또는 반영 패키지)의 지정된 데이터 유형으로 변환한 다음 패키지의 규칙에 따라 데이터를 수정합니다- 조끼를 바꾸는 것과 동일하며 다음과 같은 작업을 수행할 수 있습니다. do it 다양한 조작 사용 사례에 주의하고 유연하게 사용하세요
- 일반적으로 먼저 기본 응용 프로그램을 이해한 다음 그 원리와 왜 이런 식으로 사용될 수 있는지 연구하고 천천히 이해하게 됩니다. 더 깊이
법칙 1의 경우 인터페이스 유형 변수를 반사 유형 객체로 변환합니다
실제로 여기에 언급된 인터페이스 유형 변수의 경우etc.
와 같은 모든 데이터 유형의 변수를 전달할 수 있습니다.Reflection 유형 객체는 여기서 제공되는 reflect.Type
和 reflect.Value
对象,可以通过 reflect 包中提供的 TypeOf 和 ValueOf 函数得到
其中 reflect.Type
实际上是一个 interface ,他里面包含了各种接口需要进行实现,它里面提供了关于类型相关的信息
其中如下图可以查看到 reflect.Type
的所有方法,其中
- 绿色的 是所有数据类型都是可以调用的
- 红色的是 函数类型数据可以调用的
- 黑色的是 Map,数组 Array,通道 Chan,指针 Ptr 或者 切片Slice 可以调用的
- 蓝色的是结构体调用的
- 黄色的是通道 channel 类型调用的
reflect.Value
实际上是一个 struct,根据这个 struct 还关联了一组方法,这里面存放了数据类型和具体的数据,通过查看其数据结构就可以看出
type Value struct { typ *rtype ptr unsafe.Pointer flag }
看到此处的 unsafe.Pointer 是不是很熟悉,底层自然就可以将 unsafe.Pointer
转换成 uintptr
,然后再修改其数据后,再转换回来,对于 Go 指针不太熟悉的可以查看这篇文章:
写一个简单的 demo 就可以简单的获取到变量的数据类型和值
func main() { var demoStr string = "now reflect" fmt.Println("type:", reflect.TypeOf(demoStr)) fmt.Println("value:", reflect.ValueOf(demoStr)) }
对于定律二,将 反射类型的对象 转换成 接口类型的变量
我们可以通过将 reflect.Value
类型转换成我们具体的数据类型,因为 reflect.Value
中有对应的 typ *rtype
以及 ptr unsafe.Pointer
例如我们可以 通过 reflect.Value
对象的 interface() 方法来处理
func main() { var demoStr string = "now reflect" fmt.Println("type:", reflect.TypeOf(demoStr)) fmt.Println("value:", reflect.ValueOf(demoStr)) var res string res = reflect.ValueOf(demoStr).Interface().(string) fmt.Println("res == ",res) }
对于定律三,修改反射类型的对象
首先我们看上书的 demo 代码,传入 TypeOf 和 ValueOf 的变量实际上也是一个拷贝,那么如果期望在反射类型的对象中修改其值,那么就需要拿到具体变量的地址然后再进行修改,前提是这个变量是可写的
举个例子你就能明白
func main() { var demoStr string = "now reflect" v := reflect.ValueOf(demoStr) fmt.Println("is canset ", v.CanSet()) //v.SetString("hello world") // 会panic }
可以先调用 reflect.Value
对象的 CanSet
查看是否可写,如果是可写的,我们再写,如果不可写就不要写了,否则会 panic
那么传入变量的地址就可以修改了??
传入地址的思路没有毛病,但是我们去设置值的方式有问题,因此也会出现上述的 panic 情况
此处仔细看能够明白,反射的对象 v 自然是不可修改的,我们应该找到 reflect.Value
里面具体具体的数据指针,那么才是可以修改的,可以使用 reflect.Value
TypeOf 및 를 통해 액세스할 수 있는 Reflect 패키지의 reflect.Type
및 Reflect.Value
객체로 이해될 수 있습니다. Reflect 패키지에서 ValueOf
여기서
reflect.Type
은 실제로 구현해야 하는 다양한 인터페이스가 포함된 인터페이스이며 볼 수 있는 유형
에 대한 정보를 제공합니다. 아래와 같이 reflect.Type
의 모든 메소드에
green
은 모든 데이터 타입을 호출할 수 있으며- red
- 함수 타입 데이터를 호출할 수 있습니다 검은색은 Map, array Array, 채널 Chan, 포인터 Ptr 또는 슬라이스라고 할 수 있는 슬라이스

Reflect.Value
는 실제로 구조체입니다. 이 구조체에 따르면 데이터 유형과 특정 데이터를 저장하는 메서드 집합도 연결되어 있습니다. 데이터 구조를 보면 알 수 있습니다🎜type RDemo struct { Name string Age int Money float32 Hobby map[string][]string } func main() { tmp := &RDemo{ Name: "xiaomiong", Age: 18, Money: 25.6, Hobby: map[string][]string{ "sport": {"basketball", "football"}, "food": {"beef"}, }, } v := reflect.ValueOf(tmp).Elem() // 拿到结构体对象 h := v.FieldByName("Hobby") // 拿到 Hobby 对象 h1 := h.MapKeys()[0] // 拿到 Hobby 的第 0 个key fmt.Println("key1 name == ",h1.Interface().(string)) sli := h.MapIndex(h1) // 拿到 Hobby 的第 0 个key对应的对象 str := sli.Index(1) // 拿到切片的第 1 个对象 fmt.Println(str.CanSet()) str.SetString("helloworld") fmt.Println("tmp == ",tmp) }
unsafe.Pointer
를 uintptr
로 변환한 다음 해당 데이터를 수정하고 다시 변환할 수 있습니다. not 너무 익숙하다면 다음 기사를 확인해 보세요: 🎜🎜🎜GO의 포인터? 🎜🎜🎜변수의 데이터 유형과 값을 쉽게 얻을 수 있는 간단한 데모를 작성하세요🎜// rtype must be kept in sync with ../runtime/type.go:/^type._type. type rtype struct { size uintptr ptrdata uintptr hash uint32 tflag tflag align uint8 fieldAlign uint8 kind uint8 equal func(unsafe.Pointer, unsafe.Pointer) bool gcdata *byte str nameOff ptrToThis typeOff }

🎜법칙 2의 경우 반사 유형 객체를 인터페이스 유형 변수로 변환🎜🎜 🎜우리는 reflect.Value
유형을 특정 데이터 유형에 입력하세요. reflect.Value
및 ptr unsafe에 해당 <code>typ *rtype
이 있기 때문입니다. 포인터🎜🎜예를 들어 reflect.Value
객체🎜🎜
🎜// emptyInterface is the header for an interface{} value.type emptyInterface struct {
typ *rtype
word unsafe.Pointer
}复制代码
로그인 후 복사로그인 후 복사🎜
🎜법칙 3의 경우 반사 유형 객체를 수정하세요🎜🎜먼저 살펴보겠습니다 책의 데모 코드에서 🎜TypeOf🎜 및 🎜ValueOf🎜에 전달된 변수는 실제로 복사본이므로 리플렉션 유형 개체에서 해당 값을 수정하려면 특정 변수의 주소를 가져온 다음 수정해야 합니다. 🎜이 변수는 쓰기 가능하다는 전제가 있습니다🎜🎜🎜예제를 보면 알 수 있습니다🎜rrreee🎜
🎜🎜먼저 reflect.Value
객체의 CanSet
를 호출하여 쓰기 가능한지 확인할 수 있습니다. 즉, 다시 쓰자. 쓸 수 없으면 쓰지 마세요. 그렇지 않으면 패닉 상태가 됩니다🎜🎜
🎜🎜그럼 전달된 변수의 주소를 수정할 수 있다는 건가요? ? 🎜🎜
🎜🎜들어오는 주소가 있습니다 아이디어에는 문제가 없지만 값을 설정하는 방식에 문제가 있으므로 위에서 언급한 패닉 상황도 발생하게 됩니다. 여기서 잘 살펴보면 반영된 객체 v가 당연히 수정 불가능하다는 것을 알 수 있습니다. reflect.Value
의 특정 데이터 포인터는 약간 더 복잡한 경우 reflect.Value
의 🎜Elem🎜 메서드를 사용할 수 있습니다. , 이렇게 단순한 경우라고 생각하실 수도 있고, 시연만 하면 괜찮겠지만, 직장에서 사용하면 바로 크래쉬가 납니다. 당연히 아직 완전히 이해되지는 않았습니다. 잘 소화되지 않았습니다. 작업에 대한 또 다른 예가 있습니다🎜🎜🎜구조에는 맵이 있고 맵의 키는 문자열이며 값은 []string🎜🎜🎜🎜입니다. 요구 사항은 🎜1🎜번째에 액세스하는 것입니다. 맵 키 🎜sport🎜를 사용하여 구조에서 취미 분야에 해당하는 슬라이스 요소를 추가하고 🎜 hellolworld🎜🎜🎜rrreee🎜🎜🎜로 수정합니다.
// emptyInterface is the header for an interface{} value.type emptyInterface struct { typ *rtype word unsafe.Pointer }复制代码
reflect.Value
객체의 CanSet
를 호출하여 쓰기 가능한지 확인할 수 있습니다. 즉, 다시 쓰자. 쓸 수 없으면 쓰지 마세요. 그렇지 않으면 패닉 상태가 됩니다🎜🎜

reflect.Value
의 특정 데이터 포인터는 약간 더 복잡한 경우 reflect.Value
의 🎜Elem🎜 메서드를 사용할 수 있습니다. , 이렇게 단순한 경우라고 생각하실 수도 있고, 시연만 하면 괜찮겠지만, 직장에서 사용하면 바로 크래쉬가 납니다. 당연히 아직 완전히 이해되지는 않았습니다. 잘 소화되지 않았습니다. 작업에 대한 또 다른 예가 있습니다🎜🎜🎜구조에는 맵이 있고 맵의 키는 문자열이며 값은 []string🎜🎜🎜🎜입니다. 요구 사항은 🎜1🎜번째에 액세스하는 것입니다. 맵 키 🎜sport🎜를 사용하여 구조에서 취미 분야에 해당하는 슬라이스 요소를 추가하고 🎜 hellolworld🎜🎜🎜rrreee🎜🎜🎜로 수정합니다.可以看到上述案例运行之后有时可以运行成功,有时会出现 panic 的情况,相信细心的 xdm 就可以看出来,是因为 map 中的 key 是 无序的导致的,此处也提醒一波,使用 map 的时候要注意这一点
看上述代码,是不是就能够明白咱们使用反射去找到对应的数据类型,然后按照数据类型进行处理数据的过程了呢
有需要的话,可以慢慢的去熟练反射包中涉及的函数,重点是要了解其三个规则,对象转换方式,访问方式,以及数据修改方式
反射原理
那么通过上述案例,可以知道关于反射中数据类型和数据指针对应的值是相当重要的,不同的数据类型能够用哪些函数这个需要注意,否则用错直接就会 panic
TypeOf
来看 TypeOf 的接口中涉及的数据结构
在 reflect 包中 rtype
是非常重要的,Go 中所有的类型都会包含这个结构,所以咱们反射可以应用起来,结构如下
// rtype must be kept in sync with ../runtime/type.go:/^type._type. type rtype struct { size uintptr ptrdata uintptr hash uint32 tflag tflag align uint8 fieldAlign uint8 kind uint8 equal func(unsafe.Pointer, unsafe.Pointer) bool gcdata *byte str nameOff ptrToThis typeOff }
其中可以看到此处的 rtype
的结构保持和 runtime/type.go
一致 ,都是关于数据类型的表示,以及对应的指针,关于这一块的说明和演示可以查看文末的 interface{} 处的内容
ValueOf
从 ValueOf 的源码中,我们可以看到,重要的是 emptyInterface 结构
// emptyInterface is the header for an interface{} value.type emptyInterface struct { typ *rtype word unsafe.Pointer }复制代码
emptyInterface 结构中有 rtype
类型的指针, word 自然是对应的数据的地址了
reflect.Value
对象中的方法也是非常的多,用起来和上述说到的 reflect.Type
接口中的功能类似
关于源码中涉及到的方法,就不再过多的赘述了,更多的还是需要自己多多实践才能体会的更好
殊不知,此处的 reflect.Value
也是可以转换成 reflect.Type
,可以查看源码中 reflect\value.go
的 func (v Value) Type() Type {
其中 reflect.Value
,reflect.Type
,和任意数据类型
可以相互这样来转换
如下图:
总结
至此,关于反射就聊到这里,一些关于源码的细节并没有详细说,更多的站在一个使用者的角度去看反射需要注意的点
关于反射,大多的人是建议少用,因为是会影响到性能,不过如果不太关注这一点,那么用起来还是非常方便的
高级功能自然也是双刃剑,你用不好就会 panic,如果你期望去使用他,那么就去更多的深入了解和一步一步的吃透他吧
大道至简,反射三定律,活学活用
更多编程相关知识,请访问:编程视频!!
위 내용은 Golang의 리플렉션을 자세히 설명하는 기사의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Go Crawler Colly의 대기열 스레딩 문제는 Colly Crawler 라이브러리를 GO 언어로 사용하는 문제를 탐구합니다. � ...

Go Language의 부동 소수점 번호 작동에 사용되는 라이브러리는 정확도를 보장하는 방법을 소개합니다.

Go Language의 문자열 인쇄의 차이 : println 및 String () 함수 사용 효과의 차이가 진행 중입니다 ...

Go Language에서 메시지 대기열을 구현하기 위해 Redisstream을 사용하는 문제는 Go Language와 Redis를 사용하는 것입니다 ...

골란드의 사용자 정의 구조 레이블이 표시되지 않으면 어떻게해야합니까? Go Language 개발을 위해 Goland를 사용할 때 많은 개발자가 사용자 정의 구조 태그를 만날 것입니다 ...

GO의 어떤 라이브러리가 대기업이나 잘 알려진 오픈 소스 프로젝트에서 개발 했습니까? GO에 프로그래밍 할 때 개발자는 종종 몇 가지 일반적인 요구를 만납니다.

GO 언어에서 구조를 정의하는 두 가지 방법 : VAR과 유형 키워드의 차이. 구조를 정의 할 때 Go Language는 종종 두 가지 다른 글쓰기 방법을 본다 : 첫째 ...

다중 프로세스 로그 쓰기에서 동시성 보안 문제를 효율적으로 처리합니다. 여러 프로세스는 동시에 동일한 로그 파일을 작성합니다. 동시성을 안전하고 효율적으로 보장하는 방법은 무엇입니까? 이것은 ...
