Tutoriel Golang

C'est quoi Go ?

Go (รฉgalement connu sous le nom de Golang) est un langage de programmation open source dรฉveloppรฉ par Google. C'est un langage compilรฉ ร  typage statique. Go prend en charge la programmation simultanรฉe, c'est-ร -dire qu'il permet d'exรฉcuter plusieurs processus simultanรฉment. Ceci est rรฉalisรฉ ร  l'aide de canaux, de goroutines, etc. Go Language dispose d'un garbage collection qui gรจre lui-mรชme la mรฉmoire et permet l'exรฉcution diffรฉrรฉe des fonctions.

Nous apprendrons toutes les bases de Golang dans ce didacticiel Learn Go Language.

Comment tรฉlรฉcharger et installer GO

ร‰tape 1) Allez dans https://golang.org/dl/. Tรฉlรฉchargez le binaire pour votre systรจme d'exploitation.

ร‰tape 2) Double cliquez sur le programme d'installation et cliquez sur Exรฉcuter.

ร‰tape 3) Cliquez Sur Suivant

ร‰tape 4) Sรฉlectionnez le dossier d'installation et cliquez sur Suivant.

ร‰tape 5) Cliquez sur Terminer une fois l'installation terminรฉe.

ร‰tape 6) Une fois l'installation terminรฉe, vous pouvez la vรฉrifier en ouvrant le terminal et en tapant

go version

Cela affichera la version de go installรฉe

Votre programme First Go โ€“ Go Hello World !

Crรฉez un dossier appelรฉ StudyGo. Dans ce didacticiel du langage Go, nous crรฉerons nos programmes Go dans ce dossier. Les fichiers Go sont crรฉรฉs avec l'extension .aller. Vous pouvez exรฉcuter des programmes Go en utilisant la syntaxe

go run <filename>

Crรฉez un fichier appelรฉ first.go, ajoutez-y le code ci-dessous et enregistrez

package main
import ("fmt")

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

Accรฉdez ร  ce dossier dans votre terminal. Exรฉcutez le programme ร  l'aide de la commande

va courir en premier, va

Vous pouvez voir l'impression de sortie

Hello World! This is my first Go program

Parlons maintenant du programme ci-dessus.

package main โ€“ Chaque programme Go Language doit commencer par un nom de package. Go nous permet d'utiliser des packages dans d'autres programmes Go et prend donc en charge la rรฉutilisation du code. L'exรฉcution d'un programme Go commence par le code contenu dans le package nommรฉ main.

import fmt โ€“ importe le package fmt. Ce package implรฉmente les fonctions d'E/S.

func main() โ€“ C'est la fonction ร  partir de laquelle commence l'exรฉcution du programme. La fonction main doit toujours รชtre placรฉe dans le package principal. Sous main(), vous pouvez รฉcrire le code ร  lโ€™intรฉrieur de { }.

fmt.Println โ€“ Cela imprimera le texte ร  lโ€™รฉcran grรขce ร  la fonction Println de fmt.

Remarque : dans les sections ci-dessous de ce didacticiel Go, lorsque vous mentionnez exรฉcuter/exรฉcuter le code, cela signifie enregistrer le code dans un fichier avec l'extension .go et l'exรฉcuter en utilisant la syntaxe.

    go run <filename>

Types de donnรฉes

Les types (types de donnรฉes) reprรฉsentent le type de la valeur stockรฉe dans une variable, le type de la valeur renvoyรฉe par une fonction, etc.

Il existe trois types de base dans Go Language

Types numรฉriques โ€“ Reprรฉsente des valeurs numรฉriques qui incluent des valeurs entiรจres, ร  virgule flottante et complexes. Diffรฉrents types numรฉriques sont :

int8 โ€“ entiers signรฉs 8 bits.

int16 โ€“ entiers signรฉs 16 bits.

int32 โ€“ entiers signรฉs 32 bits.

int64 โ€“ entiers signรฉs 64 bits.

uint8 โ€“ entiers non signรฉs de 8 bits.

uint16 โ€“ entiers non signรฉs de 16 bits.

uint32 โ€“ entiers non signรฉs de 32 bits.

uint64 โ€“ entiers non signรฉs de 64 bits.

float32 โ€“ Nombres ร  virgule flottante 32 bits.

float64 โ€“ Nombres ร  virgule flottante 64 bits.

complex64 โ€“ a float32 parties rรฉelles et imaginaires.

complex128 โ€“ a float32 parties rรฉelles et imaginaires.

Types de chaรฎnes โ€“ Reprรฉsente une sรฉquence dโ€™octets (caractรจres). Vous pouvez effectuer diverses opรฉrations sur des chaรฎnes comme la concatรฉnation de chaรฎnes, l'extraction de sous-chaรฎnes, etc.

Types boolรฉens โ€“ Reprรฉsente 2 valeurs, vraies ou fausses.

Interface Golang

Interface Golang est une collection de signatures de mรฉthodes utilisรฉes par un type pour implรฉmenter le comportement des objets. L'objectif principal de l'interface Golang est de fournir des signatures de mรฉthodes avec des noms, des arguments et des types de retour. C'est ร  un Type de dรฉclarer et d'implรฉmenter la mรฉthode. Une interface dans Golang peut รชtre dรฉclarรฉe ร  l'aide du mot-clรฉ ยซ interface ยป.

