Preskúmajte koncept reflexie v programovacom jazyku Go a ponorte sa do jeho výkonných možností pre dynamickú analýzu kódu a manipuláciu.

Programovací jazyk Go je všeobecne známy svojou výraznosťou. Je to silne typovaný jazyk, ale stále dáva aplikáciám schopnosť dynamicky manipulovať a kontrolovať objekty vrátane premenných, funkcií a typov za behu.

Odraz je mechanizmus, ktorý Go používa na dosiahnutie tejto schopnosti. Čo je teda odraz a ako ho môžete použiť vo svojich aplikáciách Go?

Čo je odraz?

Reflexia je schopnosť programu skúmať svoje premenné a štruktúru a manipulovať s nimi za behu.

Reflection in Go je mechanizmus, ktorý jazyk poskytuje na manipuláciu s dynamickým typom a objektom. Možno budete musieť skúmať objekty, aktualizovať ich, volať ich metódy alebo dokonca vykonávať operácie natívne pre ich typy bez toho, aby ste poznali ich typy v čase kompilácie. Reflexia toto všetko umožňuje.

Rôzne balíčky v Go vrátane kódovanie čo vám umožňuje pracovať s JSON, a fmt, sa pri plnení svojich povinností vo veľkej miere spoliehajú na odraz pod kapotou.

instagram viewer

Pochopenie reflexného balíka v službe Go

Učenie Golang môže byť náročné vďaka svojej sémantike a rozsiahlej knižnici balíkov a metód, ktoré uľahčujú vývoj efektívneho softvéru.

The odrážať balík je jedným z týchto mnohých balíkov. Pozostáva zo všetkých metód, ktoré potrebujete na implementáciu odrazu v aplikáciách Go.

Ak chcete začať s odrážať balík, môžete ho jednoducho importovať takto:

import"reflect"

Balík definuje dva hlavné typy, ktoré kladú základy reflexie v Go: odrážať. Typ a odrážať. Hodnota.

A Typ je jednoducho typ Go. odrážať. Typ je rozhranie, ktoré pozostáva z rôznych metód na identifikáciu rôznych typov a skúmanie ich komponentov.

Funkcia na kontrolu typu akéhokoľvek objektu v Go, odrážať. Typ, akceptuje akúkoľvek hodnotu (an rozhranie{}) ako svoj jediný argument a vráti a odrážať. Typ hodnotu, ktorá predstavuje dynamický typ objektu.

Nižšie uvedený kód ukazuje použitie odrážať. Typ:

x := "3.142"
y := 3.142
z := 3
typeOfX := reflect.TypeOf(x)
typeOfY := reflect.TypeOf(y)
typeOfZ := reflect.TypeOf(z)
fmt.Println(typeOfX, typeOfY, typeOfZ) // string float64 int

Druhý typ v odrážať balík, odrážať. Hodnota môže obsahovať hodnotu akéhokoľvek typu. The odrážať. Hodnota funkcia akceptuje ľubovoľné rozhranie{} a vráti dynamickú hodnotu rozhrania.

Tu je príklad použitia odrážať. Hodnota skontrolovať vyššie uvedené hodnoty:

valueOfX := reflect.ValueOf(x)
valueOfY := reflect.ValueOf(y)
valueOfZ := reflect.ValueOf(z)
fmt.Println(valueOfX, valueOfY, valueOfZ) // 3.142 3.142 3

Na kontrolu druhov a typov hodnôt môžete použiť Milý a Typ metóda ako je táto:

typeOfX2 := valueOfX.Type()
kindOfX := valueOfX.Kind()
fmt.Println(typeOfX2, kindOfX) // string string

Hoci výsledok oboch volaní funkcií je rovnaký, sú odlišné. typeOfX2 je v podstate to isté ako typeOfX pretože obe sú dynamické odrážať. Typ hodnoty, ale druhOfX je konštanta, ktorej hodnota je špecifický druh X, reťazec.

Práve preto existuje konečný počet druhov ako napr int, reťazec, plavák, pole, atď., ale nekonečné množstvo typov, pretože môže existovať niekoľko typov definovaných používateľom.

An rozhranie{} a a odrážať. Hodnota funguje takmer rovnako, môžu obsahovať hodnoty akéhokoľvek typu.

Rozdiel medzi nimi spočíva v tom, ako prázdne rozhranie{} nikdy neodhaľuje natívne operácie a metódy hodnoty, ktorú má. Vo väčšine prípadov teda potrebujete poznať dynamický typ hodnoty a na prístup k nej použiť aserciu typu (t.j. i.(reťazec), x. (int), atď.), než s ním budete môcť vykonávať operácie.

Naproti tomu a odrážať. Hodnota má metódy, ktoré môžete použiť na preskúmanie jeho obsahu a vlastností, bez ohľadu na jeho typ. Nasledujúca časť skúma tieto dva typy prakticky a ukazuje, ako sú užitočné v programoch.

