この記事では主に Golang でのリフレクションについて説明し、皆さんについて新たな理解を得ることができれば幸いです。
Go 言語を一定期間使用している人は多く、中には 1 ~ 2 年使用している人もいますが、反映についてはまだ曖昧です。 Go言語. 、私は自分の心にあまり自信がありません。 [関連する推奨事項: Go ビデオ チュートリアル 、プログラミング教育 ]
さらに、リフレクションはほとんど使用されません。もちろん、それ自体に問題はありません。当然のことながら、最もシンプルで、最も効率的で、スケーラブルで、パフォーマンスの良い方法で処理するのが最も良い方法です。高度な使用法を機械的にコピーする必要はありません。結局のところ、仕事は私たちの実験場ではありません。実際に行って実験することができます。自分で、 this リフレクションの遊び方を詳しく見てみましょう
この記事では次の 5 つの側面から説明します
- リフレクションとは
- #リフレクションのルール
- ##リフレクションの原則
- 概要
- リフレクションとは何かを簡単に見てみる
簡単に言うと、リフレクションとは、次のことにアクセスする機能です。プログラムの実行中にプログラム自体を変更する
たとえば、プログラムの実行中に、プログラムのフィールド名とフィールド値を変更したり、プログラムにインターフェイスのアクセス情報を提供したりすることもできます。これは Go 言語で提供されるメカニズムです。言語のパブリック ライブラリでの Reflect の使用については多くのことがわかります。
たとえば、一般的に使用される fmt パッケージでは、一般的に使用される
json シリアル化と逆シリアル化、当然、先ほど述べた gorm ライブラリもリフレクションを使用します
しかし、なぜ一般的に「リフレクションはどうですか?」を使用するのでしょうか?
リフレクションの機能によると、当然のことですが、提供するインターフェイスでは受信データ型がわからないため、特定のデータ型はプログラムの実行中にのみわかります
しかし、コーディング時には、プログラムの実行時に渡された型が何であるかを検証し (json のシリアル化など)、この特定のデータを操作したいとも考えています。このとき、リフレクションの機能を使用する必要がありますリフレクションが使用されている場所では、インターフェイス{}
が表示されるのは驚くことではありませんか?受信データ型が何になるかわからないからこそ、インターフェースとして設計しました。{}。インターフェースの特徴や使い方がわからない場合は、過去の記事を確認してください。 . :
インターフェースについて注意すべき点は何ですか?{} #インターフェースについて注意すべき点は何ですか?{}次まず、反省の 3 つの重要な法則に注意してください。ルールを理解した後、私たちはルールに従います プレーする際には問題はありません
, ルールを知らずに常に条項を発動した場合にのみ、奇妙な問題が発生します##反省することができますインターフェイスの変更に使用されます。 Type 変数はリフレクション タイプのオブジェクトに変換されます。
- Reflection は、リフレクション タイプのオブジェクトをインターフェイス タイプの変数に変換できます。実行時に変更するリフレクション タイプのオブジェクト。次に、このオブジェクトに対応する値が書き込み可能である必要があります。
- 上記の 3 つのルールも比較的理解しやすいものです。前に説明した安全でないパッケージ内のポインタをまだ覚えていますか?
- 一般的に使用されるデータ型をパッケージ内の指定されたデータ型 (安全でないパッケージやリフレクト パッケージなど) に変換し、パッケージ内のルールに従ってデータを変更します
まったく同等そのため、ベストを変更することで、さまざまな操作を行うことができます。
ユースケースに注意して柔軟に使用してください一般的には、最初に基本的なアプリケーションを学び、次に、その原則を学び、なぜこの方法で使用できるのかを学び、ゆっくりとより深く理解していきます。
法則 1 については、インターフェース型変数をリフレクション型オブジェクトに変換します実際 ここで説明したインターフェイス タイプの変数については、int、float、string、map、slice、struct などの任意のデータ タイプの変数を渡すことができます。
リフレクション タイプ オブジェクトは、ここでは、reflect リフレクション パッケージの reflect.Type
および reflect.Value
オブジェクトとして理解できます。これらは、で提供される TypeOf# を通じて使用できます。 ## および ValueOf 関数は
reflect.Type は実際にはインターフェースであり、実装する必要があるさまざまなインターフェースが含まれています)。 Type 関連情報
reflect.Type のすべてのメソッドが表示されます。その中には、
- green があります。はすべてのデータです。型はすべて呼び出し可能です。
- 赤いものは、呼び出し可能な関数型のデータです。
- Black
- は、Map、配列 Array、チャネル Chan、ポインタ Ptr、またはスライス Slice です。
- 青色の
- は、実行できる # です。
- はチャネル タイプの呼び出し
reflect.Value
type Value struct { typ *rtype ptr unsafe.Pointer flag }
参照unsafe.Pointer はこちら ご存知ですか? 最下位層は自然に
unsafe.Pointer を uintptr に変換し、そのデータを変更してから元に戻すことができます。 、次の記事を確認できます:
func main() { var demoStr string = "now reflect" fmt.Println("type:", reflect.TypeOf(demoStr)) fmt.Println("value:", reflect.ValueOf(demoStr)) }
法律の場合 2 番目、リフレクション型オブジェクトをインターフェイス型変数に変換します
reflect であるため、
reflect.Value 型を特定のデータ型に変換できます。対応する # があります。 ##typ *rtype および
ptr unsafe.Pointer in Value
. たとえば、reflect.Value
オブジェクトのインターフェイスを渡すことができます。 () に対処するメソッド
#
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) }
最初に、デモ コードでは、
と
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 オブジェクトの
を呼び出して、書き込み可能かどうかを確認できます。書き込み可能であれば、再度書き込みます。書き込み可能でない場合は、書き込みを行わないでください。そうしないとパニックになります
reflect.Value で特定のデータ ポインタを見つける必要があります。そうすれば、それを変更できます。
的
Elemメソッドもう少し複雑なもの
上記のケースを見てみればそう感じるかもしれません 簡単なケースはデモするまでは大丈夫ですが、仕事で使うとすぐにクラッシュしてしまいます 当然まだ完全には理解されていません。うまく消化されていません。これは仕事からの別の例です。
#A 構造体にはマップが含まれており、マップ内のキーは文字列で、値は []文字列## です。
#要件は、構造内の趣味フィールドに対応するマップ キーの ## 番目のスライス (sport
##1- 要素) にアクセスし、それらを
- に変更することです。 hellolworld
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) }
可以看到上述案例运行之后有时可以运行成功,有时会出现 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 中国語 Web サイトの他の関連記事を参照してください。

