Istražite koncept refleksije u programskom jeziku Go, udubljujući se u njegove moćne mogućnosti za dinamičku analizu koda i manipulaciju.
Programski jezik Go nadaleko je poznat po svojoj ekspresivnosti. To je strogo tipiziran jezik, ali još uvijek daje aplikacijama mogućnost dinamičke manipulacije i pregledavanja objekata uključujući varijable, funkcije i tipove tijekom izvođenja.
Refleksija je mehanizam koji Go koristi za postizanje ove sposobnosti. Što je onda refleksija i kako možete primijeniti refleksiju u svojim Go aplikacijama?
Što je odraz?
Refleksija je sposobnost programa da ispita svoje varijable i strukturu i njima manipulira tijekom izvođenja.
Refleksija u Go je mehanizam koji jezik pruža za dinamičku manipulaciju tipom i objektima. Možda ćete morati ispitati objekte, ažurirati ih, pozvati njihove metode ili čak izvršiti operacije koje su izvorne njihovim tipovima bez poznavanja njihovih tipova tijekom kompilacije. Refleksija čini sve ovo mogućim.
Razni paketi u Go uključujući
kodiranje koji vam omogućuje da rad s JSON-om, i fmt, uvelike se oslanjaju na odraz ispod haube kako bi obavili svoje dužnosti.Razumijevanje refleksijskog paketa u Go
Učenje Golanga može biti izazovan zbog svoje semantike i robusne biblioteke paketa i metoda koje olakšavaju razvoj učinkovitog softvera.
The odražavati paket je jedan od ovih mnogih paketa. Sastoji se od svih metoda koje su vam potrebne za implementaciju refleksije u Go aplikacijama.
Da biste započeli s odražavati paket, možete ga jednostavno uvesti ovako:
import"reflect"
Paket definira dvije glavne vrste koje postavljaju temelj za razmišljanje u Go: odražavati. Tip i odražavati. Vrijednost.
A Tip je jednostavno Go tip. odražavati. Tip je sučelje koje se sastoji od različitih metoda za identificiranje različitih tipova i ispitivanje njihovih komponenti.
Funkcija za provjeru vrste bilo kojeg objekta u Gou, odražavati. Vrsta, prihvaća bilo koju vrijednost (an sučelje{}) kao jedini argument i vraća a odražavati. Tip vrijednost koja predstavlja dinamički tip objekta.
Kôd ispod pokazuje upotrebu odražavati. Vrsta:
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
Drugi tip u odražavati paket, odražavati. Vrijednost može držati vrijednost bilo koje vrste. The odražavati. Vrijednost funkcija prihvaća bilo koji sučelje{} i vraća dinamičku vrijednost sučelja.
Evo primjera koji pokazuje kako se koristi odražavati. Vrijednost za provjeru gornjih vrijednosti:
valueOfX := reflect.ValueOf(x)
valueOfY := reflect.ValueOf(y)
valueOfZ := reflect.ValueOf(z)
fmt.Println(valueOfX, valueOfY, valueOfZ) // 3.142 3.142 3
Da biste provjerili vrste i tipove vrijednosti, možete koristiti Ljubazan i Tip metoda poput ove:
typeOfX2 := valueOfX.Type()
kindOfX := valueOfX.Kind()
fmt.Println(typeOfX2, kindOfX) // string string
Iako je rezultat oba poziva funkcije isti, oni su različiti. typeOfX2 je u osnovi ista stvar kao typeOfX jer su oboje dinamični odražavati. Tip vrijednosti, ali kindOfX je konstanta čija je vrijednost specifične vrste x, niz.
Zbog toga postoji konačan broj vrsta kao što su int, niz, plutati, niz, itd., ali beskonačan broj tipova jer može postojati nekoliko korisnički definiranih tipova.
An sučelje{} i a odražavati. Vrijednost rade gotovo na isti način, mogu držati vrijednosti bilo koje vrste.
Razlika između njih leži u tome kako su prazne sučelje{} nikada ne izlaže izvorne operacije i metode vrijednosti koju ima. Dakle, u većini slučajeva trebate znati dinamički tip vrijednosti i upotrijebiti tvrdnju tipa da biste mu pristupili (tj. i. (string), x.(int), itd.) prije nego što možete izvoditi operacije s njim.
Nasuprot tome, a odražavati. Vrijednost ima metode koje možete koristiti za ispitivanje sadržaja i svojstava, bez obzira na vrstu. Sljedeći odjeljak praktično ispituje ove dvije vrste i pokazuje kako su korisne u programima.
Implementacija refleksije u Go programima
Refleksija je vrlo široka i može se koristiti u programu u bilo kojem trenutku. Ispod su neki praktični primjeri koji pokazuju korištenje refleksije u programima:
-
Provjerite duboku jednakost: The odražavati paket pruža DeepEqual funkcija za dubinsku provjeru jednakosti vrijednosti dvaju objekata. Na primjer, dvije su strukture duboko jednake ako sva njihova odgovarajuća polja imaju iste tipove i vrijednosti. Evo primjera koda:
// deep equality of two arrays
arr1 := [...]int{1, 2, 3}
arr2 := [...]int{1, 2, 3}
fmt.Println(reflect.DeepEqual(arr1, arr2)) // true -
Kopiraj rezove i nizove: Također možete koristiti API Go refleksije za kopiranje sadržaja jednog isječka ili niza u drugi. Evo kako:
slice1 := []int{1, 2, 3}
slice2 := []int{4, 5, 6}
reflect.Copy(reflect.ValueOf(slice1), reflect.ValueOf(slice2))
fmt.Println(slice1) // [4 5 6] -
Definiranje generičkih funkcija: Jezici poput TypeScripta osigurati generički tip, bilo koji, koji možete koristiti za držanje varijabli bilo koje vrste. Iako Go ne dolazi s ugrađenim generičkim tipom, možete koristiti refleksiju za definiranje generičkih funkcija. Na primjer:
// print the type of any value
funcprintType(x reflect.Value) {
fmt.Println("Value type:", x.Type())
} -
Pristup struct oznakama: Oznake se koriste za dodavanje metapodataka u Go struct polja, a mnoge biblioteke ih koriste za određivanje i manipuliranje ponašanjem svakog polja. Strukturnim oznakama možete pristupiti samo s refleksijom. Sljedeći primjer koda to pokazuje:
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 -
Razmišljanje o sučeljima: Također je moguće provjeriti implementira li vrijednost sučelje. Ovo može biti korisno kada trebate izvršiti neki dodatni sloj provjera valjanosti na temelju zahtjeva i ciljeva vaše aplikacije. Kod u nastavku pokazuje kako vam refleksija pomaže pregledati sučelja i odrediti njihova svojstva:
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
Gore navedeni primjeri neki su od načina na koje možete koristiti refleksiju u svojim Go programima u stvarnom svijetu. The odražavati paket je vrlo robustan i više o njegovim mogućnostima možete saznati u službenom Idi razmisli dokumentacija.
Kada koristiti refleksiju i preporučene prakse
Može postojati više scenarija u kojima se odraz može činiti idealnim, ali važno je napomenuti da odraz ima svoje ustupke i može negativno utjecati na program ako se ne koristi na odgovarajući način.
Evo nekoliko stvari koje treba imati na umu o refleksiji:
- Refleksiju biste trebali koristiti samo kada niste u mogućnosti unaprijed odrediti vrstu objekta u svom programu.
- Refleksija može smanjiti izvedbu vaše aplikacije, stoga biste je trebali izbjegavati koristiti za operacije kritične za izvedbu.
- Refleksija također može utjecati na čitljivost vašeg koda, tako da je želite izbjeći bacanje posvuda.
- Uz refleksiju, pogreške se ne bilježe tijekom kompajliranja, tako da možete izložiti svoju aplikaciju većem broju pogrešaka tijekom izvođenja.
Koristite odraz kada je to potrebno
Reflection je dostupan na mnogim jezicima uključujući C# i JavaScript, a Go je dobar za izvrsnu implementaciju API-ja. Glavna prednost refleksije u Go je ta što možete riješiti probleme s manje koda kada iskoristite mogućnosti biblioteke.
Međutim, sigurnost tipa ključna je za osiguranje pouzdanog koda, a brzina je još jedan važan čimbenik za glatko korisničko iskustvo. Zbog toga biste trebali koristiti razmišljanje tek nakon što ste odvagnuli svoje mogućnosti. I nastojte da vaš kod bude čitljiv i optimalan.