Implementácia Reflection v Go programoch

Reflexia je veľmi široká a môže nájsť využitie v programe kedykoľvek. Nižšie je uvedených niekoľko praktických príkladov, ktoré demonštrujú využitie reflexie v programoch:

  • Skontrolujte hlbokú rovnosť: The odrážať balík poskytuje DeepEqual funkcia na kontrolu hodnôt dvoch objektov do hĺbky z hľadiska rovnosti. Napríklad dve štruktúry sú úplne rovnaké, ak všetky ich zodpovedajúce polia majú rovnaké typy a hodnoty. Tu je príklad kódu:
     // deep equality of two arrays
     arr1 := [...]int{1, 2, 3}
     arr2 := [...]int{1, 2, 3}
     fmt.Println(reflect.DeepEqual(arr1, arr2)) // true
  • Skopírujte rezy a polia: Na skopírovanie obsahu jedného rezu alebo poľa môžete použiť aj rozhranie API Go reflection. Tu je postup:
     slice1 := []int{1, 2, 3}
     slice2 := []int{4, 5, 6}
     reflect.Copy(reflect.ValueOf(slice1), reflect.ValueOf(slice2))
     fmt.Println(slice1) // [4 5 6]
  • Definovanie generických funkcií: Jazyky ako TypeScript poskytnúť všeobecný typ, akýkoľvek, ktorý môžete použiť na uchovávanie premenných akéhokoľvek typu. Hoci Go neprichádza so vstavaným generickým typom, môžete použiť reflexiu na definovanie generických funkcií. Napríklad:
     // print the type of any value
     funcprintType(x reflect.Value) {
    fmt.Println("Value type:", x.Type())
     }
  • Prístup k značkám struct: Značky sa používajú na pridávanie metadát do polí Go struct a mnohé knižnice ich používajú na určenie a úpravu správania každého poľa. K značkám struct máte prístup len s odrazom. Nasledujúci vzorový kód to demonštruje:
     type User struct {
    Name string`json:"name" required:"true"`
     }

     user := User{"John"}
     field, ok := reflect.TypeOf(user).Elem().FieldByName("Name")

     if !ok {
    fmt.Println("Field not found")
     }

     // print all tags, and value of "required"
     fmt.Println(field.Tag, field.Tag.Get("required"))
     // json:"name" required:"true" true

  • Zamyslenie sa nad rozhraniami: Je tiež možné skontrolovať, či hodnota implementuje rozhranie. To môže byť užitočné, keď potrebujete vykonať nejakú ďalšiu vrstvu validácií na základe požiadaviek a cieľov vašej aplikácie. Nižšie uvedený kód ukazuje, ako vám reflexia pomáha kontrolovať rozhrania a určovať ich vlastnosti:
     var i interface{} = 3.142
     typeOfI := reflect.TypeOf(i)
     stringerInterfaceType := reflect.TypeOf(new(fmt.Stringer))

     // check if i implements the stringer interface
     impl := typeOfI.Implements(stringerInterfaceType.Elem())
     fmt.Println(impl) // false

Vyššie uvedené príklady predstavujú niekoľko spôsobov, ako môžete použiť reflexiu vo svojich reálnych programoch Go. The odrážať balík je veľmi robustný a viac o jeho možnostiach sa dozviete v oficiálnom Choď sa zamyslieť dokumentáciu.

Kedy použiť úvahy a odporúčané postupy

Môže existovať viacero scenárov, v ktorých sa reflexia môže zdať ideálna, ale je dôležité poznamenať, že reflexia má svoje vlastné kompromisy a môže negatívne ovplyvniť program, ak sa nepoužíva správne.

Tu je niekoľko vecí, ktoré treba poznamenať o reflexii:

  • Reflexiu by ste mali používať iba vtedy, keď nemôžete vopred určiť typ objektu vo svojom programe.
  • Reflexia môže znížiť výkon vašej aplikácie, takže by ste sa jej mali vyhýbať na operácie kritické z hľadiska výkonu.
  • Odraz môže ovplyvniť aj čitateľnosť vášho kódu, takže sa chcete vyhnúť tomu, aby ste ho všade hádzali.
  • Vďaka reflexii sa chyby nezachytia v čase kompilácie, takže svoju aplikáciu môžete vystaviť väčšiemu počtu chýb pri spustení.

V prípade potreby použite odraz

Reflection je k dispozícii v mnohých jazykoch vrátane C# a JavaScriptu a Go robí dobre, že implementuje API vynikajúco. Hlavnou výhodou reflexie v Go je, že môžete vyriešiť problémy s menším množstvom kódu, keď využijete možnosti knižnice.

Bezpečnosť typu je však rozhodujúca pre zabezpečenie spoľahlivého kódu a rýchlosť je ďalším dôležitým faktorom pre bezproblémové používanie. To je dôvod, prečo by ste mali používať reflexiu až po zvážení vašich možností. A snažte sa, aby bol váš kód čitateľný a optimálny.