Tutorial Golang

Ce este Go?

Go (cunoscut ศ™i sub numele de Golang) este un limbaj de programare open source dezvoltat de Google. Este un limbaj compilat tipizat static. Go acceptฤƒ programarea concomitentฤƒ, adicฤƒ permite rularea mai multor procese simultan. Acest lucru se realizeazฤƒ folosind canale, goroutine, etc. Go Language are garbage collection care face ea รฎnsฤƒศ™i gestionarea memoriei ศ™i permite execuศ›ia amรขnatฤƒ a funcศ›iilor.

Vom รฎnvฤƒศ›a toate elementele de bazฤƒ ale Golang รฎn acest tutorial Learn Go Language.

Cum sฤƒ descฤƒrcaศ›i ศ™i sฤƒ instalaศ›i GO

Pas 1) Acceseazฤƒ https://golang.org/dl/. Descฤƒrcaศ›i binarul pentru sistemul dvs. de operare.

Pas 2) Double faceศ›i clic pe programul de instalare ศ™i faceศ›i clic pe Run.

Pas 3) Faceศ›i clic pe Urmฤƒtorul

Pas 4) Selectaศ›i folderul de instalare ศ™i faceศ›i clic pe Urmฤƒtorul.

Pas 5) Faceศ›i clic pe Terminare odatฤƒ ce instalarea este finalizatฤƒ.

Pas 6) Odatฤƒ ce instalarea este finalizatฤƒ, o puteศ›i verifica deschizรขnd terminalul ศ™i tastรขnd

go version

Aceasta va afiศ™a versiunea go instalatฤƒ

Programul First Go โ€“ Go Hello World!

Creaศ›i un folder numit studyGo. รŽn acest tutorial รฎn limba Go, vom crea programele noastre go รฎn interiorul acestui folder. Fiศ™ierele Go sunt create cu extensia .merge. Puteศ›i rula programe Go folosind sintaxa

go run <filename>

Creaศ›i un fiศ™ier numit first.go ศ™i adฤƒugaศ›i codul de mai jos รฎn el ศ™i salvaศ›i

package main
import ("fmt")

func main() {
	fmt.Println("Hello World! This is my first Go program\n")
}

Navigaศ›i la acest folder din terminalul dvs. Rulaศ›i programul folosind comanda

du-te fugi mai รฎntรขi.du-te

Puteศ›i vedea imprimarea de ieศ™ire

Hello World! This is my first Go program

Acum sฤƒ discutฤƒm despre programul de mai sus.

pachet principal โ€“ Fiecare program Go Language ar trebui sฤƒ รฎnceapฤƒ cu un nume de pachet. Go ne permite sฤƒ folosim pachete รฎn alte programe go ศ™i, prin urmare, acceptฤƒ reutilizarea codului. Execuศ›ia unui program Go รฎncepe cu codul din interiorul pachetului numit main.

import fmt โ€“ importฤƒ pachetul fmt. Acest pachet implementeazฤƒ funcศ›iile I/O.

func main() โ€“ Aceasta este funcศ›ia de la care รฎncepe execuศ›ia programului. Funcศ›ia principalฤƒ ar trebui sฤƒ fie รฎntotdeauna plasatฤƒ รฎn pachetul principal. Sub main(), puteศ›i scrie codul รฎn { }.

fmt.Println โ€“ Aceasta va imprima textul pe ecran prin funcศ›ia Println a fmt.

Notฤƒ: รŽn secศ›iunile de mai jos ale acestui tutorial Go, cรขnd menศ›ionaศ›i executarea/executarea codului, รฎnseamnฤƒ sฤƒ salvaศ›i codul รฎntr-un fiศ™ier cu extensia .go ศ™i sฤƒ รฎl rulaศ›i folosind sintaxa

    go run <filename>

Tipuri de date

Tipurile (tipurile de date) reprezintฤƒ tipul valorii stocate รฎntr-o variabilฤƒ, tipul valorii returnate de o funcศ›ie etc.

Existฤƒ trei tipuri de bazฤƒ รฎn Go Language

Tipuri numerice โ€“ Reprezintฤƒ valori numerice care includ valori รฎntregi, virgulฤƒ mobilฤƒ ศ™i complexe. Diferite tipuri numerice sunt:

int8 โ€“ numere รฎntregi cu semn pe 8 biศ›i.

int16 โ€“ numere รฎntregi cu semn pe 16 biศ›i.

int32 โ€“ numere รฎntregi cu semn pe 32 biศ›i.

int64 โ€“ numere รฎntregi cu semn pe 64 biศ›i.

uint8 โ€“ numere รฎntregi fฤƒrฤƒ semn pe 8 biศ›i.

uint16 โ€“ numere รฎntregi fฤƒrฤƒ semn pe 16 biศ›i.

uint32 โ€“ numere รฎntregi fฤƒrฤƒ semn pe 32 biศ›i.

uint64 โ€“ numere รฎntregi fฤƒrฤƒ semn pe 64 biศ›i.

float32 โ€“ numere รฎn virgulฤƒ mobilฤƒ pe 32 de biศ›i.

float64 โ€“ numere รฎn virgulฤƒ mobilฤƒ pe 64 de biศ›i.

complex64 โ€“ are float32 pฤƒrศ›i reale ศ™i imaginare.

complex128 โ€“ are float32 pฤƒrศ›i reale ศ™i imaginare.

Tipuri de ศ™iruri โ€“ Reprezintฤƒ o secvenศ›ฤƒ de octeศ›i (caractere). Puteศ›i face diverse operaศ›ii pe ศ™iruri, cum ar fi concatenarea ศ™irurilor, extragerea subศ™irurilor etc

Tipuri booleene โ€“ Reprezintฤƒ 2 valori, fie adevฤƒrate fie false.

Interfaศ›a Golang

Interfaศ›a Golang este o colecศ›ie de semnฤƒturi de metodฤƒ utilizatฤƒ de un tip pentru a implementa comportamentul obiectelor. Scopul principal al interfeศ›ei Golang este de a oferi semnฤƒturi de metodฤƒ cu nume, argumente ศ™i tipuri de returnare. Este la latitudinea unui Type sฤƒ declare ศ™i sฤƒ implementeze metoda. O interfaศ›ฤƒ รฎn Golang poate fi declaratฤƒ folosind cuvรขntul cheie โ€žinterfaศ›ฤƒโ€.

