Golang oktatóanyag: Ismerje meg a Go programozási nyelvet kezdőknek
Mi az a Go?
Go (más néven Golang) egy nyílt forráskódú programozási nyelv, amelyet a Google fejlesztett ki. Ez egy statikusan tipizált lefordított nyelv. A Go támogatja a párhuzamos programozást, azaz lehetővé teszi több folyamat egyidejű futtatását. Ez csatornákkal, gorutinokkal stb. érhető el. A Go Language rendelkezik szemétgyűjtéssel, amely maga végzi a memóriakezelést, és lehetővé teszi a funkciók késleltetett végrehajtását.
Ebben a Learn Go Language oktatóanyagban megtanuljuk a Golang összes alapját.
A GO letöltése és telepítése
Step 1) Ugrás https://golang.org/dl/. Töltse le a bináris fájlt az operációs rendszeréhez.
Step 2) Double kattintson a telepítőre, és kattintson a Futtatás gombra.
Step 3) Kattintson a Tovább gombra
Step 4) Válassza ki a telepítési mappát, és kattintson a Tovább gombra.
Step 5) A telepítés befejezése után kattintson a Befejezés gombra.
Step 6) A telepítés befejezése után a terminál megnyitásával és gépelésével ellenőrizheti
go version
Ez megjeleníti a go telepített verzióját
Az Ön First Go programja – Go Hello World!
Hozzon létre egy studyGo nevű mappát. Ebben a Go nyelvi oktatóanyagban ebben a mappában fogjuk létrehozni a go programjainkat. A Go fájlok a kiterjesztéssel jönnek létre .megy. A Go programokat a szintaxis használatával futtathatja
go run <filename>
Hozzon létre egy first.go nevű fájlt, és adja hozzá az alábbi kódot, és mentse el
package main import ("fmt") func main() { fmt.Println("Hello World! This is my first Go program\n") }
Navigáljon ebbe a mappába a terminálon. Futtassa a programot a paranccsal
fuss először.menj
Láthatja a kimeneti nyomtatást
Hello World! This is my first Go program
Most beszéljük meg a fenti programot.
csomag fő – Minden Go Language programnak csomagnévvel kell kezdődnie. A Go lehetővé teszi, hogy csomagokat használjunk egy másik go programban, és így támogatja a kód újrafelhasználását. A Go program végrehajtása a main nevű csomagban található kóddal kezdődik.
import fmt – importálja az fmt csomagot. Ez a csomag az I/O funkciókat valósítja meg.
func main() – Ez az a függvény, amelytől a program végrehajtása kezdődik. A fő funkciót mindig a fő csomagban kell elhelyezni. A main() alatt a kódot a { } belsejébe írhatod.
fmt.Println – Ez kinyomtatja a szöveget a képernyőn az fmt Println funkciójával.
Megjegyzés: A Go oktatóanyag alábbi szakaszaiban, amikor a kód végrehajtása/futtatását említi, az azt jelenti, hogy a kódot .go kiterjesztésű fájlba kell menteni, és a szintaxissal futtatni.
go run <filename>
Adattípusok
A típusok (adattípusok) jelentik a változóban tárolt érték típusát, a függvény által visszaadott érték típusát stb.
A Go Language három alapvető típusa létezik
Numerikus típusok – Számértékeket ábrázol, amelyek egész számokat, lebegőpontos és összetett értékeket tartalmaznak. Különféle numerikus típusok:
int8 – 8 bites előjelű egész számok.
int16 – 16 bites előjelű egész számok.
int32 – 32 bites előjelű egész számok.
int64 – 64 bites előjelű egész számok.
uint8 – 8 bites előjel nélküli egész számok.
uint16 – 16 bites előjel nélküli egész számok.
uint32 – 32 bites előjel nélküli egész számok.
uint64 – 64 bites előjel nélküli egész számok.
float32 – 32 bites lebegőpontos számok.
float64 – 64 bites lebegőpontos számok.
complex64 – float32 valós és képzeletbeli részei vannak.
complex128 – float32 valós és képzeletbeli részei vannak.
String típusok – Bájtok (karakterek) sorozatát jelöli. Különféle műveleteket hajthat végre a karakterláncokon, például a karakterlánc-összefűzést, a részkarakterlánc kibontását stb
Logikai típusok – 2 értéket képvisel, igaz vagy hamis.
Golang felület
Golang felület egy típus által az objektumok viselkedésének megvalósítására használt metódus-aláírások gyűjteménye. A Golang felület fő célja, hogy metódus-aláírásokat biztosítson nevekkel, argumentumokkal és visszatérési típusokkal. A módszer deklarálása és megvalósítása egy típustól függ. Egy interfész Golangban az „interfész” kulcsszó használatával deklarálható.
Változók
A változók egy olyan memóriahelyre mutatnak, amely valamilyen értéket tárol. A típusparaméter (az alábbi szintaxisban) a memóriahelyen tárolható érték típusát jelöli.
A változó a szintaxis segítségével deklarálható
var <variable_name> <type>
Miután deklarált egy típusú változót, a változót az adott típusú bármely értékhez hozzárendelheti.
Egy változó kezdeti értéket is megadhat magának a deklaráció során
var <variable_name> <type> = <value>
Ha a változót kezdeti értékkel deklarálja, akkor a hozzárendelt érték típusából következtessen a változó típusára. Tehát elhagyhatja a típust a deklaráció során a szintaxis használatával
var <variable_name> = <value>
Ezenkívül több változót is deklarálhat a szintaxissal
var <variable_name1>, <variable_name2> = <value1>, <value2>
A Go oktatóanyag alábbi programja néhány Golang példát tartalmaz a változók deklarációira
package main import "fmt" func main() { //declaring a integer variable x var x int x=3 //assigning x the value 3 fmt.Println("x:", x) //prints 3 //declaring a integer variable y with value 20 in a single statement and prints it var y int=20 fmt.Println("y:", y) //declaring a variable z with value 50 and prints it //Here type int is not explicitly mentioned var z=50 fmt.Println("z:", z) //Multiple variables are assigned in single line- i with an integer and j with a string var i, j = 100,"hello" fmt.Println("i and j:", i,j) }
A kimenet az lesz
x: 3 y: 20 z: 50 i and j: 100 hello
A Go Language ezenkívül egyszerű módot biztosít a változók értékkel rendelkező deklarálására a var kulcsszó kihagyásával
<variable_name> := <value>
Vegye figyelembe, hogy használt := helyett =. A := nem használható csak arra, hogy értéket rendeljen egy már deklarált változóhoz. A := az érték deklarálására és hozzárendelésére szolgál.
Hozzon létre egy assign.go nevű fájlt a következő kóddal
package main import ("fmt") func main() { a := 20 fmt.Println(a) //gives error since a is already declared a := 30 fmt.Println(a) }
Hajtsa végre a go futtassa a assign.go parancsot, hogy megnézze az eredményt mint
./assign.go:7:4: no new variables on left side of :=
A kezdeti érték nélkül deklarált változók numerikus típusok esetén 0, logikai érték hamis és karakterláncok üres karakterlánca
állandók
Az állandó változók azok a változók, amelyek értéke a hozzárendelés után nem változtatható meg. A Go programozási nyelvben a konstans a „const” kulcsszó használatával deklarálható.
Hozzon létre egy állandó.go nevű fájlt a következő kóddal
package main import ("fmt") func main() { const b =10 fmt.Println(b) b = 30 fmt.Println(b) }
Hajtsa végre a go futtassa a konstans.go parancsot az eredmény megtekintéséhez mint
.constant.go:7:4: cannot assign to b
Hurokpéldákért
A hurkok egy utasításblokk ismételt végrehajtására szolgálnak egy feltétel alapján. A legtöbb programozási nyelv 3 típusú ciklust biztosít – for, while, do while. De a Go programozási nyelv csak a ciklust támogatja.
A Golang for ciklus szintaxisa az
for initialisation_expression; evaluation_expression; iteration_expression{ // one or more statement }
Az inicializálás_kifejezés először (és csak egyszer) kerül végrehajtásra a Golang for ciklusban.
Ezután az értékelés_kifejezés kiértékelésre kerül, és ha igaz, a blokkon belüli kód végrehajtásra kerül.
Az iteration_expression id végrehajtásra kerül, és az értékelési_kifejezés újra kiértékelésre kerül. Ha ez igaz, az utasításblokk újra végrehajtásra kerül. Ez addig folytatódik, amíg az értékelés_kifejezés hamis lesz.
Másolja az alábbi programot egy fájlba, és futtassa, hogy megtekinthesse a Golang for loop számok nyomtatását 1-től 5-ig
package main import "fmt" func main() { var i int for i = 1; i <= 5; i++ { fmt.Println(i) } }
A kimenet az
1 2 3 4 5
Ha más
Ha más egy feltételes kijelentés. A szinax az
if condition{ // statements_1 }else{ // statements_2 }
Itt a feltétel kiértékelésre kerül, és ha igaz, akkor a_1 utasítások végrehajtásra kerülnek, különben a_2 utasítások.
Használhatja az if utasítást más nélkül is. Lehetőséged van láncolt if else állításokra is. Az alábbi programok részletesebben elmagyarázzák, ha más.
Hajtsa végre az alábbi programot. Ellenőrzi, hogy egy szám (x) kisebb-e 10-nél. Ha igen, akkor kiírja, hogy „x kisebb, mint 10”
package main import "fmt" func main() { var x = 50 if x < 10 { //Executes if x < 10 fmt.Println("x is less than 10") } }
Mivel itt az x értéke nagyobb, mint 10, a benne lévő if blokk feltétel utasítása nem hajtódik végre.
Most nézze meg az alábbi programot. Ebben a Go programozási nyelv oktatóanyagában van egy else blokk, amely az if kiértékelés meghiúsulása esetén kerül végrehajtásra.
package main import "fmt" func main() { var x = 50 if x < 10 { //Executes if x is less than 10 fmt.Println("x is less than 10") } else { //Executes if x >= 10 fmt.Println("x is greater than or equals 10") } }
Ez a program kimenetet ad
x is greater than or equals 10
Ebben a Go oktatóanyagban egy olyan programot fogunk látni, amelyben több if else blokk található (láncolt, ha else). Hajtsa végre az alábbi Go példát. Ellenőrzi, hogy egy szám kisebb-e 10-nél, vagy 10-90 között van-e, vagy nagyobb-e 90-nél.
package main import "fmt" func main() { var x = 100 if x < 10 { //Executes if x is less than 10 fmt.Println("x is less than 10") } else if x >= 10 && x <= 90 { //Executes if x >= 10 and x<=90 fmt.Println("x is between 10 and 90") } else { //Executes if both above cases fail i.e x>90 fmt.Println("x is greater than 90") } }
Itt először az if feltétel ellenőrzi, hogy x kisebb-e 10-nél, és nem. Tehát ellenőrzi a következő feltételt (else if), hogy 10 és 90 között van-e, ami szintén hamis. Így aztán végrehajtja a blokkot az else szakasz alatt, amely a kimenetet adja
x is greater than 90
kapcsoló
A Switch egy másik feltételes utasítás. A Switch utasítások kiértékelnek egy kifejezést, és az eredményt összehasonlítják a rendelkezésre álló értékekkel (esetekkel). Egyezés megtalálása után az egyezéshez (esethez) társított utasítások végrehajtásra kerülnek. Ha nem talál egyezést, akkor semmi sem kerül végrehajtásra. A váltáshoz hozzáadhat egy alapértelmezett esetet is, amely akkor hajtódik végre, ha nem található más egyezés. A kapcsoló szintaxisa az
switch expression { case value_1: statements_1 case value_2: statements_2 case value_n: statements_n default: statements_default }
Itt a kifejezés értékét minden esetben összehasonlítjuk az értékekkel. Ha egyezés található, az adott esethez tartozó utasítások végrehajtásra kerülnek. Ha nem található egyezés, az alapértelmezett szakasz alatti utasítások végrehajtásra kerülnek.
Hajtsa végre az alábbi programot
package main import "fmt" func main() { a,b := 2,1 switch a+b { case 1: fmt.Println("Sum is 1") case 2: fmt.Println("Sum is 2") case 3: fmt.Println("Sum is 3") default: fmt.Println("Printing default") } }
A kimenetet mint
Sum is 3
Módosítsa a és b értékét 3-ra, és az eredmény lesz
Printing default
Egy esetben több értéket is megadhat, ha vesszővel választja el őket.
tömbök
A tömb egy rögzített méretű, azonos típusú elemek elnevezett sorozatát képviseli. Nem lehet olyan tömb, amely egész számokat és karaktereket is tartalmaz. Egy tömb mérete nem módosítható, miután megadta a méretet.
A tömb deklarálásának szintaxisa a következő
var arrayname [size] type
Minden tömbelemhez értéket rendelhetünk a szintaxis segítségével
arrayname [index] = value
A tömb indexe innen kezdődik 0-tól 1-es méretig.
A szintaxis használatával a deklaráció során értékeket rendelhet a tömbelemekhez
arrayname := [size] type {value_0,value_1,…,value_size-1}
A méret paramétert figyelmen kívül hagyhatja a tömb értékekkel történő deklarálása közben is, ha a méretet helyettesíti a méret értékkel ... és a fordító az értékek számából fogja megtalálni a hosszt. A szintaxis az
arrayname := […] type {value_0,value_1,…,value_size-1}
A tömb hosszát a szintaxis segítségével találhatja meg
len(arrayname)
Hajtsa végre az alábbi Go példát a tömb megértéséhez
package main import "fmt" func main() { var numbers [3] string //Declaring a string array of size 3 and adding elements numbers[0] = "One" numbers[1] = "Two" numbers[2] = "Three" fmt.Println(numbers[1]) //prints Two fmt.Println(len(numbers)) //prints 3 fmt.Println(numbers) // prints [One Two Three] directions := [...] int {1,2,3,4,5} // creating an integer array and the size of the array is defined by the number of elements fmt.Println(directions) //prints [1 2 3 4 5] fmt.Println(len(directions)) //prints 5 //Executing the below commented statement prints invalid array index 5 (out of bounds for 5-element array) //fmt.Println(directions[5]) }
teljesítmény
Two 3 [One Two Three] [1 2 3 4 5] 5
Golang szelet és hozzáfűzés funkció
A szelet egy tömb egy része vagy szegmense. Vagy egy mögöttes tömb nézete vagy részleges nézete, amelyre mutat. A szelet elemeit a szelet nevével és indexszámával érheti el, ugyanúgy, mint egy tömbben. Egy tömb hosszát nem lehet megváltoztatni, de egy szelet méretét igen.
Egy szelet tartalma valójában egy tömb elemeire mutató mutatók. Azt jelenti ha egy szeletben bármely elemet megváltoztat, az az alapul szolgáló tömbtartalomra is hatással lesz.
A szelet létrehozásának szintaxisa a következő
var slice_name [] type = array_name[start:end]
Ez létrehoz egy szelet_neve nevű szeletet a tömb_neve nevű tömbből, az index elemeivel az elejétől az end-1-ig.
Most ebben a Golang oktatóanyagban az alábbi programot hajtjuk végre. A program létrehoz egy szeletet a tömbből, és kinyomtatja. Azt is láthatja, hogy a szelet tartalmának módosítása módosítja a tényleges tömböt.
package main import "fmt" func main() { // declaring array a := [5] string {"one", "two", "three", "four", "five"} fmt.Println("Array after creation:",a) var b [] string = a[1:4] //created a slice named b fmt.Println("Slice after creation:",b) b[0]="changed" // changed the slice data fmt.Println("Slice after modifying:",b) fmt.Println("Array after slice modification:",a) }
Ez a következőképpen nyomtatja ki az eredményt
Array after creation: [one two three four five] Slice after creation: [two three four] Slice after modifying: [changed three four] Array after slice modification: [one changed three four five]
Vannak bizonyos funkciók, mint például a Golang len, a Golang append, amelyeket szeletekre alkalmazhat
len(szelet_neve) – visszaadja a szelet hosszát
hozzáfűzés(szelet_neve,érték_1,érték_2) – A Golang append az érték_1 és érték_2 hozzáfűzésére szolgál egy meglévő szelethez.
append(szelet_nale1,szelet_neve2…) – hozzáfűzi a szelet_neve2-t a szelet_neve1-hez
Hajtsa végre a következő programot.
package main import "fmt" func main() { a := [5] string {"1","2","3","4","5"} slice_a := a[1:3] b := [5] string {"one","two","three","four","five"} slice_b := b[1:3] fmt.Println("Slice_a:", slice_a) fmt.Println("Slice_b:", slice_b) fmt.Println("Length of slice_a:", len(slice_a)) fmt.Println("Length of slice_b:", len(slice_b)) slice_a = append(slice_a,slice_b...) // appending slice fmt.Println("New Slice_a after appending slice_b :", slice_a) slice_a = append(slice_a,"text1") // appending value fmt.Println("New Slice_a after appending text1 :", slice_a) }
A kimenet az lesz
Slice_a: [2 3] Slice_b: [two three] Length of slice_a: 2 Length of slice_b: 2 New Slice_a after appending slice_b : [2 3 two three] New Slice_a after appending text1 : [2 3 two three text1]
A program először 2 szeletet készít, és kinyomtatja a hosszát. Ezután az egyik szeletet hozzáfűzte a másikhoz, majd egy karakterláncot fűzött a kapott szelethez.
Funkciók
A függvény egy utasításblokkot képvisel, amely egy adott feladatot hajt végre. A függvénydeklaráció megmondja a függvény nevét, a visszatérési típust és a bemeneti paramétereket. A függvénydefiníció a függvényben található kódot képviseli. A függvény deklarálásának szintaxisa a
func function_name(parameter_1 type, parameter_n type) return_type { //statements }
A paraméterek és a visszatérési típusok nem kötelezőek. Ezenkívül egy függvényből több értéket is visszaadhat.
Most ebben a Golang-oktatóanyagban futtassuk le a következő Golang-példát. Itt a calc nevű függvény 2 számot fogad el, elvégzi az összeadást és a kivonást, és mindkét értéket visszaadja.
package main import "fmt" //calc is the function name which accepts two integers num1 and num2 //(int, int) says that the function returns two values, both of integer type. func calc(num1 int, num2 int)(int, int) { sum := num1 + num2 diff := num1 - num2 return sum, diff } func main() { x,y := 15,10 //calls the function calc with x and y an d gets sum, diff as output sum, diff := calc(x,y) fmt.Println("Sum",sum) fmt.Println("Diff",diff) }
A kimenet az lesz
Sum 25 Diff 5
Csomagok
Csomagok a kód rendszerezésére szolgálnak. Egy nagy projektben nem lehetséges egyetlen fájlba kódot írni. A Go programozási nyelv lehetővé teszi, hogy a kódot különböző csomagokba rendezzük. Ez növeli a kód olvashatóságát és újrafelhasználhatóságát. A végrehajtható Go programnak tartalmaznia kell egy main nevű csomagot, és a program végrehajtása a main nevű függvénytől indul. Programunkba más csomagokat is importálhat a szintaxis használatával
import package_name
Ebben a Golang oktatóanyagban látni fogjuk és megvitatjuk, hogyan lehet csomagokat létrehozni és használni a következő Golang példában.
Step 1) Hozzon létre egy package_example.go nevű fájlt, és adja hozzá az alábbi kódot
package main import "fmt" //the package to be created import "calculation" func main() { x,y := 15,10 //the package will have function Do_add() sum := calculation.Do_add(x,y) fmt.Println("Sum",sum) }
A fenti programban az fmt egy olyan csomag, amelyet a Go programozási nyelv elsősorban I/O célokra biztosít számunkra. Ezenkívül láthat egy számítás nevű csomagot. A main()-on belül egy lépésösszeg := számítás látható.Do_add(x,y). Ez azt jelenti, hogy a Do_add függvényt a csomagszámításból hívja meg.
Step 2) Először is létre kell hoznia a csomagszámítást egy azonos nevű mappában, a go src mappájában. A go telepített elérési útja a PATH változóból található.
Mac esetén az echo $PATH parancs végrehajtásával keresse meg az elérési utat
Tehát az elérési út /usr/local/go
Windows esetén keresse meg az elérési utat az echo %GOROOT% végrehajtásával
Itt az elérési út: C:\Go\
Step 3) Keresse meg az src mappát (/usr/local/go/src Mac és C:\Go\src Windows esetén). Most a kódból a csomag neve számítás. A Go használatához a csomagot egy azonos nevű könyvtárba kell helyezni az src könyvtár alatt. Hozzon létre egy számítás nevű könyvtárat az src mappában.
Step 4) Hozzon létre egy calc.go nevű fájlt (bármilyen nevet megadhat, de a kódban lévő csomag neve számít. Itt számításnak kell lennie) a számítási könyvtárban, és adja hozzá az alábbi kódot
package calculation func Do_add(num1 int, num2 int)(int) { sum := num1 + num2 return sum }
Step 5) Futtassa a go install parancsot a számítási könyvtárból, amely lefordítja a calc.go fájlt.
Step 6) Most térjen vissza a package_example.go fájlhoz, és futtassa a go futtassa a package_example.go fájlt. A kimenet összege 25 lesz.
Vegye figyelembe, hogy a Do_add függvény neve nagybetűvel kezdődik. Ennek az az oka, hogy a Go-ban, ha a függvény neve nagybetűvel kezdődik, ez azt jelenti, hogy más programok láthatják (elérhetik), más programok nem férhetnek hozzá. Ha a függvény neve do_add, akkor a hibaüzenetet kapta volna
nem hivatkozhat a nem exportált név számítására.kalc..
Halasztás és halmozás
A Defer utasítások egy függvényhívás végrehajtásának elhalasztására szolgálnak, amíg a defer utasítást tartalmazó függvény a végrehajtást be nem fejezi.
Tanuljuk meg ezt egy példán keresztül:
package main import "fmt" func sample() { fmt.Println("Inside the sample()") } func main() { //sample() will be invoked only after executing the statements of main() defer sample() fmt.Println("Inside the main()") }
A kimenet az lesz
Inside the main() Inside the sample()
Itt a sample() végrehajtását elhalasztjuk, amíg a befoglaló függvény (main()) végrehajtása be nem fejeződik.
A halmozási halasztás több halasztási utasítást használ. Tegyük fel, hogy egy függvényen belül több késleltetési utasítás is van. A Go az összes halasztott függvényhívást egy verembe helyezi, és amint a befoglaló függvény visszatér, a halmozott függvények végrehajtásra kerülnek a Last In First Out (LIFO) rendelés. Ezt láthatja az alábbi példában.
Hajtsa végre az alábbi kódot
package main import "fmt" func display(a int) { fmt.Println(a) } func main() { defer display(1) defer display(2) defer display(3) fmt.Println(4) }
A kimenet az lesz
4 3 2 1
Itt először a main()-ban lévő kód fut le, majd a késleltetett függvényhívások fordított sorrendben, azaz 4, 3,2,1, XNUMX, XNUMX.
mutatók
A mutatók magyarázata előtt először beszéljük meg az '&' operátort. Az '&' operátor egy változó címének lekérésére szolgál. Ez azt jelenti, hogy az '&a' kiírja az a változó memóriacímét.
Ebben a Golang oktatóanyagban az alábbi programot fogjuk végrehajtani, hogy megjelenítsük egy változó értékét és a változó címét
package main import "fmt" func main() { a := 20 fmt.Println("Address:",&a) fmt.Println("Value:",a) }
Az eredmény lesz
Address: 0xc000078008 Value: 20
A mutatóváltozó egy másik változó memóriacímét tárolja. A szintaxis segítségével mutatót definiálhat
var variable_name *type
A csillag(*) azt jelenti, hogy a változó egy mutató. Az alábbi program végrehajtásával többet megtudhat
package main import "fmt" func main() { //Create an integer variable a with value 20 a := 20 //Create a pointer variable b and assigned the address of a var b *int = &a //print address of a(&a) and value of a fmt.Println("Address of a:",&a) fmt.Println("Value of a:",a) //print b which contains the memory address of a i.e. &a fmt.Println("Address of pointer b:",b) //*b prints the value in memory address which b contains i.e. the value of a fmt.Println("Value of pointer b",*b) //increment the value of variable a using the variable b *b = *b+1 //prints the new value using a and *b fmt.Println("Value of pointer b",*b) fmt.Println("Value of a:",a)}
A kimenet az lesz
Address of a: 0x416020 Value of a: 20 Address of pointer b: 0x416020 Value of pointer b 20 Value of pointer b 21 Value of a: 21
Struktúrák
A struktúra egy felhasználó által definiált adattípus, amely önmagában még egy azonos vagy eltérő típusú elemet tartalmaz.
A szerkezet használata 2 lépésből áll.
Először hozzon létre (deklaráljon) egy szerkezettípust
Másodszor, hozzon létre ilyen típusú változókat az értékek tárolására.
A struktúrákat főleg akkor használjuk, ha a kapcsolódó adatokat együtt szeretnénk tárolni.
Vegye figyelembe az alkalmazottak adatait, amelyek tartalmazzák a nevét, életkorát és címét. Ezt 2 módon kezelheti
Hozzon létre 3 tömböt – az egyik az alkalmazottak neveit, az egyik az életkort, a harmadik pedig az életkort tárolja.
Deklaráljon egy szerkezettípust 3 mezővel – név, cím és életkor. Hozzon létre egy ilyen szerkezettípusú tömböt, amelyben minden elem egy névvel, címmel és életkorral rendelkező struktúraobjektum.
Az első megközelítés nem hatékony. Az ilyen forgatókönyvekben a struktúrák kényelmesebbek.
A szerkezet deklarálásának szintaxisa a
type structname struct { variable_1 variable_1_type variable_2 variable_2_type variable_n variable_n_type }
Példa a szerkezeti deklarációra
type emp struct { name string address string age int }
Itt egy új felhasználó által definiált típus jön létre emp néven. Most már létrehozhat emp típusú változókat a szintaxis segítségével
var variable_name struct_name
Erre példa a
var empdata1 emp
Az empdata1 értékeit beállíthatja
empdata1.name = "John" empdata1.address = "Street-1, Bangalore" empdata1.age = 30
Struktúraváltozót is létrehozhat, és értékeket rendelhet hozzá
empdata2 := emp{"Raj", "Building-1, Delhi", 25}
Itt meg kell őriznie az elemek sorrendjét. Raj a névre, a következő elem a címre, az utolsó pedig az életkorra lesz leképezve.
Hajtsa végre az alábbi kódot
package main import "fmt" //declared the structure named emp type emp struct { name string address string age int } //function which accepts variable of emp type and prints name property func display(e emp) { fmt.Println(e.name) } func main() { // declares a variable, empdata1, of the type emp var empdata1 emp //assign values to members of empdata1 empdata1.name = "John" empdata1.address = "Street-1, London" empdata1.age = 30 //declares and assign values to variable empdata2 of type emp empdata2 := emp{"Raj", "Building-1, Paris", 25} //prints the member name of empdata1 and empdata2 using display function display(empdata1) display(empdata2) }
teljesítmény
John Raj
Módszerek (nem függvények)
A metódus egy vevő argumentumú függvény. Archiszerkezetileg a func kulcsszó és a metódus neve között van. Egy metódus szintaxisa az
func (variable variabletype) methodName(parameter1 paramether1type) { }
Konvertáljuk a fenti példaprogramot függvény helyett metódusra.
package main import "fmt" //declared the structure named emp type emp struct { name string address string age int } //Declaring a function with receiver of the type emp func(e emp) display() { fmt.Println(e.name) } func main() { //declaring a variable of type emp var empdata1 emp //Assign values to members empdata1.name = "John" empdata1.address = "Street-1, Lodon" empdata1.age = 30 //declaring a variable of type emp and assign values to members empdata2 := emp { "Raj", "Building-1, Paris", 25} //Invoking the method using the receiver of the type emp // syntax is variable.methodname() empdata1.display() empdata2.display() }
A Go nem egy objektum orientált nyelv, és nem tartalmazza az osztály fogalmát. A metódusok azt a képet adják, amit az objektumorientált programokban csinálunk, ahol egy osztály függvényei az objektumnév.függvénynév() szintaxis használatával kerülnek meghívásra.
Konkurencia
A Go támogatja a feladatok egyidejű végrehajtását. Ez azt jelenti, hogy a Go több feladatot is végrehajthat egyszerre. Ez eltér a párhuzamosság fogalmától. A párhuzamosság során egy feladatot kis részfeladatokra osztanak, és párhuzamosan hajtják végre. De párhuzamosan több feladatot hajtanak végre egyszerre. Az egyidejűség a Go-ban Goroutines és csatornák használatával érhető el.
Gorutines
A gorutin olyan függvény, amely más függvényekkel párhuzamosan is futhat. Általában egy függvény meghívásakor a vezérlés átkerül a meghívott függvénybe, majd a végrehajtás befejeztével visszatér a hívó függvényhez. A hívó függvény ezután folytatja a végrehajtását. A hívó függvény megvárja, hogy a meghívott függvény befejezze a végrehajtást, mielőtt folytatná a többi utasítást.
A gorutin esetén azonban a hívó függvény nem várja meg, amíg a meghívott függvény végrehajtása befejeződik. A következő utasításokkal folytatódik a végrehajtás. Egy programban több gorutin is lehet.
Ezenkívül a fő program kilép, amint befejezi az utasítások végrehajtását, és nem várja meg a meghívott gorutinok befejezését.
A Goroutine a go kulcsszóval, majd egy függvényhívással hívható meg.
Példa
go add(x,y)
Az alábbi Golang példák segítségével megértheti a gorutinokat. Hajtsa végre az alábbi programot
package main import "fmt" func display() { for i:=0; i<5; i++ { fmt.Println("In display") } } func main() { //invoking the goroutine display() go display() //The main() continues without waiting for display() for i:=0; i<5; i++ { fmt.Println("In main") } }
A kimenet az lesz
In main In main In main In main In main
Itt a főprogram még a gorutin megkezdése előtt befejezte a végrehajtást. A display() egy gorutin, amelyet a szintaxis segítségével hívunk meg
go function_name(parameter list)
A fenti kódban a main() nem várja meg, amíg a display() befejeződik, és a main() befejezte a végrehajtását, mielőtt a display() végrehajtotta volna a kódját. Tehát a display() belsejében lévő print utasítás nem lett kinyomtatva.
Most úgy módosítjuk a programot, hogy a display()-ből is kinyomtassa az utasításokat. 2 másodperces késleltetést adunk a main() for ciklusához és 1 másodperces késleltetést a display() for ciklusához.
package main import "fmt" import "time" func display() { for i:=0; i<5; i++ { time.Sleep(1 * time.Second) fmt.Println("In display") } } func main() { //invoking the goroutine display() go display() for i:=0; i<5; i++ { time.Sleep(2 * time.Second) fmt.Println("In main") } }
A kimenet némileg hasonló lesz
In display In main In display In display In main In display In display In main In main In main
Itt láthatja, hogy a párhuzamos végrehajtás miatt mindkét ciklus egymást átfedő módon hajtja végre.
Csatornák
A csatornák egy módja annak, hogy a funkciók kommunikáljanak egymással. Felfogható médiumnak, ahová az egyik rutin adatokat helyez el, és egy másik rutin eléri a Golang szerveren.
Egy csatorna a szintaxissal deklarálható
channel_variable := make(chan datatype)
Példa:
ch := make(chan int)
A szintaxis használatával adatokat küldhet egy csatornára
channel_variable <- variable_name
Példa
ch <- x
A szintaxis használatával adatokat fogadhat egy csatornáról
variable_name := <- channel_variable
Példa
y := <- ch
A gorutin fenti Go nyelvi példáiban láthatta, hogy a fő program nem várja meg a gorutint. De ez nem így van, ha csatornák érintettek. Tegyük fel, hogy ha egy gorutin adatokat küld a csatornának, a main() megvárja a csatornaadatokat fogadó utasítást, amíg meg nem kapja az adatokat.
Ezt az alábbi Go nyelvi példákban láthatja. Először írjon egy normál gorutint, és nézze meg a viselkedést. Ezután módosítsa a programot, hogy csatornákat használjon, és nézze meg a viselkedést.
Hajtsa végre az alábbi programot
package main import "fmt" import "time" func display() { time.Sleep(5 * time.Second) fmt.Println("Inside display()") } func main() { go display() fmt.Println("Inside main()") }
A kimenet az lesz
Inside main()
A main() befejezte a végrehajtást, és kilépett a gorutin végrehajtása előtt. Tehát a display()-n belüli nyomtatás nem lett végrehajtva.
Most módosítsa a fenti programot a csatornák használatához és a viselkedés megtekintéséhez.
package main import "fmt" import "time" func display(ch chan int) { time.Sleep(5 * time.Second) fmt.Println("Inside display()") ch <- 1234 } func main() { ch := make(chan int) go display(ch) x := <-ch fmt.Println("Inside main()") fmt.Println("Printing x in main() after taking from channel:",x) }
A kimenet az lesz
Inside display() Inside main() Printing x in main() after taking from channel: 1234
Itt az történik, hogy a main() x elérésekor := <-ch a ch csatornán várja az adatokat. A display() 5 másodpercet vár, majd adatokat küld a ch csatornára. A main() az adatok fogadásakor a csatornától feloldódik, és folytatja a végrehajtását.
A csatornának adatot küldő küldő a csatorna bezárásával tájékoztathatja a fogadókat, hogy a csatornához nem kerül több adat. Ez főleg akkor használatos, ha hurkot használ az adatok egy csatornára küldésére. Egy csatorna a segítségével zárható be
close(channel_name)
A vevő oldalon pedig egy további változó segítségével ellenőrizhető, hogy a csatorna le van-e zárva, miközben az adatokat lekéri a csatornáról.
variable_name, status := <- channel_variable
Ha az állapot True, az azt jelenti, hogy adatokat kapott a csatornától. Ha hamis, az azt jelenti, hogy egy zárt csatornáról próbál olvasni
Csatornákat is használhat a gorutinok közötti kommunikációhoz. 2 gorutint kell használni – az egyik adatot küld a csatornának, a másik pedig fogadja az adatokat a csatornától. Lásd az alábbi programot
package main import "fmt" import "time" //This subroutine pushes numbers 0 to 9 to the channel and closes the channel func add_to_channel(ch chan int) { fmt.Println("Send data") for i:=0; i<10; i++ { ch <- i //pushing data to channel } close(ch) //closing the channel } //This subroutine fetches data from the channel and prints it. func fetch_from_channel(ch chan int) { fmt.Println("Read data") for { //fetch data from channel x, flag := <- ch //flag is true if data is received from the channel //flag is false when the channel is closed if flag == true { fmt.Println(x) }else{ fmt.Println("Empty channel") break } } } func main() { //creating a channel variable to transport integer values ch := make(chan int) //invoking the subroutines to add and fetch from the channel //These routines execute simultaneously go add_to_channel(ch) go fetch_from_channel(ch) //delay is to prevent the exiting of main() before goroutines finish time.Sleep(5 * time.Second) fmt.Println("Inside main()") }
Itt 2 szubrutin van, az egyik adatot küld a csatornának, a másik pedig adatokat nyomtat a csatornára. Az add_to_channel függvény összeadja a 0 és 9 közötti számokat, és bezárja a csatornát. Ezzel egyidejűleg a fetch_from_channel függvény itt vár
x, flag := <- ch, és amint az adatok elérhetővé válnak, kinyomtatja az adatokat. Kilép, ha a zászló hamis, ami azt jelenti, hogy a csatorna zárva van.
A main()-ban a várakozás a main()-ból való kilépést megakadályozza, amíg a gorutinok be nem fejezik a végrehajtást.
Futtassa le a kódot, és nézze meg a kimenetet mint
Read data Send data 0 1 2 3 4 5 6 7 8 9 Empty channel Inside main()
választ
A Select a csatornákon működő switch utasításként tekinthető meg. Itt az esetleírások csatornaműveletek lesznek. Általában minden esetben a kijelentések olvasási kísérletet tesznek a csatornából. Amikor bármelyik eset készen áll (a csatorna beolvasásra kerül), akkor az adott esethez tartozó utasítás végrehajtásra kerül. Ha több eset is készen áll, egy véletlenszerűt választ. Megadhat egy alapértelmezett esetet, amely akkor hajtódik végre, ha egyik eset sem áll készen.
Lássuk az alábbi kódot
package main import "fmt" import "time" //push data to channel with a 4 second delay func data1(ch chan string) { time.Sleep(4 * time.Second) ch <- "from data1()" } //push data to channel with a 2 second delay func data2(ch chan string) { time.Sleep(2 * time.Second) ch <- "from data2()" } func main() { //creating channel variables for transporting string values chan1 := make(chan string) chan2 := make(chan string) //invoking the subroutines with channel variables go data1(chan1) go data2(chan2) //Both case statements wait for data in the chan1 or chan2. //chan2 gets data first since the delay is only 2 sec in data2(). //So the second case will execute and exits the select block select { case x := <-chan1: fmt.Println(x) case y := <-chan2: fmt.Println(y) } }
A fenti program végrehajtása a következő kimenetet adja:
from data2()
Itt a select utasítás arra vár, hogy az adatok bármelyik csatornán elérhetők legyenek. A data2() 2 másodperces alvás után adatokat ad a csatornához, ami a második esetet hajtja végre.
Adjon hozzá egy alapértelmezett esetet a kiválasztáshoz ugyanabban a programban, és nézze meg a kimenetet. Itt a kiválasztási blokk elérésekor, ha egyetlen esetben sincs kész adat a csatornán, akkor az alapértelmezett blokkot hajtja végre anélkül, hogy megvárná, amíg az adatok bármelyik csatornán elérhetővé válnak.
package main import "fmt" import "time" //push data to channel with a 4 second delay func data1(ch chan string) { time.Sleep(4 * time.Second) ch <- "from data1()" } //push data to channel with a 2 second delay func data2(ch chan string) { time.Sleep(2 * time.Second) ch <- "from data2()" } func main() { //creating channel variables for transporting string values chan1 := make(chan string) chan2 := make(chan string) //invoking the subroutines with channel variables go data1(chan1) go data2(chan2) //Both case statements check for data in chan1 or chan2. //But data is not available (both routines have a delay of 2 and 4 sec) //So the default block will be executed without waiting for data in channels. select { case x := <-chan1: fmt.Println(x) case y := <-chan2: fmt.Println(y) default: fmt.Println("Default case executed") } }
Ez a program a következő kimenetet adja:
Default case executed
Ennek az az oka, hogy amikor a kiválasztási blokkot elérte, egyetlen csatornának sem volt kiolvasható adata. Tehát az alapértelmezett eset kerül végrehajtásra.
mutexek
A Mutex a kölcsönös kizárás rövid formája. A Mutex akkor használatos, ha nem akarja, hogy egy erőforráshoz egyszerre több szubrutin is hozzáférjen. A Mutexnek 2 módja van – zárolás és feloldás. A Mutex a szinkroncsomagban található. Tehát importálnia kell a szinkronizálási csomagot. A kölcsönösen kizárólagosan végrehajtandó utasításokat a mutex.Lock() és a mutex.Unlock() belül lehet elhelyezni.
Tanuljuk meg a mutexet egy példával, amely megszámolja, hogy hányszor kerül végrehajtásra egy hurok. Ebben a programban azt várjuk, hogy a rutin 10-szer fut le, és a számlálás összegben kerül tárolásra. Ezt a rutint háromszor hívja meg, így a teljes számnak 3-nak kell lennie. A számlálás egy globális változóban van tárolva.
Először mutex nélkül futtassa a programot
package main import "fmt" import "time" import "strconv" import "math/rand" //declare count variable, which is accessed by all the routine instances var count = 0 //copies count to temp, do some processing(increment) and store back to count //random delay is added between reading and writing of count variable func process(n int) { //loop incrementing the count by 10 for i := 0; i < 10; i++ { time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) temp := count temp++ time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) count = temp } fmt.Println("Count after i="+strconv.Itoa(n)+" Count:", strconv.Itoa(count)) } func main() { //loop calling the process() 3 times for i := 1; i < 4; i++ { go process(i) } //delay to wait for the routines to complete time.Sleep(25 * time.Second) fmt.Println("Final Count:", count) }
Lásd az eredményt
Count after i=1 Count: 11 Count after i=3 Count: 12 Count after i=2 Count: 13 Final Count: 13
Az eredmény más lehet, ha végrehajtja, de a végeredmény nem lesz 30.
Itt az történik, hogy 3 gorutin próbálja növelni a count változóban tárolt hurokszámot. Tegyük fel, hogy egy pillanatban a szám 5, és a gorutin1 6-ra növeli a számot. A fő lépések a következők:
Számláló másolása temp
Növekedési hőmérséklet
Tárolja vissza a hőmérsékletet a számoláshoz
Tegyük fel, hogy hamarosan a 3. lépés végrehajtása után a gorutin1; lehet, hogy egy másik gorutinnak régi értéke van, mondjuk a 3 elvégzi a fenti lépéseket, és visszatárolja a 4-et, ami rossz. Ez megakadályozható a mutex használatával, amely arra készteti a többi rutint, hogy várakozzanak, amikor az egyik rutin már használja a változót.
Most a programot mutex-el fogjuk futtatni. Itt a fent említett 3 lépést mutexben hajtjuk végre.
package main import "fmt" import "time" import "sync" import "strconv" import "math/rand" //declare a mutex instance var mu sync.Mutex //declare count variable, which is accessed by all the routine instances var count = 0 //copies count to temp, do some processing(increment) and store back to count //random delay is added between reading and writing of count variable func process(n int) { //loop incrementing the count by 10 for i := 0; i < 10; i++ { time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) //lock starts here mu.Lock() temp := count temp++ time.Sleep(time.Duration(rand.Int31n(2)) * time.Second) count = temp //lock ends here mu.Unlock() } fmt.Println("Count after i="+strconv.Itoa(n)+" Count:", strconv.Itoa(count)) } func main() { //loop calling the process() 3 times for i := 1; i < 4; i++ { go process(i) } //delay to wait for the routines to complete time.Sleep(25 * time.Second) fmt.Println("Final Count:", count) }
Most lesz a kimenet
Count after i=3 Count: 21 Count after i=2 Count: 28 Count after i=1 Count: 30 Final Count: 30
Itt a várt eredményt kapjuk végső kimenetként. Mivel a számlálást beolvasó, növelő és visszaírt utasításokat mutexben hajtják végre.
Hibakezelés
A hibák abnormális állapotok, például egy meg nem nyitott fájl bezárása, egy nem létező fájl megnyitása stb. A függvények általában a hibákat adják vissza utolsó visszatérési értékként.
Az alábbi példa részletesebben elmagyarázza a hibát.
package main import "fmt" import "os" //function accepts a filename and tries to open it. func fileopen(name string) { f, er := os.Open(name) //er will be nil if the file exists else it returns an error object if er != nil { fmt.Println(er) return }else{ fmt.Println("file opened", f.Name()) } } func main() { fileopen("invalid.txt") }
A kimenet a következő lesz:
open /invalid.txt: no such file or directory
Itt megpróbáltunk megnyitni egy nem létező fájlt, és az er változónak adta vissza a hibát. Ha a fájl érvényes, akkor a hiba nulla lesz
Egyedi hibák
Ezzel a funkcióval egyéni hibákat hozhat létre. Ez a hibacsomag New() használatával történik. A fenti programot átírjuk, hogy kihasználjuk az egyedi hibákat.
Futtassa az alábbi programot
package main import "fmt" import "os" import "errors" //function accepts a filename and tries to open it. func fileopen(name string) (string, error) { f, er := os.Open(name) //er will be nil if the file exists else it returns an error object if er != nil { //created a new error object and returns it return "", errors.New("Custom error message: File name is wrong") }else{ return f.Name(),nil } } func main() { //receives custom error or nil after trying to open the file filename, error := fileopen("invalid.txt") if error != nil { fmt.Println(error) }else{ fmt.Println("file opened", filename) } }
A kimenet a következő lesz:
Custom error message:File name is wrong
Itt a area() egy négyzet területét adja vissza. Ha a bemenet kisebb, mint 1, akkor a area() hibaüzenetet ad vissza.
Fájlok olvasása
A fájlok az adatok tárolására szolgálnak. A Go segítségével adatokat olvashatunk ki a fájlokból
Először hozzon létre egy data.txt fájlt a jelenlegi könyvtárában az alábbi tartalommal.
Line one Line two Line three
Most futtassa az alábbi programot, hogy lássa, az a teljes fájl tartalmát nyomtatja ki kimenetként
package main import "fmt" import "io/ioutil" func main() { data, err := ioutil.ReadFile("data.txt") if err != nil { fmt.Println("File reading error", err) return } fmt.Println("Contents of file:", string(data)) }
Itt az adat, err := ioutil.ReadFile(“data.txt”) beolvassa az adatokat, és egy bájtsorozatot ad vissza. Nyomtatás közben string formátumba konvertálódik.
Fájlok írása
Ezt egy programmal látni fogod
package main import "fmt" import "os" func main() { f, err := os.Create("file1.txt") if err != nil { fmt.Println(err) return } l, err := f.WriteString("Write Line one") if err != nil { fmt.Println(err) f.Close() return } fmt.Println(l, "bytes written") err = f.Close() if err != nil { fmt.Println(err) return } }
Itt létrejön egy teszt.txt fájl. Ha a fájl már létezik, akkor a fájl tartalma csonkolva lesz. A Writeline() a tartalom fájlba írásához használható. Ezt követően a fájlt a Close() segítségével bezártad.
Puska
Ebben a Go oktatóanyagban bemutattuk,
Téma | Leírás | Szintaxis |
---|---|---|
Alapvető típusok | Numerikus, karakterlánc, bool | |
Változók | A változók deklarálása és értékek hozzárendelése | var változó_név típusa var változó_név típusa = érték var változó_neve1, változó_neve2 = érték1, érték2 változó_név := érték |
állandók | Változók, amelyek értéke a hozzárendelés után nem módosítható | const változó = érték |
A hurok számára | Az utasítások végrehajtása ciklusban. | inicializálási_kifejezéshez; értékelés_kifejezés; iterációs_kifejezés{ // egy vagy több állítás } |
Ha más | Ez egy feltételes kijelentés | if condition{ // nyilatkozatok_1 } Else { // nyilatkozatok_2 } |
kapcsoló | Feltételes nyilatkozat több esettel | switch kifejezés { case value_1: nyilatkozatok_1 case value_2: nyilatkozatok_2 case value_n: nyilatkozatok_n alapbeállítás: nyilatkozatok_alapértelmezett } |
Sor | Azonos típusú elemek fix méretű, elnevezett sorozata | tömbnév := [méret] típus {érték_0,érték_1,…,érték_méret-1} |
Szelet | Egy tömb része vagy szegmense | var slice_name [] type = tömb_neve[start:end] |
Funkciók | Kijelentések blokkja, amely egy adott feladatot hajt végre | func függvény_neve(paraméter_1 típusa, paraméter_n típusa) return_type { //állítások } |
Csomagok | A kód rendszerezésére szolgálnak. Növeli a kód olvashatóságát és újrafelhasználhatóságát | import csomag_neve |
Elhalasztja | Elhalasztja egy függvény végrehajtását, amíg a tartalmazó függvény be nem fejezi a végrehajtást | defer function_name(parameter_list) |
mutatók | Egy másik változó memóriacímét tárolja. | var változó_név *típus |
Szerkezet | Felhasználó által definiált adattípus, amely önmagában még egy azonos vagy eltérő típusú elemet tartalmaz | típus struktúranév struct { változó_1 változó_1_típusa változó_2 változó_2_típusa változó_n változó_n_típusa } |
Mód | A metódus egy vevő argumentumú függvény | func (változótípus) methodName(parameter_list) { } |
Goroutine | Olyan függvény, amely más függvényekkel párhuzamosan is futhat. | go function_name(parameter_list) |
csatorna | A funkciók egymás közötti kommunikációjának módja. Olyan adathordozó, amelyre az egyik rutin adatokat helyez el, és egy másik rutin hozzáfér. | Kijelent: ch := make(chan int) Adatok küldése a csatornára: csatorna_változó <- változó_neve Fogadás a csatornáról: változó_neve := <- csatorna_változó |
választ | Csatornákon működő Váltási utasítás. Az esetleírások csatornaműveletek lesznek. Amikor bármelyik csatorna készen áll az adatokkal, akkor az adott esethez tartozó utasítás végrehajtásra kerül | select { x eset := <-chan1: fmt.Println(x) y eset := <-chan2: fmt.Println(y) } |
mutexek | A Mutex akkor használatos, ha nem akarja, hogy egy erőforráshoz egyszerre több szubrutin is hozzáférjen. A Mutexnek 2 módja van – zárolás és feloldás | mutex.Lock() //állítások mutex.Unlock(). |
Fájlok olvasása | Beolvassa az adatokat, és egy bájtsorozatot ad vissza. | Data, err := ioutil.ReadFile(fájlnév) |
Fájl írása | Adatokat ír egy fájlba | l, err := f.WriteString(írandó_szöveg) |