この記事では主に 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 サイトの他の関連記事を参照してください。

GO言語で文字列パッケージをマスターすると、テキスト処理機能と開発効率が向上します。 1)コンテナ機能を使用してサブストリングを確認し、2)インデックス関数を使用してサブストリング位置を見つけ、3)関数を効率的にスプライスストリングスライス、4)機能を置き換えてサブストリングを置き換えます。空の文字列や大きな文字列操作のパフォーマンスの問題をチェックしないなど、一般的なエラーを避けるように注意してください。

文字列の操作を簡素化し、コードをより明確かつ効率的にすることができるため、GOの文字列パッケージを気にする必要があります。 1)文字列を使用して、弦を効率的にスプライスするために参加します。 2)文字列を使用して、空白の文字で文字列を分割します。 3)文字列を介してサブストリング位置を見つけます。Indexと文字列lastindex; 4)文字列を使用して、文字列を置き換える。 5)文字列を使用して、ビルダーを効率的にスプライスします。 6)予期しない結果を避けるために、常に入力を確認してください。

theStringspackageIngoisESSENTINEFOREFFSTRINGMANIPULATION.1)ITOFFERSSSIMPLEYETPOWERFULFUNCTIONS FORTOSSCHECKINGSUBSTRINGSNINGSTRINGS.2)ITHANDLESUNICODEWELL、ITHANDLESUNICODEWELL

whendeciding botedego'sbytespackageandstringspackage、usebytes.bufferbinarydataandstrings.builderforstringoperations.1)usebytes.bufferforkithbyteslices、binarydata、appendingdatatypes、およびwritioio.writioio.writioio.writioio.writioio.

Goの文字列パッケージは、さまざまな文字列操作機能を提供します。 1)文字列を使用して、サブストリングを確認します。 2)文字列を使用して、ストリングをサブストリングスライスに分割します。 3)文字列を通して文字列をマージします。 4)文字列または文字列を使用して、文字列の最初と端でブランクまたは指定された文字を削除します。 5)指定されたすべてのサブストリングを文字列に置き換えます。ReplaceAll。 6)文字列を使用して、hasprefixまたは文字列hassuffixを使用して、文字列の接頭辞または接尾辞を確認します。

GO言語文字列パッケージを使用すると、コードの品質が向上します。 1)文字列を使用して()join()を使用して、パフォーマンスのオーバーヘッドを避けるために、文字列アレイをエレガントに接続します。 2)strings.split()とstrings.contains()を組み合わせて、テキストを処理し、ケースの感度の問題に注意を払います。 3)文字列の乱用を避け、replace()を回避し、多数の置換に正規表現を使用することを検討します。 4)文字列を使用して、ビルダーを使用して、頻繁にスプライシング文字列の性能を向上させます。

GoのBYTESパッケージは、バイトスライスを処理するためのさまざまな実用的な機能を提供します。 1.bites.containsは、バイトスライスに特定のシーケンスが含まれているかどうかを確認するために使用されます。 2.bites.splitは、バイトスライスをスモールピースに分割するために使用されます。 3.bites.joinは、複数のバイトスライスを1つに連結するために使用されます。 4.bites.trimspaceは、バイトスライスのフロントブランクとバックブランクを削除するために使用されます。 5.バイト。エクアルは、2つのバイトスライスが等しいかどうかを比較するために使用されます。 6.bytes.indexは、大規模なスライスでサブスライスの開始インデックスを見つけるために使用されます。

エンコード/binaryPackageIngoisESSENTINESTENTINESTINESTIDANDARDIZEDWAIDTOREADANDWRITEBINIRYDATA、クロスプラットフォームコンパティビティアンドハンドリングの可能性を確保することを確認します


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

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

メモ帳++7.3.1
使いやすく無料のコードエディター

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

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

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