Variabile

Variabilele indicฤƒ o locaศ›ie de memorie care stocheazฤƒ un fel de valoare. Parametrul tip (รฎn sintaxa de mai jos) reprezintฤƒ tipul de valoare care poate fi stocatฤƒ รฎn locaศ›ia de memorie.

Variabila poate fi declaratฤƒ folosind sintaxa

    var <variable_name> <type>

Odatฤƒ ce declaraศ›i o variabilฤƒ de tip, puteศ›i atribui variabila oricฤƒrei valori de tipul respectiv.

De asemenea, puteศ›i da o valoare iniศ›ialฤƒ unei variabile รฎn timpul declaraศ›iei รฎn sine folosind

    var <variable_name> <type> = <value>

Dacฤƒ declaraศ›i variabila cu o valoare iniศ›ialฤƒ, mergeศ›i ศ™i deduceศ›i tipul variabilei din tipul valorii atribuite. Deci, puteศ›i omite tipul รฎn timpul declaraศ›iei folosind sintaxa

    var <variable_name> = <value>

De asemenea, puteศ›i declara mai multe variabile cu sintaxa

    var <variable_name1>, <variable_name2>  = <value1>, <value2>

Programul de mai jos din acest tutorial Go are cรขteva exemple Golang de declaraศ›ii de variabile

 
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)
}

Ieศ™irea va fi

x: 3
y: 20
z: 50
i and j: 100 hello

Go Language oferฤƒ, de asemenea, o modalitate uศ™oarฤƒ de a declara variabilele cu valoare prin omiterea cuvรขntului cheie var folosind

    <variable_name> := <value>

Reศ›ineศ›i cฤƒ aศ›i folosit := รฎn loc de =. Nu puteศ›i folosi := doar pentru a atribui o valoare unei variabile care este deja declaratฤƒ. := este folosit pentru a declara ศ™i a atribui valoare.

Creaศ›i un fiศ™ier numit assign.go cu urmฤƒtorul cod

package main
import ("fmt")

func main() {
	a := 20
	fmt.Println(a)

	//gives error since a is already declared
	a := 30
	fmt.Println(a)
}

Executaศ›i go run assign.go pentru a vedea rezultatul ca

./assign.go:7:4: no new variables on left side of :=		

Variabilele declarate fฤƒrฤƒ valoare iniศ›ialฤƒ vor avea 0 pentru tipurile numerice, false pentru boolean ศ™i ศ™ir gol pentru ศ™iruri

constante

Variabilele constante sunt acele variabile a cฤƒror valoare nu poate fi modificatฤƒ odatฤƒ ce au fost atribuite. O constantฤƒ รฎn limbajul de programare Go este declaratฤƒ prin utilizarea cuvรขntului cheie โ€žconstโ€

Creaศ›i un fiศ™ier numit constant.go ศ™i cu urmฤƒtorul cod

package main
import ("fmt")

func main() {
	const b =10
	fmt.Println(b)
	b = 30
	fmt.Println(b)
}

Executaศ›i go run constant.go pentru a vedea rezultatul ca

.constant.go:7:4: cannot assign to b

Pentru exemple de buclฤƒ

Buclele sunt folosite pentru a executa un bloc de instrucศ›iuni รฎn mod repetat pe baza unei condiศ›ii. Majoritatea limbajelor de programare oferฤƒ 3 tipuri de bucle - for, while, do while. Dar limbajul de programare Go acceptฤƒ doar bucla for.

Sintaxa unei bucle pentru Golang este

for initialisation_expression; evaluation_expression; iteration_expression{
   // one or more statement
}

Expresia_iniศ›ializare este executatฤƒ mai รฎntรขi (ศ™i doar o datฤƒ) รฎn Golang pentru bucla.

Apoi evaluation_expression este evaluatฤƒ ศ™i dacฤƒ este adevฤƒrat, codul din interiorul blocului este executat.

Id-ul expresiei_iteraศ›ie este executat, iar expresia_evaluฤƒrii este evaluat din nou. Dacฤƒ este adevฤƒrat, blocul de instrucศ›iuni este executat din nou. Aceasta va continua pรขnฤƒ cรขnd expresia_evaluare devine falsฤƒ.

Copiaศ›i programul de mai jos รฎntr-un fiศ™ier ศ™i executaศ›i-l pentru a vedea Golang pentru numere de tipฤƒrire รฎn buclฤƒ de la 1 la 5

package main
import "fmt"

func main() {  
var i int
for i = 1; i <= 5; i++ {
fmt.Println(i)
    }
}

Ieศ™irea este

1
2
3
4
5

Dacฤƒ altceva

Dacฤƒ else este o declaraศ›ie condiศ›ionatฤƒ. Sinaxa este

if condition{
// statements_1
}else{
// statements_2
}

Aici condiศ›ia este evaluatฤƒ ศ™i dacฤƒ este adevฤƒratฤƒ instrucศ›iunile_1 vor fi executate, altfel vor fi executate instrucศ›iunile_2.

Puteศ›i folosi declaraศ›ia if ศ™i fฤƒrฤƒ else. De asemenea, puteศ›i avea declaraศ›ii if else รฎnlฤƒnศ›uite. Programele de mai jos vor explica mai multe despre dacฤƒ altfel.

Executaศ›i programul de mai jos. Verificฤƒ dacฤƒ un numฤƒr, x, este mai mic de 10. Dacฤƒ da, va afiศ™a โ€žx este mai mic de 10โ€

package main
import "fmt"

func main() {  
    var x = 50
    if x < 10 {
        //Executes if x < 10
        fmt.Println("x is less than 10")
    } 
}

Aici, deoarece valoarea lui x este mai mare decรขt 10, instrucศ›iunea din interiorul dacฤƒ condiศ›ia blocului nu va fi executatฤƒ.

Acum vedeศ›i programul de mai jos. รŽn acest tutorial despre limbajul de programare Go, avem un bloc else care va fi executat la eศ™ecul evaluฤƒrii if.

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")
    }
}

