Golangi õpetus: õppige Go programmeerimiskeelt algajatele
Mis on Go?
Go (tuntud ka kui Golang) on avatud lähtekoodiga programmeerimiskeel, mille on välja töötanud Google. See on staatiliselt tipitud kompileeritud keel. Go toetab samaaegset programmeerimist, st võimaldab käivitada mitut protsessi samaaegselt. See saavutatakse kanalite, gorutiinide jms abil. Go Languageil on prügikogumine, mis ise haldab mälu ja võimaldab funktsioonide edasilükkamist.
Selles Learn Go Language õpetuses õpime kõiki Golangi põhitõdesid.
Kuidas GO alla laadida ja installida
Step 1) Minna https://golang.org/dl/. Laadige oma OS-i jaoks alla binaarfail.
Step 2) Double klõpsake installiprogrammil ja klõpsake nuppu Käivita.
Step 3) Klõpsake nuppu Edasi
Step 4) Valige installikaust ja klõpsake nuppu Edasi.
Step 5) Kui installimine on lõppenud, klõpsake nuppu Lõpeta.
Step 6) Kui installimine on lõppenud, saate seda kontrollida, avades terminali ja tippides
go version
See kuvab installitud go versiooni
Sinu esimene Go programm – Go Hello World!
Looge kaust nimega studyGo. Selles Go keele õpetuses loome sellesse kausta oma go programmid. Go failid luuakse laiendiga .mine. Saate käivitada Go programme süntaksi abil
go run <filename>
Looge fail nimega first.go ja lisage sellele allolev kood ning salvestage
package main import ("fmt") func main() { fmt.Println("Hello World! This is my first Go program\n") }
Liikuge oma terminalis sellesse kausta. Käivitage programm käsuga
mine enne jooksma.mine
Näete väljatrükki
Hello World! This is my first Go program
Nüüd arutame ülaltoodud programmi.
paketi põhi – iga Go Language programm peaks algama paketi nimega. Go võimaldab meil kasutada pakette teises go programmides ja toetab seega koodi korduvkasutatavust. Go programmi täitmine algab paketi sees oleva koodiga nimega main.
import fmt – impordib paketi fmt. See pakett rakendab I/O funktsioone.
func main() – see on funktsioon, millest algab programmi täitmine. Põhifunktsioon tuleks alati paigutada põhipakendisse. Main() all saate koodi kirjutada sisse { }.
fmt.Println – see prindib ekraanil oleva teksti fmt funktsiooni Println abil.
Märkus. Selle Go õpetuse allolevates jaotistes, kui mainite koodi käivitamist/käitamist, tähendab see koodi salvestamist faili laiendiga .go ja selle käivitamist süntaksi abil.
go run <filename>
Andmetüübid
Tüübid (andmetüübid) tähistavad muutujas salvestatud väärtuse tüüpi, funktsiooni tagastatava väärtuse tüüpi jne.
Go Languages on kolm põhitüüpi
Numbrilised tüübid – Esitage arvväärtusi, mis sisaldavad täisarve, ujukoma ja kompleksväärtusi. Erinevad numbritüübid on:
int8 – 8-bitised märgiga täisarvud.
int16 – 16-bitised märgiga täisarvud.
int32 – 32-bitised märgiga täisarvud.
int64 – 64-bitised märgiga täisarvud.
uint8 – 8-bitised märgita täisarvud.
uint16 – 16-bitised märgita täisarvud.
uint32 – 32-bitised märgita täisarvud.
uint64 – 64-bitised märgita täisarvud.
float32 – 32-bitised ujukomaarvud.
float64 – 64-bitised ujukomaarvud.
kompleks64 – sisaldab float32 reaalset ja imaginaarset osa.
kompleks128 – sisaldab float32 reaalset ja imaginaarset osa.
Stringi tüübid – esindab baitide (märkide) jada. Stringidega saate teha mitmesuguseid toiminguid, nagu stringide ühendamine, alamstringi eraldamine jne
Boole'i tüübid – tähistab kahte väärtust, kas tõene või väär.
Golangi liides
Golangi liides on meetodisignatuuride kogum, mida tüüp kasutab objektide käitumise rakendamiseks. Golangi liidese peamine eesmärk on pakkuda meetodisignatuure koos nimede, argumentide ja tagastustüüpidega. Meetodi deklareerimine ja rakendamine on tüübi ülesandeks. Golangi liidese saab deklareerida märksõna "liides" abil.
Muutujad
Muutujad osutavad mälukohale, mis salvestab mingisuguse väärtuse. Tüübiparameeter (allolevas süntaksis) tähistab väärtuse tüüpi, mida saab mälukohta salvestada.
Muutuja saab deklareerida süntaksi abil
var <variable_name> <type>
Kui olete teatud tüüpi muutuja deklareerinud, saate muutuja määrata selle tüübi mis tahes väärtusele.
Saate anda muutujale algväärtuse ka deklaratsiooni enda kasutades
var <variable_name> <type> = <value>
Kui deklareerite muutuja algväärtusega, järeldage määratud väärtuse tüübi põhjal muutuja tüüp. Seega saate süntaksi abil deklareerimise ajal tüübi välja jätta
var <variable_name> = <value>
Samuti saate süntaksiga deklareerida mitu muutujat
var <variable_name1>, <variable_name2> = <value1>, <value2>
Selle Go õpetuse allolevas programmis on mõned Golangi näited muutujate deklaratsioonidest
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) }
Väljund saab olema
x: 3 y: 20 z: 50 i and j: 100 hello
Go Language pakub ka lihtsat viisi muutujate väärtusega deklareerimiseks, jättes välja märksõna var use
<variable_name> := <value>
Pange tähele, et kasutasite := asemel =. Te ei saa kasutada := lihtsalt väärtuse määramiseks juba deklareeritud muutujale. := kasutatakse väärtuse deklareerimiseks ja määramiseks.
Looge fail nimega assign.go järgmise koodiga
package main import ("fmt") func main() { a := 20 fmt.Println(a) //gives error since a is already declared a := 30 fmt.Println(a) }
Käivitage mine käivitage assign.go, et näha tulemust kui
./assign.go:7:4: no new variables on left side of :=
Ilma algväärtuseta deklareeritud muutujatel on numbritüüpide puhul 0, Boole'i puhul false ja stringide puhul tühi string
Konstandid
Püsimuutujad on need muutujad, mille väärtust ei saa pärast määramist muuta. Go programmeerimiskeele konstant deklareeritakse märksõna "const" abil
Looge fail nimega konstant.go ja järgmise koodiga
package main import ("fmt") func main() { const b =10 fmt.Println(b) b = 30 fmt.Println(b) }
Käivitage mine käivita konstant.go, et näha tulemust kui
.constant.go:7:4: cannot assign to b
Silmusnäidete jaoks
Tsükleid kasutatakse lausete ploki korduvaks täitmiseks tingimuse alusel. Enamik programmeerimiskeeli pakuvad kolme tüüpi silmuseid – for, while, do while. Kuid Go programmeerimiskeel toetab ainult tsüklit.
Golangi tsükli süntaks on
for initialisation_expression; evaluation_expression; iteration_expression{ // one or more statement }
Initsialiseerimise_avaldis käivitatakse esimesena (ja ainult üks kord) Golang for tsüklis.
Seejärel hinnatakse hindamisavaldist ja kui see on tõsi, siis käivitatakse ploki sees olev kood.
Käitatakse iteratsiooni_avaldise ID ja hindamisavaldist hinnatakse uuesti. Kui see on tõsi, käivitatakse lauseplokk uuesti. See jätkub, kuni hindamisavaldis muutub vääraks.
Kopeerige allolev programm faili ja käivitage see, et näha Golangi tsükli trükkimiseks numbrid vahemikus 1 kuni 5
package main import "fmt" func main() { var i int for i = 1; i <= 5; i++ { fmt.Println(i) } }
Väljund on
1 2 3 4 5
Kui veel
Kui muidu on tingimuslause. Sünaks on
if condition{ // statements_1 }else{ // statements_2 }
Siin hinnatakse tingimust ja kui see on tõene, täidetakse laused_1, muidu käivitatakse laused_2.
Võite kasutada if-lauset ka ilma muuta. Samuti võite olla aheldatud kui else avaldused. Allpool olevad programmid selgitavad rohkem, kui veel.
Käivitage allolev programm. See kontrollib, kas arv x on väiksem kui 10. Kui jah, siis prindib "x on väiksem kui 10".
package main import "fmt" func main() { var x = 50 if x < 10 { //Executes if x < 10 fmt.Println("x is less than 10") } }
Kuna x väärtus on suurem kui 10, siis ploki tingimuse sees olevat avaldust ei täideta.
Nüüd vaadake allolevat programmi. Selles Go programmeerimiskeele õpetuses on meil muu plokk, mis käivitatakse, kui hindamine ebaõnnestub.
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") } }
See programm annab teile väljundi
x is greater than or equals 10
Nüüd selles Go õpetuses näeme programmi, millel on mitu if else plokki (aheldatud kui else). Käivitage allolev Go näide. See kontrollib, kas arv on väiksem kui 10 või vahemikus 10–90 või suurem kui 90.
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") } }
Siin kontrollib kõigepealt tingimus, kas x on väiksem kui 10 ja see pole nii. Seega kontrollib see järgmist tingimust (muidu kui), kas see on vahemikus 10 kuni 90, mis on samuti vale. Seejärel käivitab see ploki muu jaotises, mis annab väljundi
x is greater than 90
Lüliti
Switch on veel üks tingimuslause. Lülituslaused hindavad avaldist ja tulemust võrreldakse saadaolevate väärtuste (juhtumite) komplektiga. Kui vaste on leitud, täidetakse selle vastega (juhtumiga) seotud avaldused. Kui vastet ei leita, ei teostata midagi. Lülitumiseks saate lisada ka vaikejuhtumi, mis käivitatakse juhul, kui teisi vasteid ei leita. Lüliti süntaks on
switch expression { case value_1: statements_1 case value_2: statements_2 case value_n: statements_n default: statements_default }
Siin võrreldakse avaldise väärtust iga juhtumi väärtustega. Kui vaste on leitud, täidetakse selle juhtumiga seotud avaldused. Kui vastet ei leita, käivitatakse vaikejaotise all olevad avaldused.
Käivitage allolev programm
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") } }
Saate väljundi kujul
Sum is 3
Muutke a ja b väärtused 3-ks ja tulemus on selline
Printing default
Ühel juhul võib olla ka mitu väärtust, eraldades need komaga.
Massiraadid
Massiiv tähistab sama tüüpi elementide fikseeritud suurusega, nimega jada. Teil ei saa olla massiivi, mis sisaldab nii täisarvu kui ka märke. Massiivi suurust ei saa muuta, kui olete suuruse määranud.
Massiivi deklareerimise süntaks on
var arrayname [size] type
Igale massiivi elemendile saab süntaksi abil määrata väärtuse
arrayname [index] = value
Massiiviindeks algab alates 0 suurusele-1.
Deklareerimise ajal saate määrata massiivi elementidele väärtusi süntaksi abil
arrayname := [size] type {value_0,value_1,…,value_size-1}
Samuti saate massiivi väärtustega deklareerimisel ignoreerida suuruse parameetrit, asendades suuruse väärtusega ... ja kompilaator leiab pikkuse väärtuste arvust. Süntaks on
arrayname := […] type {value_0,value_1,…,value_size-1}
Massiivi pikkuse leiate süntaksi abil
len(arrayname)
Massiivi mõistmiseks käivitage allolev Go näide
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]) }
Väljund
Two 3 [One Two Three] [1 2 3 4 5] 5
Golangi viilutamise ja lisamise funktsioon
Lõik on massiivi osa või segment. Või on see vaade või osaline vaade aluseks olevast massiivist, millele see osutab. Lõigu elementidele pääsete juurde, kasutades lõigu nime ja indeksi numbrit samamoodi nagu massiivi puhul. Massiivi pikkust muuta ei saa, aga lõigu suurust saab muuta.
Lõigu sisu on tegelikult viidad massiivi elementidele. See tähendab kui muudate lõigul mõnda elementi, mõjutab see ka aluseks olevat massiivi sisu.
Lõigu loomise süntaks on
var slice_name [] type = array_name[start:end]
See loob massiivist nimega massiivi_nimi viilu nimega viilu_nimi, mille indeksi elemendid on algusest lõpuni-1.
Nüüd selles Golangi õpetuses käivitame alloleva programmi. Programm loob massiivist lõigu ja prindib selle. Samuti näete, et lõigu sisu muutmine muudab tegelikku massiivi.
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) }
Tulemus prinditakse kujul
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]
On teatud funktsioone, nagu Golang len, Golang append, mida saate viiludele rakendada
len(lõigu_nimi) – tagastab lõigu pikkuse
append(lõigu_nimi, väärtus_1, väärtus_2) – Golangi lisamist kasutatakse väärtuse_1 ja väärtus_2 lisamiseks olemasolevale lõigule.
append(slice_nale1,slice_name2…) – lisab lõigu_nimi2 jaotisele slice_name1
Käivitage järgmine programm.
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) }
Väljund saab olema
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]
Programm loob esmalt 2 viilu ja prindib selle pikkuse. Seejärel lisas see ühe lõigu teisele ja seejärel lõi saadud lõigule stringi.
Funktsioonid
Funktsioon esindab avalduste plokki, mis täidab konkreetset ülesannet. Funktsiooni deklaratsioon ütleb meile funktsiooni nime, tagastustüübi ja sisendparameetrid. Funktsiooni definitsioon tähistab funktsioonis sisalduvat koodi. Funktsiooni deklareerimise süntaks on
func function_name(parameter_1 type, parameter_n type) return_type { //statements }
Parameetrid ja tagastustüübid on valikulised. Samuti saate funktsioonist tagastada mitu väärtust.
Nüüd selles Golangi õpetuses käivitame järgmise Golangi näite. Siin aktsepteerib funktsioon nimega calc 2 numbrit ja teeb liitmise ja lahutamise ning tagastab mõlemad väärtused.
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) }
Väljund saab olema
Sum 25 Diff 5
Paketid
Koodi korrastamiseks kasutatakse pakette. Suure projekti puhul ei ole võimalik koodi kirjutada ühte faili. Go programmeerimiskeel võimaldab meil korraldada koodi erinevate pakettide alla. See suurendab koodi loetavust ja korduvkasutatavust. Käivitatav Go programm peaks sisaldama paketti nimega main ja programmi täitmine algab funktsioonist nimega main. Teisi meie programmi pakette saate importida süntaksi abil
import package_name
Selles Golangi õpetuses näeme ja arutame, kuidas järgmises Golangi näites pakette luua ja kasutada.
Step 1) Looge fail nimega package_example.go ja lisage allolev kood
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) }
Ülaltoodud programmis on fmt pakett, mille Go programmeerimiskeel pakub meile peamiselt I/O eesmärkidel. Samuti näete paketti nimega arvutus. Main() sees näete sammusummat := arvutus. Do_add(x,y). See tähendab, et käivitate paketi arvutamisel funktsiooni Do_add.
Step 2) Esiteks peaksite looma paketi arvutuse sama nimega kaustas src kausta all. Paigaldatud käigutee leiate muutujast PATH.
Maci puhul leidke tee, käivitades echo $PATH
Nii et tee on /usr/local/go
Windowsi puhul leidke tee, käivitades echo %GOROOT%
Siin on tee C:\Go\
Step 3) Liikuge kausta src (/usr/local/go/src Maci jaoks ja C:\Go\src Windowsi jaoks). Nüüd koodist on paketi nimi arvutus. Go nõuab, et pakett tuleks paigutada src kataloogi all olevasse samanimelisse kataloogi. Looge src kaustas kataloog nimega arvutus.
Step 4) Looge arvutuskataloogi fail nimega calc.go (võite anda mis tahes nime, kuid koodis olev paketi nimi on oluline. Siin peaks see olema arvutus) ja lisage allolev kood
package calculation func Do_add(num1 int, num2 int)(int) { sum := num1 + num2 return sum }
Step 5) Käivitage arvutuskataloogist käsk go install, mis kompileerib faili calc.go.
Step 6) Nüüd minge tagasi saidile package_example.go ja käivitage käsk, käivitage package_example.go. Väljund on summa 25.
Pange tähele, et funktsiooni Do_add nimi algab suure tähega. Selle põhjuseks on asjaolu, et kui funktsiooni nimi algab Go-s suure tähega, tähendab see seda, et teised programmid näevad seda (juurdepääsevad), muidu ei pääse teised programmid sellele juurde. Kui funktsiooni nimi oleks do_add, oleks viga saanud
ei saa viidata eksportimata nimede arvutamisele.arvutus..
Edasilükkamine ja edasilükkamiste virnastamine
Edasilükkamise lauseid kasutatakse funktsioonikutse täitmise edasilükkamiseks, kuni edasilükkamislauset sisaldav funktsioon täitmise lõpetab.
Õppige seda näitega:
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()") }
Väljund saab olema
Inside the main() Inside the sample()
Siin lükatakse proovi() täitmine edasi, kuni sulgemisfunktsiooni(main()) täitmine on lõppenud.
Edasilükkamise virnastamine kasutab mitut edasilükkamise avaldust. Oletame, et teil on funktsiooni sees mitu edasilükkamislauset. Go paigutab kõik edasilükatud funktsioonikutsed virna ja kui ümbritsev funktsioon naaseb, käivitatakse virnastatud funktsioonid Last In First Out (LIFO) tellimus. Seda näete allolevas näites.
Käivitage allolev kood
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) }
Väljund saab olema
4 3 2 1
Siin käivitatakse esmalt main() sees olev kood ja seejärel edasilükatud funktsioonikutsed vastupidises järjekorras, st 4, 3,2,1, XNUMX, XNUMX.
viiteid
Enne näpunäidete selgitamist käsitleme kõigepealt operaatorit '&'. Muutuja aadressi saamiseks kasutatakse operaatorit '&'. See tähendab, et '&a' prindib muutuja a mäluaadressi.
Selles Golangi õpetuses käivitame alloleva programmi, et kuvada muutuja väärtus ja selle muutuja aadress
package main import "fmt" func main() { a := 20 fmt.Println("Address:",&a) fmt.Println("Value:",a) }
Tulemus saab olema
Address: 0xc000078008 Value: 20
Osutimuutuja salvestab teise muutuja mäluaadressi. Kursori saate määratleda süntaksi abil
var variable_name *type
Tärn (*) tähistab muutujat, mis on osuti. Alloleva programmi käivitamisel saate rohkem aru
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)}
Väljund saab olema
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
Struktuurid
Struktuur on kasutaja määratletud andmetüüp, mis ise sisaldab veel ühte sama või erinevat tüüpi elementi.
Struktuuri kasutamine on kaheastmeline protsess.
Esiteks looge (deklareerige) struktuuri tüüp
Teiseks loo väärtuste salvestamiseks seda tüüpi muutujad.
Struktuure kasutatakse peamiselt siis, kui soovite seotud andmeid koos salvestada.
Mõelge töötaja teabele, millel on nimi, vanus ja aadress. Saate sellega hakkama kahel viisil
Loo 3 massiivi – üks massiiv salvestab töötajate nimed, üks vanus ja kolmas vanus.
Struktuuritüübi deklareerimine kolme väljaga – nimi, aadress ja vanus. Looge seda tüüpi struktuuriga massiiv, kus iga element on struktuuriobjekt, millel on nimi, aadress ja vanus.
Esimene meetod ei ole tõhus. Seda tüüpi stsenaariumide korral on struktuurid mugavamad.
Struktuuri deklareerimise süntaks on
type structname struct { variable_1 variable_1_type variable_2 variable_2_type variable_n variable_n_type }
Struktuurideklaratsiooni näide on
type emp struct { name string address string age int }
Siin luuakse uus kasutaja määratud tüüp nimega emp. Nüüd saate süntaksi abil luua emp-tüüpi muutujaid
var variable_name struct_name
Näitena võib tuua
var empdata1 emp
Saate määrata empdata1 väärtused as
empdata1.name = "John" empdata1.address = "Street-1, Bangalore" empdata1.age = 30
Samuti saate luua struktuurimuutuja ja määrata väärtused
empdata2 := emp{"Raj", "Building-1, Delhi", 25}
Siin peate säilitama elementide järjekorra. Raj kaardistatakse nimega, järgmine element aadressiga ja viimane vanusega.
Käivitage allolev kood
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) }
Väljund
John Raj
Meetodid (mitte funktsioonid)
Meetod on vastuvõtja argumendiga funktsioon. Archistruktuuriliselt jääb see märksõna func ja meetodi nime vahele. Meetodi süntaks on
func (variable variabletype) methodName(parameter1 paramether1type) { }
Teisendame ülaltoodud näidisprogrammi funktsiooni asemel meetodeid kasutama.
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() }
Go ei ole objektorienteeritud keel ja sellel puudub klassi mõiste. Meetodid annavad aimu sellest, mida teete objektorienteeritud programmides, kus klassi funktsioone kutsutakse välja süntaksiga objektinimi.funktsiooninimi()
Kooskõla
Go toetab ülesannete samaaegset täitmist. See tähendab, et Go saab korraga täita mitut ülesannet. See erineb paralleelsuse mõistest. Paralleelsuse korral jagatakse ülesanne väikesteks alamülesanneteks ja täidetakse paralleelselt. Kuid samaaegselt täidetakse korraga mitu ülesannet. Samaaegsus saavutatakse Go-s Goroutines'i ja kanalite abil.
Gorutines
Gorutine on funktsioon, mis võib töötada samaaegselt teiste funktsioonidega. Tavaliselt kantakse funktsiooni käivitamisel juhtelement väljakutsutavasse funktsiooni ja kui selle täitmise juhtimine naaseb kutsuva funktsiooni juurde. Seejärel jätkab helistamisfunktsioon oma täitmist. Väljakutsuv funktsioon ootab, kuni käivitatud funktsioon täitmise lõpetab, enne kui jätkab ülejäänud lausetega.
Kuid gorutiini puhul ei oota kutsumisfunktsioon kutsutud funktsiooni täitmise lõpuleviimist. Selle täitmist jätkatakse järgmiste avaldustega. Ühes programmis võib olla mitu gorutiini.
Samuti väljub põhiprogramm, kui ta on oma avalduste täitmise lõpetanud, ega oota kutsutud gorutiinide lõpetamist.
Goroutine'i käivitamiseks kasutatakse märksõna go, millele järgneb funktsioonikutse.
Näide
go add(x,y)
Alltoodud Golangi näidete abil saate aru gorutiinidest. Käivitage allolev programm
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") } }
Väljund saab olema
In main In main In main In main In main
Siin lõpetas põhiprogramm täitmise juba enne gorutiini algust. Display() on gorutiin, mis käivitatakse süntaksi abil
go function_name(parameter list)
Ülaltoodud koodis ei oota main() displei() lõpetamist ja main() lõpetas täitmise enne, kui display() oma koodi käivitas. Nii et display() sees olevat printimislauset ei trükitud.
Nüüd muudame programmi, et printida väljavõtted ka väljast display(). Lisame 2-sekundilise viivituse main() for-tsüklile ja 1-sekundilise viivituse display() for-tsüklile.
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") } }
Väljund on mõnevõrra sarnane
In display In main In display In display In main In display In display In main In main In main
Siin näete, et mõlemad tsüklid täidetakse samaaegse täitmise tõttu kattuval viisil.
Kanalid
Kanalid on viis, kuidas funktsioonid saavad omavahel suhelda. Seda võib pidada meediumiks, kuhu üks rutiin paigutab andmed ja millele pääseb juurde teine rutiin Golangi serveris.
Kanali saab deklareerida süntaksiga
channel_variable := make(chan datatype)
Näide:
ch := make(chan int)
Saate saata andmeid kanalile süntaksi abil
channel_variable <- variable_name
Näide
ch <- x
Saate kanalilt andmeid vastu võtta süntaksi abil
variable_name := <- channel_variable
Näide
y := <- ch
Ülaltoodud go-keelsetes gorutiini näidetes olete näinud, et põhiprogramm ei oota gorutiini. Kuid see pole nii, kui kanalid on kaasatud. Oletame, et kui gorutiin surub andmed kanalisse, ootab main() kanali andmeid vastuvõtvat lauset, kuni ta andmed hangib.
Seda näete allpool Go keele näidetes. Kõigepealt kirjutage tavaline gorutiin ja vaadake käitumist. Seejärel muutke programmi kanalite kasutamiseks ja käitumise vaatamiseks.
Käivitage allolev programm
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()") }
Väljund saab olema
Inside main()
Main() lõpetas täitmise ja väljus enne gorutiini käivitamist. Nii et kuva() sees olevat printimist ei teostatud.
Nüüd muutke ülaltoodud programmi kanalite kasutamiseks ja käitumise vaatamiseks.
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) }
Väljund saab olema
Inside display() Inside main() Printing x in main() after taking from channel: 1234
Siin juhtub, et main() x saavutamisel := <-ch ootab andmeid kanalil ch. Kuva() ootab 5 sekundit ja seejärel edastab andmed kanalile ch. Main() kanalilt andmete vastuvõtmisel deblokeeritakse ja jätkab selle täitmist.
Saatja, kes edastab andmed kanalisse, saab kanali sulgemisega teavitada vastuvõtjaid, et kanalile rohkem andmeid ei lisata. Seda kasutatakse peamiselt siis, kui kasutate andmete kanalisse suunamiseks silmust. Kanali saab sulgeda kasutades
close(channel_name)
Ja vastuvõtja otsas on võimalik kontrollida, kas kanal on suletud, kasutades lisamuutujat, samal ajal kui kanalilt andmeid tuuakse kasutades
variable_name, status := <- channel_variable
Kui olek on Tõene, tähendab see, et saite kanalilt andmeid. Kui see on vale, tähendab see, et proovite lugeda suletud kanalist
Gorutiinide vaheliseks suhtluseks saate kasutada ka kanaleid. Vaja kasutada 2 gorutiini – üks lükkab andmed kanalisse ja teine võtab andmed kanalilt vastu. Vaadake allolevat programmi
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()") }
Siin on 2 alamprogrammi, millest üks edastab andmed kanalile ja teine prindib andmed kanalile. Funktsioon add_to_channel liidab numbrid vahemikus 0 kuni 9 ja sulgeb kanali. Samal ajal ootab funktsioon Fetch_from_channel kell
x, lipp := <- ch ja kui andmed muutuvad kättesaadavaks, prindib see andmed välja. See väljub, kui lipp on vale, mis tähendab, et kanal on suletud.
Main()-s oodatakse main()-st väljumist, kuni gorutiinid täitmise lõpetavad.
Käivitage kood ja vaadake väljundit kui
Read data Send data 0 1 2 3 4 5 6 7 8 9 Empty channel Inside main()
valima
Valikut saab vaadata lüliti avaldusena, mis töötab kanalitel. Siin on juhtumiavaldused kanalioperatsioon. Tavaliselt loetakse iga juhtumi avaldused kanalist. Kui mõni juhtudest on valmis (kanalit loetakse), täidetakse selle juhtumiga seotud avaldus. Kui valmis on mitu juhtumit, valib see juhusliku. Teil võib olla vaikejuhtum, mis käivitatakse, kui ükski juhtudest pole valmis.
Vaatame allolevat koodi
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) } }
Ülaltoodud programmi käivitamine annab väljundi:
from data2()
Siin ootab valikuavaldus, kuni andmed on saadaval mis tahes kanalis. Data2() lisab andmed kanalile pärast 2-sekundilist unerežiimi, mis käivitab teise juhtumi käivitamise.
Lisage samas programmis valikule vaiketäht ja vaadake väljundit. Kui valikuplokini jõudmisel ühelgi juhul pole kanalil andmeid valmis, siis käivitab see vaikeploki, ootamata, kuni andmed on ühelgi kanalil saadaval.
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") } }
See programm annab väljundi:
Default case executed
Selle põhjuseks on asjaolu, et valikuploki jõudmisel polnud ühelgi kanalil lugemiseks andmeid. Seega täidetakse vaikejuhtum.
mutexid
Mutex on vastastikuse välistamise lühivorm. Mutexi kasutatakse siis, kui te ei soovi lubada ressursile juurdepääsu korraga mitmele alamprogrammile. Mutexil on 2 meetodit – lukustada ja avada. Mutex sisaldub sünkroonimispaketis. Seega peate sünkroonimispaketi importima. Avaldused, mida tuleb üksteist välistavalt täita, saab paigutada mutex.Lock() ja mutex.Unlock() sisse.
Õppime mutexi näitega, mis loeb tsükli käivitamise kordade arvu. Selles programmis eeldame, et rutiin jookseb tsüklit 10 korda ja loendus salvestatakse summana. Kutsute seda rutiini 3 korda, nii et koguarv peaks olema 30. Arv salvestatakse globaalsesse muutujate loendisse.
Esiteks käivitate programmi ilma mutexita
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) }
Vaadake tulemust
Count after i=1 Count: 11 Count after i=3 Count: 12 Count after i=2 Count: 13 Final Count: 13
Tulemus võib selle täitmisel olla erinev, kuid lõpptulemus ei ole 30.
Siin juhtub, et 3 gorutiini üritavad suurendada muutuja loendusesse salvestatud silmuste arvu. Oletame, et hetkel on arv 5 ja goroutine1 suurendab arvu 6-ni. Peamised sammud hõlmavad
Kopeeri loendur temp
Temp
Salvestage temperatuur loendamiseks
Oletame, et varsti pärast sammu 3 sooritamist goroutine1 poolt; teisel gorutiinil võib olla vana väärtus, näiteks 3 teeb ülaltoodud toimingud ja salvestab 4 tagasi, mis on vale. Seda saab vältida Mutexi kasutamisega, mis paneb teised rutiinid ootama, kui üks rutiin juba seda muutujat kasutab.
Nüüd käivitate programmi mutexiga. Siin teostatakse ülalmainitud 3 sammu mutexis.
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) }
Nüüd on väljund
Count after i=3 Count: 21 Count after i=2 Count: 28 Count after i=1 Count: 30 Final Count: 30
Siin saame lõppväljundina oodatud tulemuse. Kuna loenduse lugemise, suurendamise ja tagasikirjutamise avaldused täidetakse mutexis.
Viga käsitlemisel
Vead on ebanormaalsed tingimused, nagu faili sulgemine, mida ei avata, faili avamine, mida pole olemas, jne. Funktsioonid tagastavad tavaliselt vead viimase tagastatava väärtusena.
Allolev näide selgitab vea kohta lähemalt.
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") }
Väljundiks on:
open /invalid.txt: no such file or directory
Siin proovisime avada olematut faili ja see tagastas vea muutujale er. Kui fail on kehtiv, on viga null
Kohandatud vead
Seda funktsiooni kasutades saate luua kohandatud vigu. Seda tehakse veapaketi New() abil. Kirjutame ülaltoodud programmi ümber, et kasutada kohandatud vigu.
Käivitage allolev programm
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) } }
Väljundiks on:
Custom error message:File name is wrong
Siin tagastab area() ruudu pindala. Kui sisend on väiksem kui 1, tagastab area() veateate.
Failide lugemine
Andmete salvestamiseks kasutatakse faile. Go võimaldab meil failidest andmeid lugeda
Esmalt looge oma praeguses kataloogis alloleva sisuga fail data.txt.
Line one Line two Line three
Nüüd käivitage allolev programm, et näha, et see prindib väljundina kogu faili sisu
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)) }
Siin loeb andmed err := ioutil.ReadFile(“data.txt”) andmed ja tagastab baidijada. Printimise ajal teisendatakse see stringivormingusse.
Failide kirjutamine
Seda näete programmiga
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 } }
Siin luuakse fail test.txt. Kui fail on juba olemas, siis faili sisu kärbitakse. Writeline() kasutatakse faili sisu kirjutamiseks. Pärast seda sulgesite faili Close() abil.
Cheat Sheet
Selles Go õpetuses käsitlesime
teema | Kirjeldus | Süntaks |
---|---|---|
Põhitüübid | Numbrid, string, bool | |
Muutujad | Muutujate deklareerimine ja väärtuste määramine | muutuja_nime tüüp muutuja_nimi tüüp = väärtus muutuja_nimi1, muutuja_nimi2 = väärtus1, väärtus2 muutuja_nimi := väärtus |
Konstandid | Muutujad, mille väärtust ei saa pärast määramist muuta | const muutuja = väärtus |
Loopi jaoks | Käivitage avaldused tsüklina. | initsialiseerimise_väljenduse jaoks; hindamine_avaldis; iteratsiooni_avaldis{ // üks või mitu väidet } |
Kui veel | See on tingimuslik väide | if tingimus{ // väited_1 } Else { // väited_2 } |
lüliti | Tingimuslik avaldus mitme juhtumiga | lüliti avaldis { case value_1: avaldused_1 case value_2: avaldused_2 case value_n: avaldused_n default: avaldused_vaikeväärtus } |
Array | Fikseeritud suurusega nimega sama tüüpi elementide jada | massiivinimi := [suurus] tüüp {väärtus_0,väärtus_1,…,väärtus_suurus-1} |
Viil | Massiivi osa või segment | var slice_name [] type = massiivi_nimi[algus:lõpp] |
Funktsioonid | Avalduste plokk, mis täidab konkreetset ülesannet | func funktsiooni_nimi(parameetri_1 tüüp, parameetri_n tüüp) return_type { //avaldused } |
Paketid | Kasutatakse koodi korraldamiseks. Suurendab koodi loetavust ja korduvkasutatavust | impordi paketi_nimi |
Edasilükkamine | Lülitab funktsiooni täitmise edasi, kuni sisaldav funktsioon on täitmise lõpetanud | edasilükka funktsiooni_nimi(parameetrite_loend) |
viiteid | Salvestab teise muutuja mäluaadressi. | muutuja_nimi *tüüp |
struktuur | Kasutaja määratletud andmetüüp, mis ise sisaldab veel ühte sama või erinevat tüüpi elementi | tüüp structname struct { muutuja_1 muutuja_1_tüüp muutuja_2 muutuja_2_tüüp muutuja_n muutuja_n_tüüp } |
Meetodid | Meetod on vastuvõtja argumendiga funktsioon | func (muutuja muutujatüüp) methodName(parameetri_loend) { } |
Gorutine | Funktsioon, mis võib töötada samaaegselt teiste funktsioonidega. | go function_name(parameetrite_loend) |
Kanal | Funktsioonide üksteisega suhtlemise viis. Meedium, kuhu üks rutiin paigutab andmed ja millele pääseb juurde teine rutiin. | Kuulutama: ch := make(chan int) Saada andmed kanalile: kanali_muutuja <- muutuja_nimi Saate kanalilt: muutuja_nimi := <- kanali_muutuja |
valima | Lüliti avaldus, mis töötab kanalitel. Juhtumiavaldused on kanalioperatsioon. Kui mõni kanal on andmetega valmis, käivitatakse selle juhtumiga seotud avaldus | vali { juhtum x := <-chan1: fmt.Println(x) juhtum y := <-chan2: fmt.Println(y) } |
mutexid | Mutexi kasutatakse siis, kui te ei soovi lubada ressursile juurdepääsu korraga mitmele alamprogrammile. Mutexil on 2 meetodit – lukustada ja avada | mutex.Lock() //avaldused mutex.Unlock(). |
Lugege faile | Loeb andmed ja tagastab baidijada. | Andmed, err := ioutil.ReadFile(failinimi) |
Kirjuta faili | Kirjutab andmed faili | l, err := f.WriteString(kirjutatav_tekst) |