Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Artikel yang menerangkan refleksi di Golang secara terperinci

Artikel yang menerangkan refleksi di Golang secara terperinci

青灯夜游
青灯夜游ke hadapan
2022-12-14 20:26:346109semak imbas

Artikel ini terutamanya akan membincangkan tentang refleksi dalam Golang, dengan harapan dapat memperoleh pemahaman baharu tentang anda.

Artikel yang menerangkan refleksi di Golang secara terperinci

Walaupun ramai orang telah menggunakan bahasa Go untuk jangka masa tertentu, malah ada yang selama 1 atau 2 tahun, mereka masih samar-samar tentang refleksi dalam bahasa Go. , saya tidak begitu yakin dalam hati saya. [Cadangan berkaitan: Pergi tutorial video, Pengajaran pengaturcaraan]

Apatah lagi, refleksi hampir tidak pernah digunakan. Anda boleh melakukannya Sememangnya adalah yang paling baik untuk mengendalikannya dengan cara yang paling mudah, paling cekap, berskala dan berprestasi baik. Anda tidak perlu menyalin penggunaan lanjutan secara mekanikal sendiri. Buku ini Kali ini, mari kita lihat dengan lebih dekat cara bermain dengan refleksi

Artikel akan membincangkannya dari lima aspek berikut

  • Apakah refleksi
  • Peraturan refleksi
  • Kes guna dan aplikasi fleksibel
  • Prinsip refleksi
  • Ringkasan

Pandangan ringkas tentang apa itu pantulan

Pandangan ringkas, Refleksi ialah keupayaan untuk mengakses dan mengubah suai program itu sendiri semasa program berjalan, sebagai contoh, semasa program berjalan, anda boleh mengubah suai nama medan dan nilai medan program, dan anda juga boleh menyediakan program dengan maklumat capaian antara muka, dsb.

Ini ialah mekanisme yang disediakan dalam bahasa Go Kita boleh Anda boleh melihat banyak penggunaan reflect dalam pustaka awam bahasa

Sebagai contoh, yang biasa digunakan. pakej fmt, Biasa digunakan json Serialization dan deserialization, secara semulajadi perpustakaan gorm yang kami sebutkan tadi juga menggunakan refleksi

Tetapi kenapa kita biasanya menggunakan Bagaimana pula dengan refleksi?

Mengikut kemampuan refleksi, secara semula jadi kerana antara muka yang kami sediakan tidak mengetahui jenis data yang akan datang, jenis data tertentu hanya diketahui apabila program berjalan

Tetapi apabila kami mengekod, kami juga berharap untuk mengesahkan jenis yang diluluskan semasa program dijalankan (seperti pensirilan json) dan beroperasi pada data khusus ini Pada masa ini, kami perlu menggunakan Keupayaan untuk mencerminkan

Jadi di mana sahaja pantulan digunakan, anda boleh melihat antara muka{} Bukankah ia mengejutkan?

Ia adalah tepat kerana kami tidak pasti jenis data yang akan datang, jadi kami mereka bentuknya sebagai antara muka{}. Jika anda tidak pasti tentang ciri dan penggunaan antara muka, anda boleh menyemak artikel sejarah . :

Perhatikan dahulu peraturan muhasabah

Pertama-tama perhatikan tiga hukum muhasabah yang penting, kita ikut peraturan Tidak akan ada masalah semasa bermain Masalah pelik hanya akan berlaku apabila kita tidak tahu peraturan dan sentiasa mencetuskan klausa

  • Refleksi boleh berubah. pembolehubah jenis antara muka ditukarkan kepada objek jenis pantulan

  • Refleksi boleh menukar objek jenis pantulan kepada pembolehubah jenis antara muka
  • Objek jenis pantulan yang kita mahu ubah suai semasa runtime, Kemudian nilai yang sepadan kepada objek ini dikehendaki boleh ditulis

Tiga peraturan di atas juga agak mudah difahami Adakah anda masih ingat petunjuk dalam pakej tidak selamat yang kami nyatakan sebelum ini?

Tukar jenis data kami yang biasa digunakan kepada jenis data tertentu dalam pakej (seperti pakej tidak selamat atau pakej mencerminkan), dan kemudian ubah suai data mengikut peraturan dalam pakej

Begitu juga, dengan menukar vest, anda boleh melakukan operasi yang berbeza

Beri perhatian kepada kes penggunaan dan gunakannya secara fleksibel

Secara amnya, kami akan mempelajari aplikasi asas dahulu, dan kemudian kaji prinsipnya, kaji mengapa ia boleh digunakan dengan cara ini, dan perlahan-lahan anda akan memahami dengan lebih mendalam

Untuk Undang-undang 1, tukar pembolehubah jenis antara muka kepada objek jenis pantulan

Sebenarnya Untuk pembolehubah jenis antara muka yang dinyatakan di sini, kita boleh menghantar pembolehubah mana-mana jenis data, seperti int, float, string ,map, slice, struct dan seterusnya

Objek jenis pantulan boleh difahami di sini sebagai objek reflect.Type dan reflect.Value dalam pakej pantulan pantulan, yang boleh diperolehi melalui fungsi TypeOf dan ValueOf yang disediakan dalam pakej reflect.