解决Java反射异常(ReflectiveOperationException)的方法在Java开发中,反射(Reflection)是一种强大的机制,它允许程序在运行时动态地获取和操作类、对象、方法和属性等。通过反射,我们可以实现一些灵活的功能,比如动态创建对象、调用私有方法、获取类的注解等。然而,使用反射也会带来一些潜在的风险和问题,其中之一就是反射异常(

Golang函数的反射和类型断言的应用和底层实现在Golang编程中,函数的反射和类型断言是两个非常重要的概念。函数的反射可以让我们在运行时动态的调用函数,而类型断言则可以帮助我们在处理接口类型时进行类型转换操作。本文将深入讨论这两个概念的应用以及他们的底层实现原理。一、函数的反射函数的反射是指在程序运行时获取函数的具体信息,比如函数名、参数个数、参数类型等

如何在Java中使用反射调用方法反射是Java语言的一个重要特性,它可以在运行时动态地获取类的信息并操作类的成员,包括字段、方法和构造函数等。使用反射可以在编译时不知道具体类的情况下操作类的成员,这使得我们能够编写更加灵活和通用的代码。本文将介绍如何在Java中使用反射调用方法,并给出具体的代码示例。一、获取类的Class对象在Java中,要使用反射来调用方

Go语言作为一门静态类型语言,在代码编写时需要明确每个变量的类型。但是,在某些情况下,我们需要对程序中的类型进行动态的分析和操作,这时就需要用到反射机制。反射机制可以在程序运行时动态地获取程序对象的类型信息,并能够对其进行分析和操作,非常有用。但是,Go语言中反射机制也存在一些局限性,下面我们来详细了解一下。反射机制对性能的影响使用反射机制可以大大增强代

Python是一种灵活的编程语言,为开发人员提供了广泛的功能和工具。其强大的功能包括元编程——一种先进的技术,使开发人员能够在运行时动态地操作和生成代码。在本文中,我们将踏上高级Python元编程领域的旅程,特别关注动态代码生成和反射。通过采用这些技术,开发人员可以创建能够适应、修改甚至自省的代码,从而为创建灵活高效的应用程序开启了新的可能性世界。通过探索Python中动态代码生成和反射的概念和实际应用,我们将揭示元编程如何彻底改变开发过程,使开发人员能够生成健壮且高度适应性的代码。了解元编程元

Java是一种面向对象的编程语言,代码在编译后不直接变成机器语言,而是转化为字节码。字节码是Java虚拟机(JVM)可以理解的一种二进制形式。因此,在JVM上运行的程序可以在任何平台上运行,这就是Java的跨平台性。Java字节码的特征Java字节码是一种中间代码。编译器将Java源代码转换为字节码并存储在.class文件中。字节码指令可以轻松地转换为指示任

Java底层技术解读:如何实现反射与动态代理引言:Java是一种面向对象的编程语言,在开发过程中,我们经常需要使用到一些底层技术,比如反射和动态代理。本文将介绍反射和动态代理的原理,并给出具体的代码示例,帮助读者更好地理解和运用这两个底层技术。一、反射(Reflection)的原理反射是Java中一种强大而灵活的特性,它使得我们可以在运行时动态地获取和操作一

掌握Go语言的反射和元编程技术简介:随着计算机科技的不断发展,我们对于编程语言的要求也越来越高。Go语言作为一门现代化的编程语言,其简洁性、高效性和可靠性都受到广大开发者的认可。Go语言不仅提供了丰富的标准库,还支持强大的反射(reflection)和元编程(metaprogramming)技术,使得我们能够在运行时动态地获取和操作程序的结构信息。掌握Go语


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

ホットトピック