Variables

Les variables pointent vers un emplacement mรฉmoire qui stocke une sorte de valeur. Le paramรจtre type (dans la syntaxe ci-dessous) reprรฉsente le type de valeur qui peut รชtre stockรฉe dans l'emplacement mรฉmoire.

La variable peut รชtre dรฉclarรฉe en utilisant la syntaxe

    var <variable_name> <type>

Une fois que vous avez dรฉclarรฉ une variable d'un type, vous pouvez affecter la variable ร  n'importe quelle valeur de ce type.

Vous pouvez รฉgalement donner une valeur initiale ร  une variable lors de la dรฉclaration elle-mรชme en utilisant

    var <variable_name> <type> = <value>

Si vous dรฉclarez la variable avec une valeur initiale, allez et dรฉduire le type de la variable ร  partir du type de valeur attribuรฉe. Vous pouvez donc omettre le type lors de la dรฉclaration en utilisant la syntaxe

    var <variable_name> = <value>

De plus, vous pouvez dรฉclarer plusieurs variables avec la syntaxe

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

Le programme ci-dessous dans ce didacticiel Go contient quelques exemples Golang de dรฉclarations de variables

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

La sortie sera

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

Go Language fournit รฉgalement un moyen simple de dรฉclarer les variables avec une valeur en omettant le mot-clรฉ var en utilisant

    <variable_name> := <value>

Notez que vous avez utilisรฉ := au lieu de =. Vous ne pouvez pas utiliser := simplement pour attribuer une valeur ร  une variable dรฉjร  dรฉclarรฉe. := est utilisรฉ pour dรฉclarer et attribuer une valeur.

Crรฉez un fichier appelรฉ assign.go avec le code suivant

package main
import ("fmt")

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

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

Exรฉcutez go run assign.go pour voir le rรฉsultat comme

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

Les variables dรฉclarรฉes sans valeur initiale auront 0 pour les types numรฉriques, false pour les boolรฉens et une chaรฎne vide pour les chaรฎnes

Constants

Les variables constantes sont les variables dont la valeur ne peut pas รชtre modifiรฉe une fois attribuรฉe. Une constante dans le langage de programmation Go est dรฉclarรฉe en utilisant le mot-clรฉ ยซ const ยป

Crรฉez un fichier appelรฉ constant.go et avec le code suivant

package main
import ("fmt")

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

Exรฉcutez go run constant.go pour voir le rรฉsultat comme

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

Exemples de boucles For

Les boucles sont utilisรฉes pour exรฉcuter un bloc d'instructions ร  plusieurs reprises en fonction d'une condition. La plupart des langages de programmation proposent 3 types de boucles : for, while, do while. Mais le langage de programmation Go ne prend en charge que la boucle.

La syntaxe d'une boucle Golang for est

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

L'expression_initialisation est exรฉcutรฉe en premier (et une seule fois) dans la boucle Golang for.

Ensuite, l'expression_รฉvaluation est รฉvaluรฉe et si elle est vraie, le code ร  l'intรฉrieur du bloc est exรฉcutรฉ.

Lโ€™identifiant iteration_expression est exรฉcutรฉ et lโ€™รฉvaluation_expression est ร  nouveau รฉvaluรฉe. Si c'est vrai, le bloc d'instructions est ร  nouveau exรฉcutรฉ. Cela continuera jusqu'ร  ce que รฉvaluation_expression devienne fausse.

Copiez le programme ci-dessous dans un fichier et exรฉcutez-le pour voir le Golang pour les numรฉros d'impression en boucle de 1 ร  5.

package main
import "fmt"

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

La sortie est

1
2
3
4
5

Sinon

If else est une instruction conditionnelle. La synaxe est

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

Ici, la condition est รฉvaluรฉe et si elle est vraie, les instructions_1 seront exรฉcutรฉes, sinon les instructions_2 seront exรฉcutรฉes.

Vous pouvez รฉgalement utiliser l'instruction if sans autre. Vous pouvez รฉgalement avoir enchaรฎnรฉ des instructions if else. Les programmes ci-dessous vous expliqueront davantage si autrement.

Exรฉcutez le programme ci-dessous. Il vรฉrifie si un nombre, x, est infรฉrieur ร  10. Si tel est le cas, il affichera ยซ x est infรฉrieur ร  10 ยป.

package main
import "fmt"

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

Ici, puisque la valeur de x est supรฉrieure ร  10, lโ€™instruction ร  lโ€™intรฉrieur de la condition de bloc if ne sera pas exรฉcutรฉe.

Voyez maintenant le programme ci-dessous. Dans ce didacticiel du langage de programmation Go, nous avons un bloc else qui sera exรฉcutรฉ en cas d'รฉchec de l'รฉvaluation 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")
    }
}

Ce programme vous donnera une sortie

x is greater than or equals 10

Maintenant, dans ce didacticiel Go, nous verrons un programme avec plusieurs blocs if else (enchaรฎnรฉs if else). Exรฉcutez lโ€™exemple Go ci-dessous. Il vรฉrifie si un nombre est infรฉrieur ร  10 ou compris entre 10 et 90 ou supรฉrieur ร  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")
    }
}

Ici, la condition if vรฉrifie d'abord si x est infรฉrieur ร  10 et ce n'est pas le cas. Il vรฉrifie donc la condition suivante (sinon si) si elle est comprise entre 10 et 90, ce qui est รฉgalement faux. Il exรฉcute donc le bloc sous la section else qui donne le rรฉsultat

x is greater than 90

Basculer

Switch est une autre instruction conditionnelle. Les instructions Switch รฉvaluent une expression et le rรฉsultat est comparรฉ ร  un ensemble de valeurs disponibles (cas). Une fois qu'une correspondance est trouvรฉe, les instructions associรฉes ร  cette correspondance (cas) sont exรฉcutรฉes. Si aucune correspondance n'est trouvรฉe, rien ne sera exรฉcutรฉ. Vous pouvez รฉgalement ajouter un cas par dรฉfaut ร  switch qui sera exรฉcutรฉ si aucune autre correspondance n'est trouvรฉe. La syntaxe du commutateur est

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

Ici, la valeur de l'expression est comparรฉe aux valeurs de chaque cas. Une fois qu'une correspondance est trouvรฉe, les instructions associรฉes ร  ce cas sont exรฉcutรฉes. Si aucune correspondance n'est trouvรฉe, les instructions de la section par dรฉfaut sont exรฉcutรฉes.

Exรฉcutez le programme ci-dessous

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

Vous obtiendrez la sortie comme

Sum is 3		

Changez la valeur de a et b ร  3 et le rรฉsultat sera

Printing default

Vous pouvez รฉgalement avoir plusieurs valeurs dans une casse en les sรฉparant par une virgule.

Arrays

Le tableau reprรฉsente une taille fixe, nommรฉe sรฉquence d'รฉlรฉments du mรชme type. Vous ne pouvez pas avoir un tableau contenant ร  la fois des entiers et des caractรจres. Vous ne pouvez pas modifier la taille d'un tableau une fois que vous avez dรฉfini la taille.

La syntaxe pour dรฉclarer un tableau est

var arrayname [size] type

Chaque รฉlรฉment du tableau peut se voir attribuer une valeur en utilisant la syntaxe

arrayname [index] = value

L'index du tableau commence ร  partir de 0 ร  taille-1.

Vous pouvez attribuer des valeurs aux รฉlรฉments du tableau lors de la dรฉclaration en utilisant la syntaxe

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

Vous pouvez รฉgalement ignorer le paramรจtre size lors de la dรฉclaration du tableau avec des valeurs en remplaรงant size par ... et le compilateur trouvera la longueur ร  partir du nombre de valeurs. La syntaxe est

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

Vous pouvez trouver la longueur du tableau en utilisant la syntaxe

len(arrayname)

Exรฉcutez l'exemple Go ci-dessous pour comprendre le tableau

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

Sortie

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

Golang Slice et fonction d'ajout

Une tranche est une partie ou un segment d'un tableau. Ou bien il s'agit d'une vue ou d'une vue partielle d'un tableau sous-jacent vers lequel il pointe. Vous pouvez accรฉder aux รฉlรฉments d'une tranche en utilisant le nom de la tranche et le numรฉro d'index comme vous le faites dans un tableau. Vous ne pouvez pas modifier la longueur d'un tableau, mais vous pouvez modifier la taille d'une tranche.

Le contenu d'une tranche est en fait les pointeurs vers les รฉlรฉments d'un tableau. ร‡a veut dire si vous modifiez un รฉlรฉment dans une tranche, le contenu du tableau sous-jacent sera รฉgalement affectรฉ.

La syntaxe pour crรฉer une tranche est

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

Cela crรฉera une tranche nommรฉe slice_name ร  partir d'un tableau nommรฉ array_name avec les รฉlรฉments de l'index du dรฉbut ร  la fin-1.

Maintenant, dans ce didacticiel Golang, nous allons exรฉcuter le programme ci-dessous. Le programme crรฉera une tranche ร  partir du tableau et l'imprimera. De plus, vous pouvez voir que la modification du contenu de la tranche modifiera le tableau rรฉel.

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

Cela imprimera le rรฉsultat comme

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]

Il existe certaines fonctions comme Golang len, Golang append que vous pouvez appliquer sur les tranches

len(nom_tranche) โ€“ renvoie la longueur de la tranche

append(nom_slice, valeur_1, valeur_2) โ€“ Golang append est utilisรฉ pour ajouter value_1 et value_2 ร  une tranche existante.

append(slice_nale1,slice_name2โ€ฆ) โ€“ ajoute slice_name2 ร  slice_name1

Exรฉcutez le programme suivant.

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

La sortie sera

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]

Le programme crรฉe d'abord 2 tranches et imprime sa longueur. Ensuite, il a ajoutรฉ une tranche ร  une autre, puis une chaรฎne ร  la tranche rรฉsultante.

Les fonctions

Une fonction reprรฉsente un bloc d'instructions qui effectue une tรขche spรฉcifique. Une dรฉclaration de fonction nous indique le nom de la fonction, le type de retour et les paramรจtres d'entrรฉe. La dรฉfinition de fonction reprรฉsente le code contenu dans la fonction. La syntaxe pour dรฉclarer la fonction est

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

Les paramรจtres et les types de retour sont facultatifs. En outre, vous pouvez renvoyer plusieurs valeurs ร  partir d'une fonction.

Maintenant, dans ce didacticiel Golang, exรฉcutons l'exemple Golang suivant. Ici, la fonction nommรฉe calc acceptera 2 nombres, effectuera l'addition et la soustraction et retournera les deux valeurs.

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

La sortie sera

Sum 25
Diff 5

Forfaits

Les packages sont utilisรฉs pour organiser le code. Dans un gros projet, il nโ€™est pas possible dโ€™รฉcrire du code dans un seul fichier. Le langage de programmation Go nous permet d'organiser le code sous diffรฉrents packages. Cela augmente la lisibilitรฉ et la rรฉutilisabilitรฉ du code. Un programme Go exรฉcutable doit contenir un package nommรฉ main et l'exรฉcution du programme dรฉmarre ร  partir de la fonction nommรฉe main. Vous pouvez importer d'autres packages dans notre programme en utilisant la syntaxe

import package_name

Nous verrons et discuterons dans ce didacticiel Golang de la faรงon de crรฉer et d'utiliser des packages dans l'exemple Golang suivant.

ร‰tape 1) Crรฉez un fichier appelรฉ package_example.go et ajoutez le code ci-dessous

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

Dans le programme ci-dessus, fmt est un package que le langage de programmation Go nous fournit principalement ร  des fins d'E/S. Vous pouvez รฉgalement voir un package nommรฉ calcul. ร€ l'intรฉrieur de main(), vous pouvez voir une somme d'รฉtape := calcul.Do_add(x,y). Cela signifie que vous appelez la fonction Do_add ร  partir du calcul du package.

ร‰tape 2) Tout dโ€™abord, vous devez crรฉer le calcul du package dans un dossier du mรชme nom sous le dossier src de go. Le chemin installรฉ de go peut รชtre trouvรฉ ร  partir de la variable PATH.

Pour Mac, trouvez le chemin en exรฉcutant echo $PATH

Le chemin est donc /usr/local/go

Pour Windows, recherchez le chemin en exรฉcutant echo %GOROOT%

Ici, le chemin est C:\Go\

ร‰tape 3) Accรฉdez au dossier src (/usr/local/go/src pour Mac et C:\Go\src pour Windows). Maintenant, ร  partir du code, le nom du package est calcul. Go nรฉcessite que le package soit placรฉ dans un rรฉpertoire du mรชme nom sous le rรฉpertoire src. Crรฉez un rรฉpertoire nommรฉ calcul dans le dossier src.

ร‰tape 4) Crรฉez un fichier appelรฉ calc.go (vous pouvez donner n'importe quel nom, mais le nom du package dans le code est important. Ici, il devrait s'agir de calcul) dans le rรฉpertoire de calcul et ajoutez le code ci-dessous.

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

ร‰tape 5) Exรฉcutez la commande go install depuis le rรฉpertoire de calcul qui compilera le calc.go.

ร‰tape 6) Revenez maintenant ร  package_example.go et exรฉcutez go run package_example.go. La sortie sera Somme 25.

Notez que le nom de la fonction Do_add commence par une lettre majuscule. En effet, dans Go, si le nom de la fonction commence par une lettre majuscule, cela signifie que d'autres programmes peuvent le voir (y accรฉder), sinon d'autres programmes ne peuvent pas y accรฉder. Si le nom de la fonction รฉtait do_add , alors vous auriez eu l'erreur

ne peut pas faire rรฉfรฉrence au nom non exportรฉ calculator.calc..

Report et cumul des reports

Les instructions defer sont utilisรฉes pour diffรฉrer l'exรฉcution d'un appel de fonction jusqu'ร  ce que la fonction qui contient l'instruction defer termine son exรฉcution.

Apprenons cela avec un exemple :

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

La sortie sera

Inside the main()
Inside the sample()

Ici, l'exรฉcution de sample() est diffรฉrรฉe jusqu'ร  ce que l'exรฉcution de la fonction englobante (main()) soit terminรฉe.

Le report dโ€™empilement utilise plusieurs instructions de report. Supposons que vous ayez plusieurs instructions defer dans une fonction. Go place tous les appels de fonction diffรฉrรฉs dans une pile, et une fois la fonction englobante renvoyรฉe, les fonctions empilรฉes sont exรฉcutรฉes dans le Ordre Dernier entrรฉ, premier sorti (LIFO). Vous pouvez le voir dans lโ€™exemple ci-dessous.

Exรฉcutez le code ci-dessous

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

La sortie sera

4
3
2
1			

Ici, le code ร  l'intรฉrieur de main() s'exรฉcute en premier, puis les appels de fonction diffรฉrรฉs sont exรฉcutรฉs dans l'ordre inverse, c'est-ร -dire 4, 3,2,1.

Pointers

Avant d'expliquer les pointeurs, parlons d'abord de l'opรฉrateur '&'. L'opรฉrateur '&' est utilisรฉ pour obtenir l'adresse d'une variable. Cela signifie que '&a' imprimera l'adresse mรฉmoire de la variable a.

Dans ce tutoriel Golang, nous exรฉcuterons le programme ci-dessous pour afficher la valeur d'une variable et l'adresse de cette variable

package main
import "fmt"

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

Le rรฉsultat sera

Address: 0xc000078008
Value: 20

Une variable pointeur stocke lโ€™adresse mรฉmoire dโ€™une autre variable. Vous pouvez dรฉfinir un pointeur en utilisant la syntaxe

	var variable_name *type

L'astรฉrisque (*) reprรฉsente la variable qui est un pointeur. Vous comprendrez mieux en exรฉcutant le programme ci-dessous

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

La sortie sera

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

Structure

Une structure est un type de donnรฉes dรฉfini par l'utilisateur qui contient lui-mรชme un รฉlรฉment supplรฉmentaire du mรชme type ou d'un type diffรฉrent.

L'utilisation d'une structure est un processus en 2 รฉtapes.

Tout dโ€™abord, crรฉez (dรฉclarez) un type de structure

Deuxiรจmement, crรฉez des variables de ce type pour stocker des valeurs.

Les structures sont principalement utilisรฉes lorsque vous souhaitez stocker des donnรฉes associรฉes ensemble.

Considรฉrez une information sur l'employรฉ qui contient son nom, son รขge et son adresse. Vous pouvez gรฉrer cela de 2 maniรจres

Crรฉez 3 tableaux : un tableau stocke les noms des employรฉs, un autre stocke l'รขge et le troisiรจme stocke l'รขge.

Dรฉclarez un type de structure avec 3 champs : nom, adresse et รขge. Crรฉez un tableau de ce type de structure oรน chaque รฉlรฉment est un objet de structure ayant un nom, une adresse et un รขge.

La premiรจre approche n'est pas efficace. Dans ce genre de scรฉnarios, les structures sont plus pratiques.

La syntaxe pour dรฉclarer une structure est

type structname struct {
   variable_1 variable_1_type
   variable_2 variable_2_type
   variable_n variable_n_type
}

Un exemple de dรฉclaration de structure est

type emp struct {
    name string
    address string
    age int
}

Ici, un nouveau type dรฉfini par l'utilisateur nommรฉ emp est crรฉรฉ. Maintenant, vous pouvez crรฉer des variables du type emp en utilisant la syntaxe

	var variable_name struct_name

Un exemple est

var empdata1 emp 

Vous pouvez dรฉfinir des valeurs pour empdata1 comme

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

Vous pouvez รฉgalement crรฉer une variable de structure et attribuer des valeurs en

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

Ici, vous devez conserver l'ordre des รฉlรฉments. Raj sera mappรฉ au nom, au prochain รฉlรฉment ร  adresser et au dernier ร  vieillir.

Exรฉcutez le code ci-dessous

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

Sortie

John
Raj

Mรฉthodes (pas de fonctions)

Une mรฉthode est une fonction avec un argument rรฉcepteur. ArchiTechniquement, c'est entre le mot-clรฉ func et le nom de la mรฉthode. La syntaxe d'une mรฉthode est

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

Convertissons l'exemple de programme ci-dessus pour utiliser des mรฉthodes au lieu de fonctions.

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 n'est pas un langage orientรฉ objet et il n'a pas de concept de classe. Les mรฉthodes donnent une idรฉe de ce que vous faites dans les programmes orientรฉs objet oรน les fonctions d'une classe sont invoquรฉes ร  l'aide de la syntaxe objectname.functionname().

Concurrency

Go prend en charge l'exรฉcution simultanรฉe de tรขches. Cela signifie que Go peut exรฉcuter plusieurs tรขches simultanรฉment. Cโ€™est diffรฉrent du concept de parallรฉlisme. En parallรฉlisme, une tรขche est divisรฉe en petites sous-tรขches et exรฉcutรฉes en parallรจle. Mais en simultanรฉitรฉ, plusieurs tรขches sont exรฉcutรฉes simultanรฉment. La concurrence est obtenue dans Go ร  l'aide de Goroutines et de canaux.

Goroutines

Une goroutine est une fonction qui peut s'exรฉcuter simultanรฉment avec d'autres fonctions. Habituellement, lorsqu'une fonction est invoquรฉe, le contrรดle est transfรฉrรฉ dans la fonction appelรฉe et, une fois son exรฉcution terminรฉe, le contrรดle revient ร  la fonction appelante. La fonction appelante poursuit alors son exรฉcution. La fonction appelante attend que la fonction invoquรฉe termine l'exรฉcution avant de poursuivre le reste des instructions.

Mais dans le cas de goroutine, la fonction appelante n'attendra pas la fin de l'exรฉcution de la fonction invoquรฉe. Il continuera ร  s'exรฉcuter avec les prochaines instructions. Vous pouvez avoir plusieurs goroutines dans un programme.

De plus, le programme principal se fermera une fois l'exรฉcution de ses instructions terminรฉe et il n'attendra pas la fin des goroutines invoquรฉes.

Goroutine est invoquรฉ ร  l'aide du mot-clรฉ go suivi d'un appel de fonction.

Exemple

go add(x,y)

Vous comprendrez les goroutines avec les exemples Golang ci-dessous. Exรฉcutez le programme ci-dessous

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

La sortie sera

In main
In main
In main
In main
In main

Ici, le programme principal a terminรฉ son exรฉcution avant mรชme le dรฉmarrage de la goroutine. Le display() est une goroutine qui est invoquรฉe en utilisant la syntaxe

go function_name(parameter list)

Dans le code ci-dessus, main() n'attend pas la fin de display() et main() a terminรฉ son exรฉcution avant que display() n'exรฉcute son code. Ainsi, lโ€™instruction print ร  lโ€™intรฉrieur de display() nโ€™a pas รฉtรฉ imprimรฉe.

Maintenant, nous modifions le programme pour imprimer รฉgalement les instructions de display(). Nous ajoutons un dรฉlai de 2 secondes dans la boucle for de main() et un dรฉlai de 1 seconde dans la boucle for de display().

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

Le rรฉsultat sera quelque peu similaire ร 

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

Ici, vous pouvez voir que les deux boucles sont exรฉcutรฉes de maniรจre superposรฉe en raison de l'exรฉcution simultanรฉe.

Canaux de prix

Les canaux sont un moyen pour les fonctions de communiquer entre elles. Il peut รชtre considรฉrรฉ comme un support sur lequel une routine place les donnรฉes et est accessible par une autre routine sur le serveur Golang.

Un canal peut รชtre dรฉclarรฉ avec la syntaxe

channel_variable := make(chan datatype)

Exemple :

	ch := make(chan int)

Vous pouvez envoyer des donnรฉes ร  un canal en utilisant la syntaxe

channel_variable <- variable_name

Exemple

    ch <- x

Vous pouvez recevoir des donnรฉes d'un canal en utilisant la syntaxe

    variable_name := <- channel_variable

Exemple

   y := <- ch

Dans les exemples de goroutine en langage Go ci-dessus, vous avez vu que le programme principal n'attend pas le goroutine. Mais ce nโ€™est pas le cas lorsquโ€™il sโ€™agit de chaรฎnes. Supposons que si une goroutine envoie des donnรฉes vers le canal, main() attendra l'instruction recevant les donnรฉes du canal jusqu'ร  ce qu'elle obtienne les donnรฉes.

Vous le verrez dans les exemples de langage Go ci-dessous. Tout dโ€™abord, รฉcrivez une goroutine normale et voyez le comportement. Modifiez ensuite le programme pour utiliser les canaux et voir le comportement.

Exรฉcutez le programme ci-dessous

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

La sortie sera

Inside main()

Le main() a terminรฉ l'exรฉcution et s'est terminรฉ avant que la goroutine ne s'exรฉcute. Ainsi, l'impression ร  l'intรฉrieur du display() n'a pas รฉtรฉ exรฉcutรฉe.

Modifiez maintenant le programme ci-dessus pour utiliser les canaux et voir le comportement.

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

La sortie sera

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

Ici, ce qui se passe, c'est que main() en atteignant x := <-ch attendra les donnรฉes sur le canal ch. Le display() attend 5 secondes, puis transmet les donnรฉes au canal ch. Le main() ร  la rรฉception des donnรฉes du canal est dรฉbloquรฉ et continue son exรฉcution.

L'expรฉditeur qui transmet les donnรฉes au canal peut informer les rรฉcepteurs qu'aucune donnรฉe ne sera ajoutรฉe au canal en fermant le canal. Ceci est principalement utilisรฉ lorsque vous utilisez une boucle pour transmettre des donnรฉes vers un canal. Un canal peut รชtre fermรฉ en utilisant

close(channel_name)

Et cรดtรฉ rรฉcepteur, il est possible de vรฉrifier si le canal est fermรฉ ร  l'aide d'une variable supplรฉmentaire tout en rรฉcupรฉrant les donnรฉes du canal en utilisant

variable_name, status := <- channel_variable

Si le statut est True, cela signifie que vous avez reรงu des donnรฉes du canal. Si faux, cela signifie que vous essayez de lire ร  partir d'un canal fermรฉ

Vous pouvez รฉgalement utiliser des canaux de communication entre goroutines. Besoin d'utiliser 2 goroutines : l'une transmet les donnรฉes au canal et l'autre reรงoit les donnรฉes du canal. Voir le programme ci-dessous

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

Ici, il y a 2 sous-programmes, l'un pousse les donnรฉes vers le canal et l'autre imprime les donnรฉes sur le canal. La fonction add_to_channel ajoute les nombres de 0 ร  9 et ferme le canal. Simultanรฉment, la fonction fetch_from_channel attend ร 

x, flag := <- ch et une fois que les donnรฉes sont disponibles, il imprime les donnรฉes. Il se termine une fois que le drapeau est faux, ce qui signifie que le canal est fermรฉ.

L'attente dans main() est donnรฉe pour empรชcher la sortie de main() jusqu'ร  ce que les goroutines terminent l'exรฉcution.

Exรฉcutez le code et voyez le rรฉsultat comme

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

Choisir

Select peut รชtre considรฉrรฉ comme une instruction switch qui fonctionne sur les canaux. Ici, les instructions case seront une opรฉration de canal. Habituellement, chaque instruction de cas sera lue par tentative ร  partir du canal. Lorsqu'un des cas est prรชt (le canal est lu), alors l'instruction associรฉe ร  ce cas est exรฉcutรฉe. Si plusieurs cas sont prรชts, il en choisira un au hasard. Vous pouvez avoir un cas par dรฉfaut qui est exรฉcutรฉ si aucun des cas n'est prรชt.

Voyons le code ci-dessous

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

L'exรฉcution du programme ci-dessus donnera le rรฉsultat :

from data2()

Ici, l'instruction select attend que les donnรฉes soient disponibles dans l'un des canaux. data2() ajoute des donnรฉes au canal aprรจs une veille de 2 secondes, ce qui entraรฎnera l'exรฉcution du deuxiรจme cas.

Ajoutez un cas par dรฉfaut ร  la sรฉlection dans le mรชme programme et voyez le rรฉsultat. Ici, en atteignant le bloc de sรฉlection, si aucun cas n'a de donnรฉes prรชtes sur le canal, il exรฉcutera le bloc par dรฉfaut sans attendre que les donnรฉes soient disponibles sur aucun 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")
    }
}

Ce programme donnera le rรฉsultat :

Default case executed			

En effet, lorsque le bloc de sรฉlection a รฉtรฉ atteint, aucun canal n'avait de donnรฉes ร  lire. Ainsi, le cas par dรฉfaut est exรฉcutรฉ.

mutex

Mutex est la forme abrรฉgรฉe d'exclusion mutuelle. Mutex est utilisรฉ lorsque vous ne souhaitez pas autoriser l'accรจs ร  une ressource par plusieurs sous-programmes en mรชme temps. Mutex a 2 mรฉthodes โ€“ Verrouiller et Dรฉverrouiller. Mutex est contenu dans le package de synchronisation. Vous devez donc importer le package de synchronisation. Les instructions qui doivent รชtre exรฉcutรฉes mutuellement exclusivement peuvent รชtre placรฉes dans mutex.Lock() et mutex.Unlock().

Apprenons le mutex avec un exemple qui compte le nombre de fois qu'une boucle est exรฉcutรฉe. Dans ce programme, nous nous attendons ร  ce que la routine exรฉcute la boucle 10 fois et que le dรฉcompte soit stockรฉ en somme. Vous appelez cette routine 3 fois pour que le nombre total soit de 30. Le nombre est stockรฉ dans une variable globale count.

Tout d'abord, vous exรฉcutez le programme sans 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)
}

Voir le rรฉsultat

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

Le rรฉsultat pourrait รชtre diffรฉrent lorsque vous l'exรฉcuterez mais le rรฉsultat final ne sera pas 30.

Ici, ce qui se passe, c'est que 3 goroutines tentent d'augmenter le nombre de boucles stockรฉes dans le nombre de variables. Supposons qu'ร  un moment donnรฉ, le compte soit 5 et que goroutine1 va incrรฉmenter le compte ร  6. Les principales รฉtapes comprennent

Copier le nombre dans la version temporaire

Augmenter la tempรฉrature

Stocker la tempรฉrature pour compter

Supposons que peu de temps aprรจs avoir effectuรฉ l'รฉtape 3 de goroutine1 ; une autre goroutine peut avoir une ancienne valeur, par exemple 3 effectue les รฉtapes ci-dessus et stocke 4 en arriรจre, ce qui est faux. Cela peut รชtre รฉvitรฉ en utilisant un mutex qui fait attendre d'autres routines lorsqu'une routine utilise dรฉjร  la variable.

Vous allez maintenant exรฉcuter le programme avec mutex. Ici, les 3 รฉtapes mentionnรฉes ci-dessus sont exรฉcutรฉes dans 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)
}

Maintenant, la sortie sera

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

Ici, nous obtenons le rรฉsultat attendu comme rรฉsultat final. Parce que les instructions de lecture, d'incrรฉmentation et de rรฉรฉcriture du compte sont exรฉcutรฉes dans un mutex.

La gestion des erreurs

Les erreurs sont des conditions anormales comme la fermeture d'un fichier qui n'est pas ouvert, l'ouverture d'un fichier qui n'existe pas, etc. Les fonctions renvoient gรฉnรฉralement des erreurs comme derniรจre valeur de retour.

L'exemple ci-dessous explique plus en dรฉtail l'erreur.

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

La sortie sera:

open /invalid.txt: no such file or directory

Ici, nous avons essayรฉ d'ouvrir un fichier inexistant et il a renvoyรฉ l'erreur ร  la variable er. Si le fichier est valide, alors l'erreur sera nulle

Erreurs personnalisรฉes

Grรขce ร  cette fonctionnalitรฉ, vous pouvez crรฉer des erreurs personnalisรฉes. Cela se fait en utilisant New() du package d'erreur. Nous allons rรฉรฉcrire le programme ci-dessus pour utiliser les erreurs personnalisรฉes.

Exรฉcutez le programme ci-dessous

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

La sortie sera:

Custom error message:File name is wrong

Ici, la zone() renvoie l'aire d'un carrรฉ. Si l'entrรฉe est infรฉrieure ร  1, alors Area() renvoie un message d'erreur.

Lecture de fichiers

Les fichiers sont utilisรฉs pour stocker des donnรฉes. Go nous permet de lire les donnรฉes des fichiers

Crรฉez d'abord un fichier, data.txt, dans votre rรฉpertoire actuel avec le contenu ci-dessous.

Line one
Line two
Line three

Exรฉcutez maintenant le programme ci-dessous pour voir qu'il imprime le contenu de l'intรฉgralitรฉ du fichier en sortie.

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

Ici les donnรฉes, err := ioutil.ReadFile("data.txt") lit les donnรฉes et renvoie une sรฉquence d'octets. Lors de l'impression, il est converti au format chaรฎne.

Rรฉdaction de fichiers

Vous verrez cela avec un programme

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

Ici, un fichier est crรฉรฉ, test.txt. Si le fichier existe dรฉjร , son contenu est tronquรฉ. Writeline() est utilisรฉ pour รฉcrire le contenu du fichier. Aprรจs cela, vous avez fermรฉ le fichier en utilisant Close().

Aide-mรฉmoire

Dans ce didacticiel Go, nous avons couvert :

Sujet Description Syntaxe
Types de base Numรฉrique, chaรฎne, boolรฉen
Variables Dรฉclarer et attribuer des valeurs aux variables var type nom_variable
var nom_variable type = valeur
var nom_variable1, nom_variable2 = valeur1, valeur2
nom_variable := valeur
Constants Variables dont la valeur ne peut pas รชtre modifiรฉe une fois attribuรฉe variable const = valeur
Pour la boucle Exรฉcutez des instructions en boucle. pour initialisation_expression ; expression_รฉvaluation ; expression_itรฉration{
// une ou plusieurs instructions
}
Sinon C'est une instruction conditionnelle si condition{
// dรฉclarations_1
}autre{
// dรฉclarations_2
}
interrupteur Instruction conditionnelle avec plusieurs cas changer d'expression {
valeur de cas_1 :
dรฉclarations_1
valeur de cas_2 :
dรฉclarations_2
cas valeur_n :
dรฉclarations_n
par dรฉfaut:
dรฉclarations_par dรฉfaut
}
tableau Sรฉquence nommรฉe de taille fixe d'รฉlรฉments du mรชme type nom du tableau := [taille] tapez {value_0,value_1,โ€ฆ,value_size-1}
Tranche Portion ou segment d'un tableau var slice_name [] type = array_name[dรฉbut: fin]
Les fonctions Bloc d'instructions qui effectue une tรขche spรฉcifique func nom_fonction (type paramรจtre_1, type paramรจtre_n) return_type {
//instructions
}
Forfaits Sont utilisรฉs pour organiser le code. Augmente la lisibilitรฉ et la rรฉutilisabilitรฉ du code importer nom_paquet
Reporter Diffรจre l'exรฉcution d'une fonction jusqu'ร  ce que la fonction contenant termine son exรฉcution diffรฉrer nom_fonction (liste_paramรจtres)
Pointers Stocke l'adresse mรฉmoire d'une autre variable. var nom_variable *type
Structure Type de donnรฉes dรฉfini par l'utilisateur qui contient lui-mรชme un รฉlรฉment supplรฉmentaire du mรชme type ou d'un type diffรฉrent tapez nom_structure struct {
variable_1 variable_1_type
variable_2 variable_2_type
variable_n variable_n_type
}
Mรฉthodologie Une mรฉthode est une fonction avec un argument rรฉcepteur func (variable type de variable) nom_mรฉthode (liste_paramรจtres) {
}
Goroutine Une fonction qui peut s'exรฉcuter simultanรฉment avec d'autres fonctions. allez nom_fonction (liste_paramรจtres)
Dรฉveloppement Faรงon pour les fonctions de communiquer entre elles. Support sur lequel une routine place des donnรฉes et auquel une autre routine accรจde. Dรฉclarer:
ch := faire(chan int)
Envoyer des donnรฉes au canal :
variable_canal <- nom_variable
Recevoir depuis la chaรฎne :
nom_variable := <- variable_canal
Choisir Instruction Switch qui fonctionne sur les canaux. Les instructions case seront une opรฉration de canal. Lorsque l'un des canaux est prรชt avec des donnรฉes, l'instruction associรฉe ร  ce cas est exรฉcutรฉe sรฉlectionnez {
cas x := <-chan1 :
fmt.Println(x)
cas y := <-chan2 :
fmt.Println(y)
}
mutex Mutex est utilisรฉ lorsque vous ne souhaitez pas autoriser l'accรจs ร  une ressource par plusieurs sous-programmes en mรชme temps. Mutex a 2 mรฉthodes โ€“ Verrouiller et Dรฉverrouiller mutex.Lock()
//instructions
mutex.Unlock().
Lire des fichiers Lit les donnรฉes et renvoie une sรฉquence d'octets. Donnรฉes, erreur := ioutil.ReadFile(filename)
ร‰crire le fichier ร‰crit des donnรฉes dans un fichier l, erreur := f.WriteString(text_to_write)

Rรฉsumez cet article avec :