di mana reflect.Type sebenarnya adalah antara muka, yang mengandungi pelbagai antara muka yang perlu dilaksanakan, dan yang menyediakan maklumat berkaitan jenis

Anda boleh melihatnya dalam rajah di bawah reflect.Type Semua kaedah

  • hijau adalah semua jenis data yang boleh dipanggil
  • merah yang adalah data jenis fungsi yang boleh dipanggil
  • Yang hitam ialah Map, array Array, channel Chan, pointer Ptr atau slice Slice yang boleh dipanggil
  • Biru dipanggil oleh struktur
  • Kuning dipanggil mengikut jenis saluran

sebenarnya adalah struct Menurut struct ini, satu set kaedah juga dikaitkan, yang menyimpan jenis data dan data tertentu Dengan melihat datanya struktur reflect.Value

type Value struct {
   typ *rtype
   ptr unsafe.Pointer
   flag
}
Jika anda biasa dengan yang tidak selamat. Penunjuk di sini, lapisan bawah secara semula jadi boleh menukar

kepada unsafe.Pointer , kemudian mengubah suai datanya dan kemudian menukar Kembali, jika anda tidak biasa dengan penunjuk Go, anda boleh menyemak artikel ini: uintptr

  • Penunjuk dalam GO?
Tulis demo ringkas untuk mendapatkan jenis data dan nilai pembolehubah dengan mudah

func main() {   var demoStr string = "now reflect"
   fmt.Println("type:", reflect.TypeOf(demoStr))
   fmt.Println("value:", reflect.ValueOf(demoStr))
}

Untuk Undang-undang 2, untuk menukar objek jenis pantulan kepada pembolehubah jenis antara muka

kita boleh menukar jenis

ke dalam jenis data khusus kita, kerana terdapat reflect.Value > dan reflect.Value typ *rtypeptr unsafe.Pointer Contohnya, kita boleh mengendalikan

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)
}
melalui kaedah antara muka() objek

Untuk Undang-undang 3, ubah suai objek jenis pantulan

Mula-mula kita melihat kod demo dalam buku Pembolehubah yang dihantar ke

TypeOf

dan ValueOf sebenarnya adalah salinan. , maka jika anda mengharapkan untuk mengubah suai nilainya dalam objek jenis pantulan, anda perlu mendapatkan alamat pembolehubah tertentu dan kemudian mengubah suainya Premisnya ialah pembolehubah itu boleh ditulis . Sebagai contoh Anda boleh memahami daripada contoh

func main() {
   var demoStr string = "now reflect"
   v := reflect.ValueOf(demoStr)
   fmt.Println("is canset ", v.CanSet())
   //v.SetString("hello world")   // 会panic
   }

Anda boleh memanggil objek

dahulu untuk melihat sama ada ia boleh ditulis, jika ia boleh ditulis. kami akan menulisnya semula. Jika ia tidak boleh ditulis, jangan tulis, jika tidak ia akan panik

reflect.Value CanSet

Kemudian alamat pembolehubah yang diluluskan boleh diubah suai? ?

Tidak salah dengan idea untuk menghantar alamat, tetapi ada sesuatu yang salah dengan cara kita menetapkan nilai, jadi situasi panik di atas juga akan berlaku

Berhati-hati di sini Ia boleh difahami bahawa objek yang dicerminkan secara semula jadi tidak boleh diubah suai > kaedah

reflect.Value reflect.Value Cara yang lebih rumit sedikit

Selepas mengambil perhatian terhadap kes di atas, anda mungkin berfikir bahawa ia adalah kes yang begitu mudah, dan ia akan menjadi ok sebaik sahaja ia ditunjukkan, tetapi di tempat kerja Jika ia ranap sebaik sahaja ia digunakan, ia bermakna ia masih belum difahami sepenuhnya, menunjukkan bahawa ia belum dihadam Berikut ialah contoh lain di tempat kerja

Struktur mempunyai peta, kunci dalam peta ialah rentetan dan nilainya ialah [] Keperluan untuk rentetan

ialah untuk mengakses
    1
  • elemen hirisan yang kunci petanya ialah
  • sukan
sepadan dengan medan hobi dalam struktur dan menambahkannya Diubah suai kepada
    helloworld
  • 可以看到上述案例运行之后有时可以运行成功,有时会出现 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.gofunc (v Value) Type() Type {

    其中   reflect.Value  ,reflect.Type ,和任意数据类型 可以相互这样来转换

    如下图:

    总结

    至此,关于反射就聊到这里,一些关于源码的细节并没有详细说,更多的站在一个使用者的角度去看反射需要注意的点

    关于反射,大多的人是建议少用,因为是会影响到性能,不过如果不太关注这一点,那么用起来还是非常方便的

    高级功能自然也是双刃剑,你用不好就会 panic,如果你期望去使用他,那么就去更多的深入了解和一步一步的吃透他吧

    大道至简,反射三定律,活学活用

    更多编程相关知识,请访问:编程视频!!

Atas ialah kandungan terperinci Artikel yang menerangkan refleksi di Golang secara terperinci. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam