Avastage Go programmeerimiskeele peegelduse kontseptsiooni, süvenedes selle võimsatesse dünaamilise koodi analüüsi ja manipuleerimise võimalustesse.
Go programmeerimiskeel on laialt tuntud oma väljendusrikkuse poolest. See on tugevasti trükitud keel, kuid annab siiski rakendustele võimaluse käitusajal dünaamiliselt manipuleerida ja kontrollida objekte, sealhulgas muutujaid, funktsioone ja tüüpe.
Peegeldus on mehhanism, mida Go selle võime saavutamiseks kasutab. Mis siis on peegeldus ja kuidas saate peegeldust oma Go rakendustes rakendada?
Mis on peegeldus?
Peegeldus on programmi võime uurida oma muutujaid ja struktuuri ning nendega käitusajal manipuleerida.
Reflection in Go on mehhanism, mida keel pakub dünaamilise tüübi ja objektiga manipuleerimiseks. Võimalik, et peate objekte uurima, neid värskendama, nende meetodeid kutsuma või isegi nende tüüpidele omaseid toiminguid tegema, ilma nende tüüpe kompileerimise ajal teadmata. Peegeldus teeb selle kõik võimalikuks.
Erinevad Go paketid, sealhulgas
kodeering mis võimaldab teil töötage JSON-igaja fmt, toetuvad oma ülesannete täitmisel suuresti peegeldustele kapoti all.Peegelduspaketi mõistmine Go-s
Golangi õppimine võib olla väljakutseid oma semantika ning tõhusa tarkvara arendamist hõlbustavate pakettide ja meetodite tugeva raamatukogu tõttu.
The peegeldama pakett on üks neist paljudest pakettidest. See koosneb kõigist meetoditest, mida vajate peegelduse rakendamiseks Go rakendustes.
Alustamiseks peegeldama paketti, saate selle lihtsalt importida järgmiselt:
import"reflect"
Pakett määratleb kaks peamist tüüpi, mis panevad aluse Go-s mõtisklemiseks: peegeldama. Tüüp ja peegeldama. Väärtus.
A Tüüp on lihtsalt Go tüüp. peegeldama. Tüüp on liides, mis koosneb erinevatest meetoditest erinevate tüüpide tuvastamiseks ja nende komponentide uurimiseks.
Funktsioon mis tahes objekti tüübi kontrollimiseks Go-s, peegeldama. Tüüp, aktsepteerib mis tahes väärtust (an liides{}) kui selle ainsa argumendi ja tagastab a peegeldama. Tüüp väärtus, mis tähistab objekti dünaamilist tüüpi.
Allolev kood näitab kasutamist peegeldama. Tüüp:
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
Teine tüüp aastal peegeldama pakett, peegeldama. Väärtus võib sisaldada mis tahes tüüpi väärtust. The peegeldama. ValueOf funktsioon aktsepteerib mis tahes liides{} ja tagastab liidese dünaamilise väärtuse.
Siin on näide, mis näitab, kuidas seda kasutada peegeldama. ValueOf ülaltoodud väärtuste kontrollimiseks:
valueOfX := reflect.ValueOf(x)
valueOfY := reflect.ValueOf(y)
valueOfZ := reflect.ValueOf(z)
fmt.Println(valueOfX, valueOfY, valueOfZ) // 3.142 3.142 3
Väärtuste tüüpide ja tüüpide kontrollimiseks võite kasutada Lahke ja Tüüp selline meetod:
typeOfX2 := valueOfX.Type()
kindOfX := valueOfX.Kind()
fmt.Println(typeOfX2, kindOfX) // string string
Kuigi mõlema funktsioonikõne tulemus on sama, on need erinevad. tüüpOfX2 on põhimõtteliselt sama mis tüüpOfX sest mõlemad on dünaamilised peegeldama. Tüüp väärtused, kuid kindOfX on konstant, mille väärtus on spetsiifiline x, string.
Seetõttu on selliseid liike nagu piiratud arv int, string, ujuk, massiivijne, kuid lõpmatu arv tüüpe, kuna kasutaja määratud tüüpe võib olla mitu.
An liides{} ja a peegeldama. Väärtus töötab peaaegu samamoodi, võivad need sisaldada mis tahes tüüpi väärtusi.
Erinevus nende vahel seisneb selles, kuidas tühi liides{} ei avalda kunagi oma väärtuste loomulikke toiminguid ja meetodeid. Seetõttu peate enamasti teadma väärtuse dünaamilist tüüpi ja kasutama sellele juurdepääsuks tüübikinnitust (st. i.(string), x.(int)jne) enne, kui saate sellega toiminguid teha.
Seevastu a peegeldama. Väärtus sisaldab meetodeid, mida saate kasutada selle sisu ja omaduste uurimiseks, olenemata selle tüübist. Järgmises osas vaadeldakse neid kahte tüüpi praktiliselt ja näidatakse nende kasulikkust programmides.
Reflektsiooni rakendamine Go programmides
Peegeldus on väga lai ja võib leida programmis kasutust igal ajahetkel. Allpool on mõned praktilised näited, mis näitavad peegelduse kasutamist programmides:
-
Kontrollige sügavat võrdsust: peegeldama pakett pakub DeepEqual funktsioon kahe objekti väärtuste sügavuse kontrollimiseks võrdsuse tagamiseks. Näiteks on kaks struktuuri sügavalt võrdsed, kui kõigil nende vastavatel väljadel on samad tüübid ja väärtused. Siin on näide koodist:
// deep equality of two arrays
arr1 := [...]int{1, 2, 3}
arr2 := [...]int{1, 2, 3}
fmt.Println(reflect.DeepEqual(arr1, arr2)) // true -
Kopeerige viilud ja massiivid: saate kasutada ka Go refleksiooni API-d, et kopeerida ühe lõigu või massiivi sisu teise. Tehke järgmist.
slice1 := []int{1, 2, 3}
slice2 := []int{4, 5, 6}
reflect.Copy(reflect.ValueOf(slice1), reflect.ValueOf(slice2))
fmt.Println(slice1) // [4 5 6] -
Üldfunktsioonide määratlemine: Keeled nagu TypeScript esitage üldine tüüp, ükskõik milline, mida saate kasutada mis tahes tüüpi muutujate hoidmiseks. Kuigi Go ei sisalda sisseehitatud üldist tüüpi, saate üldiste funktsioonide määratlemiseks kasutada peegeldust. Näiteks:
// print the type of any value
funcprintType(x reflect.Value) {
fmt.Println("Value type:", x.Type())
} -
Juurdepääs struktuuri siltidele: silte kasutatakse Go struct väljadele metaandmete lisamiseks ning paljud teegid kasutavad neid iga välja käitumise määramiseks ja manipuleerimiseks. Struktuurimärgenditele pääsete juurde ainult peegeldusega. Järgmine näidiskood näitab seda:
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 -
Mõtiskledes liideste üle: Samuti on võimalik kontrollida, kas väärtus rakendab liidest. See võib olla kasulik, kui peate oma rakenduse nõuete ja eesmärkide alusel läbi viima täiendava valideerimiskihi. Allolev kood näitab, kuidas peegeldus aitab teil liideseid kontrollida ja nende omadusi määrata.
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
Ülaltoodud näited on mõned viisid, kuidas saate oma reaalsetes Go programmides peegeldust kasutada. The peegeldama pakett on väga vastupidav ja selle võimaluste kohta saate lisateavet ametlikust lehelt Mine peegelda dokumentatsioon.
Millal kasutada refleksiooni ja soovituslikke tavasid
Võib olla mitu stsenaariumi, mille puhul peegeldus võib tunduda ideaalne, kuid on oluline märkida, et peegeldusel on omad kompromissid ja see võib programmi negatiivselt mõjutada, kui seda ei kasutata õigesti.
Siin on mõned asjad, mida peegelduse kohta tähele panna:
- Peegeldust peaksite kasutama ainult siis, kui te ei saa oma programmis oleva objekti tüüpi eelnevalt kindlaks määrata.
- Peegeldus võib teie rakenduse jõudlust vähendada, seega peaksite vältima selle kasutamist jõudluskriitiliste toimingute jaoks.
- Peegeldus võib mõjutada ka teie koodi loetavust, seega ei tohiks te seda kõikjale loopida.
- Arvestades, vigu ei fikseerita kompileerimise ajal, nii et võite oma rakenduses rohkem käitusaegseid vigu avastada.
Vajadusel kasutage peegeldust
Reflection on saadaval paljudes keeltes, sealhulgas C# ja JavaScript, ning Go saab API suurepäraselt juurutada. Go peegelduse peamine eelis on see, et saate lahendada probleeme vähema koodiga, kui kasutate raamatukogu võimalusi.
Tüübiohutus on aga usaldusväärse koodi tagamiseks ülioluline ja kiirus on teine oluline tegur sujuva kasutuskogemuse tagamiseks. Seetõttu peaksite peegeldust kasutama alles pärast valikute kaalumist. Ja püüdke hoida oma kood loetav ja optimaalne.