Acest program vฤƒ va oferi rezultate

x is greater than or equals 10

Acum, รฎn acest tutorial Go, vom vedea un program cu mai multe blocuri if else (รฎnlฤƒnศ›uite dacฤƒ else). Executaศ›i exemplul Go de mai jos. Verificฤƒ dacฤƒ un numฤƒr este mai mic de 10 sau este รฎntre 10-90 sau mai mare de 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")
    }
}

Aici, mai รฎntรขi, condiศ›ia if verificฤƒ dacฤƒ x este mai mic de 10 ศ™i nu este. Deci verificฤƒ urmฤƒtoarea condiศ›ie (altfel dacฤƒ) dacฤƒ este รฎntre 10 ศ™i 90, ceea ce este, de asemenea, fals. Deci apoi executฤƒ blocul din secศ›iunea else care dฤƒ rezultatul

x is greater than 90

Intrerupator

Switch este o altฤƒ declaraศ›ie condiศ›ionatฤƒ. Instrucศ›iunile Switch evalueazฤƒ o expresie ศ™i rezultatul este comparat cu un set de valori disponibile (cazuri). Odatฤƒ ce o potrivire este gฤƒsitฤƒ, instrucศ›iunile asociate cu acea potrivire (caz) sunt executate. Dacฤƒ nu se gฤƒseศ™te nicio potrivire, nimic nu va fi executat. De asemenea, puteศ›i adฤƒuga un caz implicit pentru comutare, care va fi executat dacฤƒ nu sunt gฤƒsite alte potriviri. Sintaxa comutatorului este

switch expression {
    case value_1:
        statements_1
    case value_2:
        statements_2
    case value_n:
        statements_n
    default:
        statements_default
    }

Aici valoarea expresiei este comparatฤƒ cu valorile din fiecare caz. Odatฤƒ ce este gฤƒsitฤƒ o potrivire, instrucศ›iunile asociate cu acel caz sunt executate. Dacฤƒ nu se gฤƒseศ™te nicio potrivire, instrucศ›iunile din secศ›iunea implicitฤƒ sunt executate.

Executaศ›i programul de mai jos

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")
    }
}

Veศ›i obศ›ine rezultatul ca

Sum is 3		

Schimbaศ›i valoarea lui a ศ™i b la 3 ศ™i rezultatul va fi

Printing default

De asemenea, puteศ›i avea mai multe valori รฎntr-un caz, separรขndu-le cu virgulฤƒ.

Arrays

Array reprezintฤƒ o dimensiune fixฤƒ, numitฤƒ secvenศ›ฤƒ de elemente de acelaศ™i tip. Nu puteศ›i avea o matrice care conศ›ine atรขt numere รฎntregi, cรขt ศ™i caractere. Nu puteศ›i modifica dimensiunea unei matrice odatฤƒ ce aศ›i definit dimensiunea.

Sintaxa pentru declararea unui tablou este

var arrayname [size] type

Fiecฤƒrui element de matrice i se poate atribui o valoare folosind sintaxa

arrayname [index] = value

Indexul matricei รฎncepe de la 0 la mฤƒrimea-1.

Puteศ›i atribui valori elementelor de matrice รฎn timpul declaraศ›iei folosind sintaxa

arrayname := [size] type {value_0,value_1,โ€ฆ,value_size-1} 

De asemenea, puteศ›i ignora parametrul dimensiune รฎn timp ce declaraศ›i matricea cu valori, รฎnlocuind dimensiunea cu ... iar compilatorul va gฤƒsi lungimea din numฤƒrul de valori. Sintaxa este

arrayname :=  [โ€ฆ] type {value_0,value_1,โ€ฆ,value_size-1}

Puteศ›i gฤƒsi lungimea matricei folosind sintaxa

len(arrayname)

Executaศ›i exemplul Go de mai jos pentru a รฎnศ›elege matricea

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]) 
}

producศ›ie

Two
3
[One Two Three]
[1 2 3 4 5]
5

Golang Slice ศ™i funcศ›ie de adฤƒugare

O felie este o porศ›iune sau un segment dintr-o matrice. Sau este o vedere sau o vedere parศ›ialฤƒ a unui tablou subiacent cฤƒtre care indicฤƒ. Puteศ›i accesa elementele unei secศ›iuni folosind numele ศ™i numฤƒrul de index la fel ca รฎntr-o matrice. Nu puteศ›i modifica lungimea unei matrice, dar puteศ›i modifica dimensiunea unei felii.

Conศ›inutul unei felii sunt de fapt pointerii cฤƒtre elementele unui tablou. Inseamna dacฤƒ modificaศ›i orice element dintr-o felie, conศ›inutul matricei de bazฤƒ va fi de asemenea afectat.

Sintaxa pentru crearea unei felii este

var slice_name [] type = array_name[start:end]

Aceasta va crea o porศ›iune numitฤƒ slice_name dintr-o matrice numitฤƒ array_name cu elementele de la index de la รฎnceput la sfรขrศ™it-1.

Acum, รฎn acest tutorial Golang, vom executa programul de mai jos. Programul va crea o porศ›iune din matrice ศ™i o va imprima. De asemenea, puteศ›i vedea cฤƒ modificarea conศ›inutului din felie va modifica matricea realฤƒ.

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)
}

Acesta va imprima rezultatul ca

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]

Existฤƒ anumite funcศ›ii precum Golang len, Golang append pe care le puteศ›i aplica pe felii

len(nume_slice) โ€“ returneazฤƒ lungimea feliei

append(nume_slice, valoare_1, valoare_2) โ€“ Golang append este folosit pentru a adฤƒuga value_1 ศ™i value_2 la o porศ›iune existentฤƒ.

append(slice_nale1,slice_name2...) โ€“ adaugฤƒ slice_name2 la slice_name1

Executaศ›i urmฤƒtorul program.

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)
}

Ieศ™irea va fi

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]

Programul creeazฤƒ mai รฎntรขi 2 felii ศ™i i-a imprimat lungimea. Apoi a ataศ™at o felie la alta ศ™i apoi a ataศ™at un ศ™ir la felia rezultatฤƒ.

funcลฃii

O funcศ›ie reprezintฤƒ un bloc de instrucศ›iuni care รฎndeplineศ™te o anumitฤƒ sarcinฤƒ. O declaraศ›ie de funcศ›ie ne spune numele funcศ›iei, tipul de returnare ศ™i parametrii de intrare. Definiศ›ia funcศ›iei reprezintฤƒ codul conศ›inut รฎn funcศ›ie. Sintaxa pentru declararea funcศ›iei este

func function_name(parameter_1 type, parameter_n type) return_type {
//statements
}

Parametrii ศ™i tipurile de returnare sunt opศ›ionale. De asemenea, puteศ›i returna mai multe valori dintr-o funcศ›ie.

Acum, รฎn acest tutorial Golang, sฤƒ rulฤƒm urmฤƒtorul exemplu Golang. Aici funcศ›ia numitฤƒ calc va accepta 2 numere ศ™i efectueazฤƒ adunarea ศ™i scฤƒderea ศ™i returneazฤƒ ambele valori.

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) 
}

Ieศ™irea va fi

Sum 25
Diff 5

Pachete

Pachetele sunt folosite pentru a organiza codul. รŽntr-un proiect mare, nu este fezabil sฤƒ scrieศ›i cod รฎntr-un singur fiศ™ier. Limbajul de programare Go ne permite sฤƒ organizฤƒm codul รฎn diferite pachete. Acest lucru creศ™te lizibilitatea ศ™i reutilizarea codului. Un program Go executabil ar trebui sฤƒ conศ›inฤƒ un pachet numit main ศ™i execuศ›ia programului รฎncepe de la funcศ›ia numitฤƒ main. Puteศ›i importa alte pachete รฎn programul nostru folosind sintaxa

import package_name

Vom vedea ศ™i discuta รฎn acest tutorial Golang, cum sฤƒ creaศ›i ศ™i sฤƒ utilizaศ›i pachete รฎn urmฤƒtorul exemplu Golang.

Pas 1) Creaศ›i un fiศ™ier numit package_example.go ศ™i adฤƒugaศ›i codul de mai jos

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) 
}

รŽn programul de mai sus, fmt este un pachet pe care limbajul de programare Go ni-l oferฤƒ รฎn principal pentru scopuri I/O. De asemenea, puteศ›i vedea un pachet numit calcul. รŽn interiorul main() puteศ›i vedea o sumฤƒ pasฤƒ := calcul.Do_add(x,y). รŽnseamnฤƒ cฤƒ invocaศ›i funcศ›ia Do_add din calculul pachetului.

Pas 2) รŽn primul rรขnd, ar trebui sฤƒ creaศ›i calculul pachetului รฎntr-un folder cu acelaศ™i nume sub folderul src din go. Calea instalatฤƒ a go poate fi gฤƒsitฤƒ din variabila PATH.

Pentru Mac, gฤƒsiศ›i calea executรขnd echo $PATH

Deci calea este /usr/local/go

Pentru Windows, gฤƒsiศ›i calea executรขnd echo %GOROOT%

Aici calea este C:\Go\

Pas 3) Navigaศ›i la folderul src (/usr/local/go/src pentru Mac ศ™i C:\Go\src pentru Windows). Acum, din cod, numele pachetului este de calcul. Go necesitฤƒ ca pachetul sฤƒ fie plasat รฎntr-un director cu acelaศ™i nume sub directorul src. Creaศ›i un director numit calcul รฎn folderul src.

Pas 4) Creaศ›i un fiศ™ier numit calc.go (puteศ›i da orice nume, dar numele pachetului din cod conteazฤƒ. Aici ar trebui sฤƒ fie calcul) รฎn directorul de calcul ศ™i adฤƒugaศ›i codul de mai jos

package calculation
  
func Do_add(num1 int, num2 int)(int) {
    sum := num1 + num2
    return sum
}

Pas 5) Rulaศ›i comanda go install din directorul de calcul care va compila calc.go.

Pas 6) Acum reveniศ›i la package_example.go ศ™i rulaศ›i go run package_example.go. Ieศ™irea va fi Suma 25.

Reศ›ineศ›i cฤƒ numele funcศ›iei Do_add รฎncepe cu o literฤƒ majusculฤƒ. Acest lucru se datoreazฤƒ faptului cฤƒ รฎn Go, dacฤƒ numele funcศ›iei รฎncepe cu o literฤƒ majusculฤƒ, รฎnseamnฤƒ cฤƒ alte programe รฎl pot vedea (accesa), altfel alte programe nu รฎl pot accesa. Dacฤƒ numele funcศ›iei a fost do_add , atunci aศ›i fi primit eroarea

nu se poate face referire la calculul numelui neexportat.calc..

Amรขnare ศ™i stivuire amรขnฤƒ

Instrucศ›iunile Defer sunt folosite pentru a amรขna execuศ›ia unui apel de funcศ›ie pรขnฤƒ cรขnd funcศ›ia care conศ›ine instrucศ›iunea defer finalizeazฤƒ execuศ›ia.

Sฤƒ รฎnvฤƒศ›ฤƒm asta cu un exemplu:

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()")
}

Ieศ™irea va fi

Inside the main()
Inside the sample()

Aici execuศ›ia sample() este amรขnatฤƒ pรขnฤƒ cรขnd se finalizeazฤƒ execuศ›ia funcศ›iei incluse(main()).

Stacking defer foloseศ™te mai multe instrucศ›iuni defer. Sฤƒ presupunem cฤƒ aveศ›i mai multe instrucศ›iuni defer รฎn interiorul unei funcศ›ii. Go plaseazฤƒ toate apelurile de funcศ›ii amรขnate รฎntr-o stivฤƒ ศ™i, odatฤƒ ce funcศ›ia de รฎncadrare revine, funcศ›iile stivuite sunt executate รฎn Comanda Last In First Out (LIFO). Puteศ›i vedea acest lucru รฎn exemplul de mai jos.

Executaศ›i codul de mai jos

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)
}

Ieศ™irea va fi

4
3
2
1			

Aici codul din main() se executฤƒ mai รฎntรขi, iar apoi apelurile de funcศ›ii amรขnate sunt executate รฎn ordine inversฤƒ, adicฤƒ 4, 3,2,1.

Pointeri

รŽnainte de a explica indicatorii, sฤƒ discutฤƒm mai รฎntรขi despre operatorul โ€ž&โ€. Operatorul โ€ž&โ€ este folosit pentru a obศ›ine adresa unei variabile. รŽnseamnฤƒ cฤƒ โ€ž&aโ€ va tipฤƒri adresa de memorie a variabilei a.

รŽn acest tutorial Golang, vom executa programul de mai jos pentru a afiศ™a valoarea unei variabile ศ™i adresa acelei variabile

package main
import "fmt"

func main() {
	a := 20
	fmt.Println("Address:",&a)
	fmt.Println("Value:",a)
}

Rezultatul va fi

Address: 0xc000078008
Value: 20

O variabilฤƒ pointer stocheazฤƒ adresa de memorie a altei variabile. Puteศ›i defini un pointer folosind sintaxa

	var variable_name *type

Asteriscul(*) reprezintฤƒ variabila este un pointer. Veศ›i รฎnศ›elege mai multe executรขnd programul de mai jos

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)}

Ieศ™irea va fi

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

Structuri

O structurฤƒ este un tip de date definit de utilizator, care conศ›ine รฎncฤƒ un element de acelaศ™i tip sau diferit.

Utilizarea unei structuri este un proces รฎn 2 etape.

Mai รฎntรขi, creaศ›i (declaraศ›i) un tip de structurฤƒ

รŽn al doilea rรขnd, creaศ›i variabile de acest tip pentru a stoca valori.

Structurile sunt utilizate รฎn principal atunci cรขnd doriศ›i sฤƒ stocaศ›i รฎmpreunฤƒ date asociate.

Luaศ›i รฎn considerare o informaศ›ie despre angajaศ›i care are numele, vรขrsta ศ™i adresa. Puteศ›i gestiona asta รฎn 2 moduri

Creaศ›i 3 matrice - o matrice stocheazฤƒ numele angajaศ›ilor, una stocheazฤƒ vรขrsta ศ™i al treilea stocheazฤƒ vรขrsta.

Declaraศ›i un tip de structurฤƒ cu 3 cรขmpuri - nume, adresฤƒ ศ™i vรขrstฤƒ. Creaศ›i o matrice de acel tip de structurฤƒ รฎn care fiecare element este un obiect de structurฤƒ avรขnd nume, adresฤƒ ศ™i vรขrstฤƒ.

Prima abordare nu este eficientฤƒ. รŽn astfel de scenarii, structurile sunt mai convenabile.

Sintaxa pentru declararea unei structuri este

type structname struct {
   variable_1 variable_1_type
   variable_2 variable_2_type
   variable_n variable_n_type
}

Un exemplu de declaraศ›ie de structurฤƒ este

type emp struct {
    name string
    address string
    age int
}

Aici este creat un nou tip definit de utilizator numit emp. Acum, puteศ›i crea variabile de tip emp folosind sintaxa

	var variable_name struct_name

Un exemplu este

var empdata1 emp 

Puteศ›i seta valori pentru empdata1 ca

empdata1.name = "John"
	empdata1.address = "Street-1, Bangalore"
	empdata1.age = 30

De asemenea, puteศ›i crea o variabilฤƒ de structurฤƒ ศ™i aloca valori prin

empdata2 := emp{"Raj", "Building-1, Delhi", 25}

Aici, trebuie sฤƒ menศ›ineศ›i ordinea elementelor. Raj va fi mapat dupฤƒ nume, urmฤƒtorul element de adresat ศ™i ultimul pentru vรขrsta.

Executaศ›i codul de mai jos

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)
}

producศ›ie

John
Raj

Metode (nu funcศ›ii)

O metodฤƒ este o funcศ›ie cu un argument receptor. Archidin punct de vedere tehnic, este รฎntre cuvรขntul cheie func ศ™i numele metodei. Sintaxa unei metode este

func (variable variabletype) methodName(parameter1 paramether1type) {  
}

Sฤƒ convertim exemplul de program de mai sus pentru a folosi metode รฎn loc de funcศ›ie.

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 nu este un limbaj orientat pe obiecte ศ™i nu are conceptul de clasฤƒ. Metodele oferฤƒ o imagine a ceea ce faci รฎn programele orientate pe obiecte รฎn care funcศ›iile unei clase sunt invocate folosind sintaxa nume obiect.numefuncศ›ie()

Concurenta

Go acceptฤƒ executarea concomitentฤƒ a sarcinilor. รŽnseamnฤƒ cฤƒ Go poate executa mai multe sarcini simultan. Este diferit de conceptul de paralelism. รŽn paralelism, o sarcinฤƒ este รฎmpฤƒrศ›itฤƒ รฎn subsarcini mici ศ™i sunt executate รฎn paralel. Dar รฎn concurenศ›ฤƒ, mai multe sarcini sunt executate simultan. Concurenศ›a se realizeazฤƒ รฎn Go folosind Goroutines ศ™i Canale.

Goroutine

O goroutine este o funcศ›ie care poate rula concomitent cu alte funcศ›ii. De obicei, atunci cรขnd o funcศ›ie este invocatฤƒ, controlul este transferat รฎn funcศ›ia apelatฤƒ ศ™i, odatฤƒ finalizatฤƒ, controlul de execuศ›ie revine la funcศ›ia de apelare. Funcศ›ia de apelare รฎศ™i continuฤƒ apoi execuศ›ia. Funcศ›ia apelantฤƒ aศ™teaptฤƒ ca funcศ›ia invocatฤƒ sฤƒ finalizeze execuศ›ia รฎnainte de a continua cu restul instrucศ›iunilor.

Dar รฎn cazul goroutine, funcศ›ia de apelare nu va aศ™tepta finalizarea execuศ›iei funcศ›iei invocate. Va continua sฤƒ se execute cu urmฤƒtoarele instrucศ›iuni. Puteศ›i avea mai multe goroutine รฎntr-un program.

De asemenea, programul principal se va รฎnchide odatฤƒ ce รฎศ™i รฎncheie executarea instrucศ›iunilor ศ™i nu va aศ™tepta finalizarea goroutinelor invocate.

Goroutine este invocatฤƒ folosind cuvรขntul cheie go urmat de un apel de funcศ›ie.

Exemplu

go add(x,y)

Veศ›i รฎnศ›elege goroutine cu exemplele Golang de mai jos. Executaศ›i programul de mai jos

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")
	}
}

Ieศ™irea va fi

In main
In main
In main
In main
In main

Aici programul principal ศ™i-a รฎncheiat execuศ›ia chiar รฎnainte de a รฎncepe goroutine. Display() este o rutinฤƒ care este invocatฤƒ folosind sintaxa

go function_name(parameter list)

รŽn codul de mai sus, main() nu aศ™teaptฤƒ ca display() sฤƒ se finalizeze, iar main() ศ™i-a รฎncheiat execuศ›ia รฎnainte ca display() sฤƒ-ศ™i execute codul. Deci declaraศ›ia print din display() nu a fost tipฤƒritฤƒ.

Acum modificฤƒm programul pentru a imprima instrucศ›iunile ศ™i din display(). Adฤƒugฤƒm o รฎntรขrziere de 2 secunde รฎn bucla for a main() ศ™i o รฎntรขrziere de 1 secundฤƒ รฎn bucla for a afiศ™ajului().

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")
	}
}

Ieศ™irea va fi oarecum similarฤƒ cu

In display
In main
In display
In display
In main
In display
In display
In main
In main
In main

Aici puteศ›i vedea cฤƒ ambele bucle sunt executate รฎntr-un mod suprapus din cauza execuศ›iei concurente.

Canale

Canalele sunt o modalitate prin care funcศ›iile pot comunica รฎntre ele. Poate fi considerat ca un mediu รฎn care o rutinฤƒ plaseazฤƒ date ศ™i este accesatฤƒ de o altฤƒ rutinฤƒ pe serverul Golang.

Un canal poate fi declarat cu sintaxa

channel_variable := make(chan datatype)

Exemplu:

	ch := make(chan int)

Puteศ›i trimite date cฤƒtre un canal folosind sintaxa

channel_variable <- variable_name

Exemplu

    ch <- x

Puteศ›i primi date de la un canal folosind sintaxa

    variable_name := <- channel_variable

Exemplu

   y := <- ch

รŽn exemplele de limbฤƒ Go de mai sus de goroutine, aศ›i vฤƒzut cฤƒ programul principal nu aศ™teaptฤƒ goroutine. Dar nu este cazul cรขnd sunt implicate canale. Sฤƒ presupunem cฤƒ dacฤƒ o rutinฤƒ รฎmpinge date cฤƒtre canal, main() va aศ™tepta instrucศ›iunea care primeศ™te datele canalului pรขnฤƒ cรขnd primeศ™te datele.

Veศ›i vedea acest lucru รฎn exemplele de limbฤƒ Go de mai jos. Mai รฎntรขi, scrieศ›i o rutinฤƒ normalฤƒ ศ™i vedeศ›i comportamentul. Apoi modificaศ›i programul pentru a utiliza canale ศ™i a vedea comportamentul.

Executaศ›i programul de mai jos

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()")
}

Ieศ™irea va fi

Inside main()

Main() a terminat execuศ›ia ศ™i a ieศ™it รฎnainte ca goroutine sฤƒ se execute. Deci tipฤƒrirea din interiorul display() nu a fost executatฤƒ.

Acum modificaศ›i programul de mai sus pentru a utiliza canalele ศ™i a vedea comportamentul.

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)
}

Ieศ™irea va fi

Inside display()
Inside main()
Printing x in main() after taking from channel: 1234

Aici ceea ce se รฎntรขmplฤƒ este main() la atingerea x := <-ch va aศ™tepta date pe canalul ch. Display-ul () are o aศ™teptare de 5 secunde ศ™i apoi รฎmpinge datele cฤƒtre canalul de canal. Main() la primirea datelor de la canal este deblocat ศ™i รฎศ™i continuฤƒ execuศ›ia.

Expeditorul care transmite date pe canal poate informa receptorii cฤƒ nu vor mai fi adฤƒugate date la canal prin รฎnchiderea canalului. Acesta este folosit รฎn principal atunci cรขnd utilizaศ›i o buclฤƒ pentru a รฎmpinge date cฤƒtre un canal. Un canal poate fi รฎnchis folosind

close(channel_name)

ศ˜i la capฤƒtul receptorului, este posibil sฤƒ verificaศ›i dacฤƒ canalul este รฎnchis folosind o variabilฤƒ suplimentarฤƒ รฎn timp ce preluaศ›i date de pe canal folosind

variable_name, status := <- channel_variable

Dacฤƒ starea este True รฎnseamnฤƒ cฤƒ aศ›i primit date de la canal. Dacฤƒ este fals, รฎnseamnฤƒ cฤƒ รฎncercaศ›i sฤƒ citiศ›i de pe un canal รฎnchis

De asemenea, puteศ›i utiliza canale pentru comunicarea รฎntre goroutine. Trebuie sฤƒ utilizaศ›i 2 goroutine - unul รฎmpinge datele cฤƒtre canal, iar celฤƒlalt primeศ™te datele de la canal. Vezi programul de mai jos

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()")
}

Aici existฤƒ 2 subrutine, una รฎmpinge datele cฤƒtre canal ศ™i cealaltฤƒ imprimฤƒ datele cฤƒtre canal. Funcศ›ia add_to_channel adaugฤƒ numerele de la 0 la 9 ศ™i รฎnchide canalul. Simultan, funcศ›ia fetch_from_channel aศ™teaptฤƒ la

x, flag := <- ch ศ™i odatฤƒ ce datele devin disponibile, se tipฤƒreศ™te datele. Iese odatฤƒ ce steagul este fals, ceea ce รฎnseamnฤƒ cฤƒ canalul este รฎnchis.

Aศ™teptarea รฎn main() este datฤƒ pentru a preveni ieศ™irea din main() pรขnฤƒ cรขnd goroutines terminฤƒ execuศ›ia.

Executaศ›i codul ศ™i vedeศ›i rezultatul ca

Read data
Send data
0
1
2
3
4
5
6
7
8
9
Empty channel
Inside main()

Selectaศ›i

Select poate fi vฤƒzut ca o declaraศ›ie de comutare care funcศ›ioneazฤƒ pe canale. Aici declaraศ›iile de caz vor fi o operaศ›iune de canal. De obicei, fiecare declaraศ›ie de caz va fi cititฤƒ รฎncercare de pe canal. Cรขnd oricare dintre cazuri este gata (canalul este citit), atunci instrucศ›iunea asociatฤƒ cu acel caz este executatฤƒ. Dacฤƒ sunt pregฤƒtite mai multe cazuri, va alege unul aleatoriu. Puteศ›i avea un caz implicit care este executat dacฤƒ niciunul dintre cazuri nu este pregฤƒtit.

Sฤƒ vedem codul de mai jos

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)
    }
}

Executarea programului de mai sus va da rezultatul:

from data2()

Aici declaraศ›ia select aศ™teaptฤƒ ca datele sฤƒ fie disponibile pe oricare dintre canale. Data2() adaugฤƒ date la canal dupฤƒ un somn de 2 secunde, ceea ce va determina executarea celui de-al doilea caz.

Adฤƒugaศ›i un caz implicit la selectare รฎn acelaศ™i program ศ™i vedeศ›i rezultatul. Aici, la atingerea blocului select, dacฤƒ niciun caz nu are date pregฤƒtite pe canal, acesta va executa blocul implicit fฤƒrฤƒ a aศ™tepta ca datele sฤƒ fie disponibile pe orice canal.

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")
    }
}

Acest program va da rezultatul:

Default case executed			

Acest lucru se datoreazฤƒ faptului cฤƒ, atunci cรขnd a ajuns blocul de selectare, niciun canal nu avea date de citit. Deci, cazul implicit este executat.

mutex

Mutex este forma scurtฤƒ pentru excluderea reciprocฤƒ. Mutex este folosit atunci cรขnd nu doriศ›i sฤƒ permiteศ›i accesarea unei resurse de mai multe subrutine รฎn acelaศ™i timp. Mutex are 2 metode โ€“ Blocare ศ™i deblocare. Mutex este conศ›inut รฎn pachetul de sincronizare. Deci, trebuie sฤƒ importaศ›i pachetul de sincronizare. Instrucศ›iunile care trebuie sฤƒ fie executate reciproc exclusiv pot fi plasate รฎn interiorul mutex.Lock() ศ™i mutex.Unlock().

Sฤƒ รฎnvฤƒศ›ฤƒm mutex cu un exemplu care numฤƒrฤƒ de cรขte ori este executatฤƒ o buclฤƒ. รŽn acest program ne aศ™teptฤƒm ca rutina sฤƒ ruleze bucla de 10 ori ศ™i numฤƒrul este stocat รฎn sumฤƒ. Apelaศ›i aceastฤƒ rutinฤƒ de 3 ori, astfel รฎncรขt numฤƒrul total ar trebui sฤƒ fie 30. Numฤƒrul este stocat รฎntr-un numฤƒr global de variabile.

รŽn primul rรขnd, rulaศ›i programul fฤƒrฤƒ mutex

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)
}

Vezi rezultatul

 Count after i=1 Count: 11
Count after i=3 Count: 12
Count after i=2 Count: 13
Final Count: 13

Rezultatul poate fi diferit atunci cรขnd รฎl executaศ›i, dar rezultatul final nu va fi 30.

Aici ceea ce se รฎntรขmplฤƒ este cฤƒ 3 goroutine รฎncearcฤƒ sฤƒ mฤƒreascฤƒ numฤƒrul de bucle stocat รฎn numฤƒrul de variabile. Sฤƒ presupunem cฤƒ la un moment dat numฤƒrul este 5 ศ™i goroutine1 va creศ™te numฤƒrul la 6. Paศ™ii principali includ

Numฤƒr de copii la temp

Creศ™teศ›i temperatura

Stocaศ›i temperatura รฎnapoi pentru a numฤƒra

Sฤƒ presupunem cฤƒ la scurt timp dupฤƒ efectuarea pasului 3 de cฤƒtre goroutine1; o altฤƒ goroutinฤƒ ar putea avea o valoare veche, sฤƒ spunem cฤƒ 3 face paศ™ii de mai sus ศ™i stocheazฤƒ 4 รฎnapoi, ceea ce este greศ™it. Acest lucru poate fi prevenit prin utilizarea mutex care face ca alte rutine sฤƒ aศ™tepte atunci cรขnd o rutinฤƒ foloseศ™te deja variabila.

Acum veศ›i rula programul cu mutex. Aici cei 3 paศ™i menศ›ionaศ›i mai sus sunt executaศ›i รฎntr-un mutex.

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)
}

Acum ieศ™irea va fi

 Count after i=3 Count: 21
Count after i=2 Count: 28
Count after i=1 Count: 30
Final Count: 30

Aici obศ›inem rezultatul aศ™teptat ca rezultat final. Deoarece instrucศ›iunile de citire, creศ™tere ศ™i rescriere a numฤƒrului sunt executate รฎntr-un mutex.

Eroare de manipulare

Erorile sunt condiศ›ii anormale, cum ar fi รฎnchiderea unui fiศ™ier care nu este deschis, deschiderea unui fiศ™ier care nu existฤƒ, etc. Funcศ›iile returneazฤƒ de obicei erori ca ultima valoare returnatฤƒ.

Exemplul de mai jos explicฤƒ mai multe despre eroare.

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")
}

Ieศ™irea va fi:

open /invalid.txt: no such file or directory

Aici am รฎncercat sฤƒ deschidem un fiศ™ier inexistent ศ™i a returnat eroarea variabilei. Dacฤƒ fiศ™ierul este valid, atunci eroarea va fi nulฤƒ

Erori personalizate

Folosind aceastฤƒ funcศ›ie, puteศ›i crea erori personalizate. Acest lucru se face prin utilizarea New() a pachetului de erori. Vom rescrie programul de mai sus pentru a folosi erorile personalizate.

Rulaศ›i programul de mai jos

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)
    }  
}

Ieศ™irea va fi:

Custom error message:File name is wrong

Aici area() returneazฤƒ aria unui pฤƒtrat. Dacฤƒ intrarea este mai micฤƒ de 1, atunci area() returneazฤƒ un mesaj de eroare.

Citirea fiศ™ierelor

Fiศ™ierele sunt folosite pentru stocarea datelor. Go ne permite sฤƒ citim date din fiศ™iere

Mai รฎntรขi creaศ›i un fiศ™ier, data.txt, รฎn directorul dvs. actual cu conศ›inutul de mai jos.

Line one
Line two
Line three

Acum rulaศ›i programul de mai jos pentru a vedea cฤƒ imprimฤƒ conศ›inutul รฎntregului fiศ™ier ca rezultat

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))
}

Aici datele, err := ioutil.ReadFile(โ€œdata.txtโ€) citeศ™te datele ศ™i returneazฤƒ o secvenศ›ฤƒ de octeศ›i. รŽn timpul imprimฤƒrii, acesta este convertit รฎn format ศ™ir.

Scrierea fiศ™ierelor

Veศ›i vedea asta cu un program

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
    }
}

Aici este creat un fiศ™ier, test.txt. Dacฤƒ fiศ™ierul existฤƒ deja, atunci conศ›inutul fiศ™ierului este trunchiat. Writeline() este folosit pentru a scrie conศ›inutul fiศ™ierului. Dupฤƒ aceea, aศ›i รฎnchis fiศ™ierul folosind Close().

Cheat Sheet

รŽn acest tutorial Go, am acoperit,

Subiect Descriere Sintaxฤƒ
Tipuri de bazฤƒ Numeric, ศ™ir, bool
Variabile Declaraศ›i ศ™i atribuiศ›i valori variabilelor var tipul nume_variabilฤƒ
var nume_variabilฤƒ tip = valoare
var nume_variabilฤƒ1, nume_variabilฤƒ2 = valoare1, valoare2
nume_variabilฤƒ := valoare
constante Variabile a cฤƒror valoare nu poate fi modificatฤƒ odatฤƒ ce au fost atribuite const variabilฤƒ = valoare
Pentru Loop Executaศ›i instrucศ›iuni รฎntr-o buclฤƒ. pentru initialisation_expression; expresie_evaluare; expresie_iteraศ›ie{
// una sau mai multe declaraศ›ii
}
Dacฤƒ altceva Este o declaraศ›ie condiศ›ionatฤƒ dacฤƒ condiศ›ia{
// declaraศ›ii_1
} else {
// declaraศ›ii_2
}
comuta Declaraศ›ie condiศ›ionatฤƒ cu mai multe cazuri schimba expresia {
valoarea cazului_1:
declaraศ›ii_1
valoarea cazului_2:
declaraศ›ii_2
case value_n:
declaraศ›ii_n
implicit:
statements_default
}
Mulศ›ime Secvenศ›ฤƒ de nume de dimensiune fixฤƒ โ€‹โ€‹a elementelor de acelaศ™i tip arrayname := [dimensiune] tip {value_0,value_1,โ€ฆ,value_size-1}
Felie Porศ›iune sau segment dintr-o matrice var slice_name [] type = array_name[start:end]
funcลฃii Bloc de declaraศ›ii care รฎndeplineศ™te o anumitฤƒ sarcinฤƒ func function_name(parameter_1 type, parameter_n type) return_type {
//instrucศ›iuni
}
Pachete Sunt folosite pentru a organiza codul. Mฤƒreศ™te lizibilitatea ศ™i reutilizarea codului import package_nam
Amรขna Amรขnฤƒ execuศ›ia unei funcศ›ii pรขnฤƒ cรขnd funcศ›ia care o conศ›ine terminฤƒ execuศ›ia defer function_name(lista_parametri)
Pointeri Stocheazฤƒ adresa de memorie a unei alte variabile. var nume_variabilฤƒ *tip
Structure Tip de date definit de utilizator, care conศ›ine รฎncฤƒ un element de acelaศ™i tip sau diferit tip structname struct {
variabilฤƒ_1 variabilฤƒ_1_tip
variabilฤƒ_2 variabilฤƒ_2_tip
variabilฤƒ_n variabilฤƒ_n_tip
}
Aplicate O metodฤƒ este o funcศ›ie cu un argument receptor func (variabilฤƒ tip variabilฤƒ) methodName(lista_parametri) {
}
Goroutine O funcศ›ie care poate rula concomitent cu alte funcศ›ii. mergeศ›i numele_funcศ›iei(lista_parametrilor)
Canal Modul prin care funcศ›iile pot comunica รฎntre ele. Un mediu pe care o rutinฤƒ plaseazฤƒ date ศ™i este accesatฤƒ de o altฤƒ rutinฤƒ. Declara:
ch := make(chan int)
Trimiteศ›i date cฤƒtre canal:
variabilฤƒ_canal <- nume_variabilฤƒ
Primiศ›i de pe canal:
nume_variabilฤƒ := <- variabilฤƒ_canal
Selectaศ›i Declaraศ›ie Switch care funcศ›ioneazฤƒ pe canale. Declaraศ›iile de caz vor fi o operaศ›iune de canal. Cรขnd oricare dintre canale este gata cu date, atunci instrucศ›iunea asociatฤƒ cu acel caz este executatฤƒ Selectaศ›i {
caz x := <-chan1:
fmt.Println(x)
cazul y := <-chan2:
fmt.Println(y)
}
mutex Mutex este folosit atunci cรขnd nu doriศ›i sฤƒ permiteศ›i accesarea unei resurse de mai multe subrutine รฎn acelaศ™i timp. Mutex are 2 metode โ€“ Blocare ศ™i deblocare mutex.Lock()
//instrucศ›iuni
mutex.Unlock().
Citiศ›i fiศ™iere Citeศ™te datele ศ™i returneazฤƒ o secvenศ›ฤƒ de octeศ›i. Date, err := ioutil.ReadFile(nume fiศ™ier)
Scrieศ›i fiศ™ierul Scrie date รฎntr-un fiศ™ier l, err := f.WriteString(text_to_write)

Rezumaศ›i aceastฤƒ postare cu: