Golang-zelfstudie: leer Go-programmeertaal voor beginners

Wat is Go?

Go (ook bekend als Golang) is een open source programmeertaal die is ontwikkeld door Google. Het is een statisch getypeerde gecompileerde taal. Go ondersteunt gelijktijdig programmeren, d.w.z. het staat toe om meerdere processen tegelijkertijd uit te voeren. Dit wordt bereikt met behulp van kanalen, goroutines, enz. Go Language heeft garbage collection die zelf het geheugenbeheer doet en de uitgestelde uitvoering van functies toestaat.

We zullen alle basisprincipes van Golang leren in deze Learn Go Language Tutorial.

GO downloaden en installeren

Stap 1) Ga naar https://golang.org/dl/. Download het binaire bestand voor uw besturingssysteem.

Stap 2) Double klik op het installatieprogramma en klik op Uitvoeren.

Stap 3) Klik op Volgende

Stap 4) Selecteer de installatiemap en klik op Volgende.

Stap 5) Klik op Voltooien zodra de installatie is voltooid.

Stap 6) Zodra de installatie is voltooid, kunt u deze verifiëren door de terminal te openen en te typen

go version

Hierdoor wordt de geïnstalleerde versie van go weergegeven

Je First Go-programma – Go Hello World!

Maak een map met de naam studyGo. In deze Go-taaltutorial maken we onze go-programma's in deze map. Go-bestanden worden gemaakt met de extensie .Gaan. U kunt Go-programma's uitvoeren met behulp van de syntaxis

go run <filename>

Maak een bestand met de naam first.go, voeg de onderstaande code eraan toe en sla het op

package main
import ("fmt")

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

Navigeer naar deze map in uw terminal. Voer het programma uit met behulp van de opdracht

ga eerst rennen.go

U kunt de uitvoerafdruk zien

Hello World! This is my first Go program

Laten we nu het bovenstaande programma bespreken.

package main – Elk Go Language-programma moet beginnen met een pakketnaam. Met Go kunnen we pakketten in andere go-programma's gebruiken en wordt daarmee de herbruikbaarheid van code ondersteund. De uitvoering van een Go-programma begint met de code in het pakket genaamd main.

import fmt – importeert het pakket fmt. Dit pakket implementeert de I/O-functies.

func main() – Dit is de functie van waaruit de uitvoering van het programma begint. De hoofdfunctie moet altijd in het hoofdpakket worden geplaatst. Onder main() kunt u de code in { } schrijven.

fmt.Println – Hiermee wordt de tekst op het scherm afgedrukt via de Println-functie van fmt.

Opmerking: wanneer u in de onderstaande secties van deze Go-tutorial de code uitvoeren/uitvoeren vermeldt, betekent dit dat u de code opslaat in een bestand met de extensie .go en deze uitvoert met behulp van de syntaxis

    go run <filename>

Gegevenstypen

Typen (gegevenstypen) vertegenwoordigen het type waarde dat is opgeslagen in een variabele, het type waarde dat een functie retourneert, enz.

Er zijn drie basistypen in Go Language

Numerieke typen – Vertegenwoordig numerieke waarden, waaronder gehele getallen, drijvende komma's en complexe waarden. Verschillende numerieke typen zijn:

int8 – 8 bit gehele getallen met teken.

int16 – 16 bit gehele getallen met teken.

int32 – 32 bit gehele getallen met teken.

int64 – 64 bit gehele getallen met teken.

uint8 – 8 bit gehele getallen zonder teken.

uint16 – 16 bit gehele getallen zonder teken.

uint32 – 32 bit gehele getallen zonder teken.

uint64 – 64 bit gehele getallen zonder teken.

float32 – 32-bits drijvendekommagetallen.

float64 – 64-bits drijvendekommagetallen.

complex64 – heeft float32 reële en imaginaire delen.

complex128 – heeft float32 reële en imaginaire delen.

Soorten tekenreeksen – Vertegenwoordigt een reeks bytes (tekens). U kunt verschillende bewerkingen op strings uitvoeren, zoals string-concatenatie, substrings extraheren, enz.

Booleaanse typen – Vertegenwoordigt 2 waarden, waar of onwaar.

Golang-interface

Golang-interface is een verzameling methodehandtekeningen die door een type worden gebruikt om het gedrag van objecten te implementeren. Het belangrijkste doel van de Golang-interface is om methodehandtekeningen te voorzien van namen, argumenten en retourtypen. Het is aan een Type om de methode te declareren en te implementeren. Een interface in Golang kan worden gedeclareerd met het trefwoord ‘interface’.

Variabelen

Variabelen verwijzen naar een geheugenlocatie waarin een bepaalde waarde is opgeslagen. De parameter type (in de onderstaande syntaxis) vertegenwoordigt het type waarde dat op de geheugenlocatie kan worden opgeslagen.

Variabele kan worden gedeclareerd met behulp van de syntaxis

    var <variable_name> <type>

Zodra u een variabele van een bepaald type declareert, kunt u de variabele aan elke waarde van dat type toewijzen.

U kunt ook tijdens de declaratie zelf een initiële waarde aan een variabele geven met behulp van

    var <variable_name> <type> = <value>

Als u de variabele met een beginwaarde declareert, leidt u het type variabele af uit het toegewezen type waarde. U kunt het type dus weglaten tijdens de declaratie met behulp van de syntaxis

    var <variable_name> = <value>

U kunt ook meerdere variabelen declareren met de syntaxis

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

Het onderstaande programma in deze Go-tutorial bevat enkele Golang-voorbeelden van variabele declaraties

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

De uitvoer zal zijn:

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

Go Language biedt ook een gemakkelijke manier om de variabelen met waarde te declareren door het trefwoord var met behulp van weg te laten

    <variable_name> := <value>

Merk op dat u gebruikte := in plaats van =. Je kunt := niet alleen gebruiken om een ​​waarde toe te wijzen aan een variabele die al is gedeclareerd. := wordt gebruikt om waarde te declareren en toe te wijzen.

Maak een bestand genaamd assign.go met de volgende code

package main
import ("fmt")

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

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

Voer go run Assign.go uit om het resultaat te zien als

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

Variabelen die zonder initiële waarde zijn gedeclareerd, hebben de waarde 0 voor numerieke typen, false voor Booleaanse waarden en een lege tekenreeks voor tekenreeksen

constanten

Constante variabelen zijn die variabelen waarvan de waarde niet kan worden gewijzigd nadat deze is toegewezen. Een constante in de Go-programmeertaal wordt gedeclareerd met behulp van het trefwoord “const”

Maak een bestand met de naam constant.go en met de volgende code

package main
import ("fmt")

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

Voer go run constant.go uit om het resultaat te zien als

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

Voor lusvoorbeelden

Lussen worden gebruikt om een ​​blok met instructies herhaaldelijk uit te voeren op basis van een voorwaarde. De meeste programmeertalen bieden drie soorten lussen: for, while, do while. Maar de programmeertaal Go ondersteunt alleen for loop.

De syntaxis van een Golang for-lus is

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

De initialisatie_expressie wordt eerst (en slechts één keer) uitgevoerd in Golang for loop.

Vervolgens wordt de evaluatie_expressie geëvalueerd en als deze waar is, wordt de code in het blok uitgevoerd.

De iteratie_expressie-ID wordt uitgevoerd en de evaluatie_expressie wordt opnieuw geëvalueerd. Als dit waar is, wordt het instructieblok opnieuw uitgevoerd. Dit gaat door totdat de evaluatie_expressie onwaar wordt.

Kopieer het onderstaande programma naar een bestand en voer het uit om te zien hoe de Golang for-lus de getallen van 1 tot 5 afdrukt

package main
import "fmt"

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

Uitgang is

1
2
3
4
5

Als anders

If else is een voorwaardelijke verklaring. De synax is

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

Hier wordt de voorwaarde geëvalueerd en als het waar is, wordt statement_1 uitgevoerd, anders wordt statement_2 uitgevoerd.

Je kunt de if-instructie ook zonder else gebruiken. Je kunt ook if else-verklaringen hebben geketend. De onderstaande programma's leggen meer uit over if else.

Voer het onderstaande programma uit. Er wordt gecontroleerd of een getal, x, kleiner is dan 10. Als dat het geval is, wordt 'x is kleiner dan 10' weergegeven.

package main
import "fmt"

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

Omdat de waarde van x groter is dan 10, wordt de instructie binnen de if-blokvoorwaarde niet uitgevoerd.

Zie nu het onderstaande programma. In deze Go-programmeertaaltutorial hebben we een else-blok dat wordt uitgevoerd als de if-evaluatie mislukt.

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

Dit programma geeft je output

x is greater than or equals 10

In deze Go-tutorial zien we een programma met meerdere if else-blokken (aan elkaar gekoppeld if else). Voer het onderstaande Go-voorbeeld uit. Er wordt gecontroleerd of een getal kleiner is dan 10, tussen 10-90 of groter dan 90 ligt.

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

Hier controleert eerst de if-voorwaarde of x kleiner is dan 10 en dat is niet het geval. Het controleert dus de volgende voorwaarde (else if) of deze tussen 10 en 90 ligt, wat ook onwaar is. Dus voert het vervolgens het blok uit onder de else-sectie die de uitvoer geeft

x is greater than 90

Stap over voor slechts

Switch is een andere voorwaardelijke verklaring. Switch-instructies evalueren een expressie en het resultaat wordt vergeleken met een reeks beschikbare waarden (cases). Zodra er een match is gevonden, worden de instructies die bij die match(case) horen, uitgevoerd. Als er geen match wordt gevonden, wordt er niets uitgevoerd. U kunt ook een standaardgeval toevoegen aan de overstap, dat wordt uitgevoerd als er geen andere overeenkomsten worden gevonden. De syntaxis van de schakelaar is

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

Hier wordt de waarde van de uitdrukking vergeleken met de waarden in elk geval. Zodra er een match is gevonden, worden de uitspraken die bij die casus horen, uitgevoerd. Als er geen overeenkomst wordt gevonden, worden de instructies onder de standaardsectie uitgevoerd.

Voer het onderstaande programma uit

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

U krijgt de uitvoer als

Sum is 3		

Verander de waarde van a en b in 3 en het resultaat zal zijn

Printing default

U kunt ook meerdere waarden in een hoofdlettergebruik hebben door ze te scheiden met een komma.

arrays

Array vertegenwoordigt een vaste grootte, een zogenaamde reeks elementen van hetzelfde type. U kunt geen array hebben die zowel gehele getallen als tekens bevat. U kunt de grootte van een array niet wijzigen nadat u de grootte hebt gedefinieerd.

De syntaxis voor het declareren van een array is

var arrayname [size] type

Aan elk array-element kan een waarde worden toegewezen met behulp van de syntaxis

arrayname [index] = value

Array-index begint vanaf 0 tot maat 1.

U kunt tijdens de declaratie waarden toewijzen aan array-elementen met behulp van de syntaxis

arrayname := [size] type {value_0,value_1,…,value_size-1} 

U kunt de parameter size ook negeren terwijl u de array met waarden declareert door size te vervangen door ... en de compiler zal de lengte uit het aantal waarden vinden. Syntaxis is

arrayname :=  […] type {value_0,value_1,…,value_size-1}

U kunt de lengte van de array vinden met behulp van de syntaxis

len(arrayname)

Voer het onderstaande Go-voorbeeld uit om de array te begrijpen

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

uitgang

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

Golang Slice en Append-functie

Een slice is een gedeelte of segment van een array. Of het is een weergave of een gedeeltelijke weergave van een onderliggende array waarnaar deze verwijst. U kunt toegang krijgen tot de elementen van een segment met behulp van de segmentnaam en het indexnummer, net zoals u dat in een array doet. U kunt de lengte van een array niet wijzigen, maar u kunt wel de grootte van een segment wijzigen.

De inhoud van een segment zijn eigenlijk de verwijzingen naar de elementen van een array. Het betekent als u een element in een segment wijzigt, wordt de onderliggende array-inhoud ook beïnvloed.

De syntaxis voor het maken van een segment is

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

Hierdoor wordt een segment met de naam slice_name gemaakt van een array met de naam array_name, waarbij de elementen in de index van begin tot eind-1 beginnen.

In deze Golang-tutorial zullen we nu het onderstaande programma uitvoeren. Het programma maakt een segment van de array en drukt dit af. U kunt ook zien dat het wijzigen van de inhoud van het segment de daadwerkelijke array zal wijzigen.

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

Hierdoor wordt het resultaat afgedrukt als

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]

Er zijn bepaalde functies zoals Golang len en Golang append die u op segmenten kunt toepassen

len(plaknaam) – geeft de lengte van het segment terug

append(segmentnaam, waarde_1, waarde_2) – Golang append wordt gebruikt om waarde_1 en waarde_2 aan een bestaand segment toe te voegen.

append(slice_nale1,slice_name2…) – voegt segmentnaam2 toe aan segmentnaam1

Voer het volgende programma uit.

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

De uitvoer zal zijn:

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]

Het programma maakt eerst 2 plakjes en drukt de lengte ervan af. Vervolgens werd het ene segment aan het andere toegevoegd en vervolgens een tekenreeks aan het resulterende segment toegevoegd.

Functies

Een functie vertegenwoordigt een blok instructies dat een specifieke taak uitvoert. Een functiedeclaratie vertelt ons de functienaam, het retourtype en de invoerparameters. Functiedefinitie vertegenwoordigt de code in de functie. De syntaxis voor het declareren van de functie is

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

De parameters en retourtypen zijn optioneel. U kunt ook meerdere waarden uit een functie retourneren.

Laten we in deze Golang-zelfstudie het volgende Golang-voorbeeld uitvoeren. Hier accepteert de functie genaamd calc 2 getallen en voert de optelling en aftrekking uit en retourneert beide waarden.

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

De uitvoer zal zijn:

Sum 25
Diff 5

Pakketten

Pakketten worden gebruikt om de code te ordenen. In een groot project is het niet haalbaar om code in één bestand te schrijven. Met Go-programmeertaal kunnen we de code onder verschillende pakketten ordenen. Dit vergroot de leesbaarheid en herbruikbaarheid van de code. Een uitvoerbaar Go-programma moet een pakket bevatten met de naam main en de uitvoering van het programma begint met de functie genaamd main. U kunt andere pakketten in ons programma importeren met behulp van de syntaxis

import package_name

In deze Golang-zelfstudie gaan we bekijken en bespreken hoe je pakketten kunt maken en gebruiken in het volgende Golang-voorbeeld.

Stap 1) Maak een bestand met de naam package_example.go en voeg de onderstaande code toe

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

In het bovenstaande programma is fmt een pakket dat de programmeertaal Go ons levert, voornamelijk voor I/O-doeleinden. U kunt ook een pakket zien met de naam berekening. Binnen main() kun je een stapsom zien:= berekening.Do_add(x,y). Het betekent dat u de functie Do_add aanroept vanuit de pakketberekening.

Stap 2) Eerst moet u de pakketberekening maken in een map met dezelfde naam onder de src-map van onderweg. Het geïnstalleerde pad van go kan worden gevonden via de PATH-variabele.

Voor Mac: zoek het pad door echo $PATH uit te voeren

Het pad is dus /usr/local/go

Voor Windows vindt u het pad door echo %GOROOT% uit te voeren

Hier is het pad C:\Go\

Stap 3) Navigeer naar de src-map (/usr/local/go/src voor mac en C:\Go\src voor windows). Nu is de pakketnaam in de code calculation. Go vereist dat het pakket in een directory met dezelfde naam onder de src-directory wordt geplaatst. Maak een directory met de naam calculation in de src-map.

Stap 4) Maak een bestand met de naam calc.go (u kunt elke naam opgeven, maar de pakketnaam in de code is van belang. Hier zou het berekening moeten zijn) in de berekeningsmap en voeg de onderstaande code toe

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

Stap 5) Voer de opdracht go install uit vanuit de berekeningsmap die calc.go zal compileren.

Stap 6) Ga nu terug naar package_example.go en voer run package_example.go uit. De uitvoer is Som 25.

Merk op dat de naam van de functie Do_add begint met een hoofdletter. Dit komt omdat als de functienaam in Go met een hoofdletter begint, dit betekent dat andere programma's deze kunnen zien (toegang krijgen), anders hebben andere programma's er geen toegang toe. Als de functienaam do_add was, zou je de foutmelding hebben gekregen

kan niet verwijzen naar de niet-geëxporteerde naam computation.calc..

Uitstel en stapelen uitstel

Defer-instructies worden gebruikt om de uitvoering van een functieaanroep uit te stellen totdat de functie die de defer-instructie bevat, de uitvoering voltooit.

Laten we dit leren met een voorbeeld:

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

De uitvoer zal zijn:

Inside the main()
Inside the sample()

Hier wordt de uitvoering van sample() uitgesteld totdat de uitvoering van de omsluitende functie (main()) is voltooid.

Bij het stapelen van uitstel worden meerdere uitstelinstructies gebruikt. Stel dat u meerdere uitstelinstructies binnen een functie hebt. Go plaatst alle uitgestelde functieaanroepen in een stapel, en zodra de omsluitende functie terugkeert, worden de gestapelde functies uitgevoerd in de stapel. Last In First Out (LIFO)-bestelling. Je kunt dit zien in het onderstaande voorbeeld.

Voer de onderstaande code uit

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

De uitvoer zal zijn:

4
3
2
1			

Hier wordt eerst de code in main() uitgevoerd, en vervolgens worden de uitgestelde functieaanroepen in de omgekeerde volgorde uitgevoerd, dat wil zeggen 4, 3,2,1.

Pointers

Voordat we pointers uitleggen, bespreken we eerst de '&' operator. De '&' operator wordt gebruikt om het adres van een variabele te krijgen. Dit betekent dat '&a' het geheugenadres van variabele a zal afdrukken.

In deze Golang-tutorial zullen we het onderstaande programma uitvoeren om de waarde van een variabele en het adres van die variabele weer te geven

package main
import "fmt"

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

Het resultaat zal zijn

Address: 0xc000078008
Value: 20

Een pointervariabele slaat het geheugenadres van een andere variabele op. U kunt een pointer definiëren met behulp van de syntaxis

	var variable_name *type

Het sterretje (*) geeft aan dat de variabele een pointer is. U zult meer begrijpen door het onderstaande programma uit te voeren

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

De uitvoer zal zijn:

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

Structuren

Een structuur is een door de gebruiker gedefinieerd gegevenstype dat zelf nog een element van hetzelfde of een ander type bevat.

Het gebruik van een structuur bestaat uit twee stappen.

Maak (declareer) eerst een structuurtype

Ten tweede: maak variabelen van dat type om waarden op te slaan.

Structuren worden vooral gebruikt als je gerelateerde gegevens bij elkaar wilt opslaan.

Overweeg een stukje werknemersinformatie met naam, leeftijd en adres. Je kunt dit op 2 manieren aanpakken

Maak 3 arrays – één array slaat de namen van werknemers op, één slaat de leeftijd op en de derde slaat de leeftijd op.

Declareer een structuurtype met 3 velden: naam, adres en leeftijd. Maak een array van dat structuurtype waarbij elk element een structuurobject is met naam, adres en leeftijd.

De eerste aanpak is niet efficiënt. In dit soort scenario's zijn structuren handiger.

De syntaxis voor het declareren van een structuur is

type structname struct {
   variable_1 variable_1_type
   variable_2 variable_2_type
   variable_n variable_n_type
}

Een voorbeeld van een structuurdeclaratie is

type emp struct {
    name string
    address string
    age int
}

Hier wordt een nieuw door de gebruiker gedefinieerd type met de naam emp gemaakt. Nu kunt u variabelen van het type emp maken met behulp van de syntaxis

	var variable_name struct_name

Een voorbeeld is

var empdata1 emp 

U kunt waarden voor empdata1 instellen als

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

U kunt ook een structuurvariabele maken en waarden toewijzen door

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

Hier moet u de volgorde van de elementen behouden. Raj wordt toegewezen aan de naam, het volgende element dat moet worden aangepakt en het laatste aan de leeftijd.

Voer de onderstaande code uit

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

uitgang

John
Raj

Methoden (geen functies)

Een methode is een functie met een receiver-argument. Architechnisch gezien bevindt het zich tussen het func-trefwoord en de methodenaam. De syntaxis van een methode is

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

Laten we het bovenstaande voorbeeldprogramma converteren om methoden te gebruiken in plaats van functie.

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 is geen objectgeoriënteerde taal en kent niet het concept van klasse. Methoden geven een idee van wat u doet in objectgeoriënteerde programma's waarbij de functies van een klasse worden aangeroepen met behulp van de syntaxis objectnaam.functienaam()

samenloop

Go ondersteunt gelijktijdige uitvoering van taken. Dit betekent dat Go meerdere taken tegelijkertijd kan uitvoeren. Het verschilt van het concept van parallelisme. Bij parallelisme wordt een taak opgesplitst in kleine subtaken en parallel uitgevoerd. Maar bij gelijktijdigheid worden meerdere taken tegelijkertijd uitgevoerd. Gelijktijdigheid wordt in Go bereikt met behulp van Goroutines en Channels.

goroutines

Een goroutine is een functie die gelijktijdig met andere functies kan worden uitgevoerd. Wanneer een functie wordt aangeroepen, wordt de besturing gewoonlijk overgedragen naar de aangeroepen functie, en zodra de uitvoering ervan is voltooid, keert de besturing terug naar de aanroepende functie. De aanroepende functie vervolgt vervolgens de uitvoering ervan. De aanroepende functie wacht tot de aangeroepen functie de uitvoering heeft voltooid voordat deze verdergaat met de rest van de instructies.

Maar in het geval van goroutine wacht de aanroepende functie niet tot de uitvoering van de aangeroepen functie is voltooid. Het zal doorgaan met uitvoeren met de volgende instructies. U kunt meerdere goroutines in een programma hebben.

Bovendien wordt het hoofdprogramma afgesloten zodra het de instructies heeft uitgevoerd en wacht het niet op de voltooiing van de aangeroepen goroutines.

Goroutine wordt aangeroepen met het trefwoord go, gevolgd door een functieaanroep.

Voorbeeld

go add(x,y)

Je zult goroutines begrijpen met de onderstaande Golang-voorbeelden. Voer het onderstaande programma uit

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

De uitvoer zal zijn:

In main
In main
In main
In main
In main

Hier voltooide het hoofdprogramma de uitvoering nog voordat de goroutine startte. De display() is een goroutine die wordt aangeroepen met behulp van de syntaxis

go function_name(parameter list)

In de bovenstaande code wacht main() niet tot display() is voltooid, en main() voltooide de uitvoering ervan voordat display() zijn code uitvoerde. Dus de print-instructie in display() werd niet afgedrukt.

Nu passen we het programma aan om ook de instructies van display() af te drukken. We voegen een vertraging van 2 sec toe in de for-lus van main() en een vertraging van 1 sec in de for-lus van 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")
	}
}

De uitvoer zal enigszins vergelijkbaar zijn met

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

Hier kunt u zien dat beide lussen overlappend worden uitgevoerd vanwege de gelijktijdige uitvoering.

Kanalen

Kanalen zijn een manier waarop functies met elkaar kunnen communiceren. Het kan worden gezien als een medium waar de ene routine gegevens plaatst en toegankelijk is voor een andere routine op de Golang-server.

Een kanaal kan worden gedeclareerd met de syntaxis

channel_variable := make(chan datatype)

Voorbeeld:

	ch := make(chan int)

U kunt gegevens naar een kanaal verzenden met behulp van de syntaxis

channel_variable <- variable_name

Voorbeeld

    ch <- x

U kunt gegevens van een kanaal ontvangen met behulp van de syntaxis

    variable_name := <- channel_variable

Voorbeeld

   y := <- ch

In de bovenstaande Go-taalvoorbeelden van goroutine heb je gezien dat het hoofdprogramma niet op de goroutine wacht. Maar dat is niet het geval als het om kanalen gaat. Stel dat als een goroutine gegevens naar channel pusht, de main() zal wachten op de instructie die kanaalgegevens ontvangt totdat deze de gegevens ontvangt.

Je zult dit zien in onderstaande Go-taalvoorbeelden. Schrijf eerst een normale goroutine en bekijk het gedrag. Pas vervolgens het programma aan om kanalen te gebruiken en het gedrag te bekijken.

Voer het onderstaande programma uit

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

De uitvoer zal zijn:

Inside main()

De main() beëindigde de uitvoering en werd afgesloten voordat de goroutine werd uitgevoerd. Dus de afdruk in display() werd niet uitgevoerd.

Pas nu het bovenstaande programma aan om kanalen te gebruiken en het gedrag te bekijken.

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

De uitvoer zal zijn:

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

Wat hier gebeurt is de main() bij het bereiken van x := <-ch zal wachten op gegevens op kanaal ch. Het display() wacht 5 seconden en pusht vervolgens gegevens naar het kanaal ch. De main() bij het ontvangen van de gegevens van het kanaal wordt gedeblokkeerd en gaat door met de uitvoering ervan.

De afzender die gegevens naar het kanaal pusht, kan de ontvangers informeren dat er geen gegevens meer aan het kanaal worden toegevoegd door het kanaal te sluiten. Dit wordt voornamelijk gebruikt als u een lus gebruikt om gegevens naar een kanaal te pushen. Een kanaal kan worden gesloten met

close(channel_name)

En aan de ontvangerkant is het mogelijk om te controleren of het kanaal gesloten is met behulp van een extra variabele, terwijl gegevens van het kanaal worden opgehaald met behulp van

variable_name, status := <- channel_variable

Als de status True is, betekent dit dat u gegevens van het kanaal heeft ontvangen. Als dit niet waar is, betekent dit dat u probeert te lezen vanaf een gesloten kanaal

Je kunt ook kanalen gebruiken voor communicatie tussen goroutines. Er moeten twee goroutines worden gebruikt: de ene stuurt gegevens naar het kanaal en de andere ontvangt de gegevens van het kanaal. Zie onderstaand programma

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

Hier zijn er 2 subroutines, één pusht data naar het kanaal en de andere print data naar het kanaal. De functie add_to_channel voegt de getallen van 0 tot 9 toe en sluit het kanaal. Tegelijkertijd wacht de functie fetch_from_channel op

x, flag := <- ch en zodra de gegevens beschikbaar zijn, worden de gegevens afgedrukt. Het verdwijnt zodra de vlag vals is, wat betekent dat het kanaal gesloten is.

Er wordt gewacht in main() om te voorkomen dat main() wordt afgesloten totdat de goroutines de uitvoering hebben voltooid.

Voer de code uit en bekijk de uitvoer als

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

kies

Select kan worden gezien als een switch statement die op kanalen werkt. Hier zijn de case statements een kanaalbewerking. Normaal gesproken wordt elke case statement gelezen vanaf het kanaal. Wanneer een van de cases gereed is (het kanaal wordt gelezen), wordt de statement die aan die case is gekoppeld uitgevoerd. Als er meerdere cases gereed zijn, wordt er een willekeurige gekozen. U kunt een standaardcase hebben die wordt uitgevoerd als geen van de cases gereed is.

Laten we de onderstaande code bekijken

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

Als u het bovenstaande programma uitvoert, krijgt u de uitvoer:

from data2()

Hier wacht de select-instructie tot er gegevens beschikbaar zijn in een van de kanalen. De data2() voegt gegevens toe aan het kanaal na een slaap van 2 seconden, waardoor het tweede geval wordt uitgevoerd.

Voeg een standaardgeval toe aan de selectie in hetzelfde programma en bekijk de uitvoer. Hier, bij het bereiken van het geselecteerde blok, en als geen enkel geval gegevens gereed heeft op het kanaal, zal het het standaardblok uitvoeren zonder te wachten tot gegevens beschikbaar zijn op welk kanaal dan ook.

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

Dit programma geeft de uitvoer:

Default case executed			

Dit komt omdat toen het geselecteerde blok werd bereikt, geen enkel kanaal gegevens had om te lezen. Het standaardgeval wordt dus uitgevoerd.

mutex

Mutex is de korte vorm voor wederzijdse uitsluiting. Mutex wordt gebruikt wanneer u niet wilt dat een resource door meerdere subroutines tegelijk wordt benaderd. Mutex heeft 2 methoden: Lock en Unlock. Mutex is opgenomen in het sync-pakket. U moet dus het sync-pakket importeren. De statements die wederzijds exclusief moeten worden uitgevoerd, kunnen in mutex.Lock() en mutex.Unlock() worden geplaatst.

Laten we mutex leren met een voorbeeld waarin het aantal keren wordt geteld dat een lus wordt uitgevoerd. In dit programma verwachten we dat de routine 10 keer een lus uitvoert en dat de telling in som wordt opgeslagen. Je roept deze routine drie keer aan, zodat het totale aantal 3 moet zijn. Het aantal wordt opgeslagen in een globale variabele aantal.

Eerst voert u het programma uit zonder 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)
}

Bekijk het resultaat

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

Het resultaat kan anders zijn als u het uitvoert, maar het eindresultaat zal niet 30 zijn.

Wat er hier gebeurt, is dat 3 goroutines proberen het aantal lussen dat is opgeslagen in het aantal variabelen te verhogen. Stel dat de telling op een gegeven moment 5 is en goroutine1 de telling gaat verhogen naar 6. De belangrijkste stappen zijn onder meer

Kopieer telling naar temp

Verhoog de temperatuur

Bewaar de temperatuur terug naar de telling

Stel dat kort na het uitvoeren van stap 3 door goroutine1; een andere goroutine kan een oude waarde hebben, bijvoorbeeld 3, voert de bovenstaande stappen uit en slaat 4 terug, wat verkeerd is. Dit kan worden voorkomen door mutex te gebruiken, waardoor andere routines wachten wanneer een routine de variabele al gebruikt.

Nu voer je het programma uit met mutex. Hier worden de bovengenoemde 3 stappen uitgevoerd in een 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)
}

Nu zal de uitvoer zijn

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

Hier krijgen we het verwachte resultaat als uiteindelijke uitvoer. Omdat het lezen, ophogen en terugschrijven van de telling in een mutex wordt uitgevoerd.

Foutafhandeling

Fouten zijn abnormale omstandigheden, zoals het sluiten van een bestand dat niet is geopend, het openen van een bestand dat niet bestaat, enz. Functies retourneren doorgaans fouten als de laatste geretourneerde waarde.

In het onderstaande voorbeeld wordt meer uitgelegd over de fout.

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

De output zal worden:

open /invalid.txt: no such file or directory

Hier probeerden we een niet-bestaand bestand te openen, en het retourneerde de fout naar de variabele er. Als het bestand geldig is, is de fout nul

Aangepaste fouten

Met deze functie kunt u aangepaste fouten maken. Dit wordt gedaan met behulp van New() van het foutpakket. We zullen het bovenstaande programma herschrijven om gebruik te maken van aangepaste fouten.

Voer het onderstaande programma uit

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

De output zal worden:

Custom error message:File name is wrong

Hier retourneert area() de oppervlakte van een vierkant. Als de invoer kleiner is dan 1, retourneert area() een foutmelding.

Bestanden lezen

Bestanden worden gebruikt om gegevens op te slaan. Met Go kunnen we gegevens uit de bestanden lezen

Maak eerst een bestand, data.txt, in uw huidige map met de onderstaande inhoud.

Line one
Line two
Line three

Voer nu het onderstaande programma uit om te zien dat het de inhoud van het volledige bestand als uitvoer afdrukt

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

Hier lezen de gegevens, err := ioutil.ReadFile(“data.txt”) de gegevens en retourneert een bytereeks. Tijdens het afdrukken wordt het geconverteerd naar stringformaat.

Bestanden schrijven

Je zult dit zien met een programma

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

Hier wordt een bestand gemaakt, test.txt. Als het bestand al bestaat, wordt de inhoud van het bestand afgekapt. Writeline() wordt gebruikt om de inhoud naar het bestand te schrijven. Daarna sloot u het bestand met Close().

Cheatsheet

In deze Go-tutorial hebben we besproken:

Thema Beschrijving Syntaxis
Basistypen Numeriek, tekenreeks, bool
Variabelen Waarden declareren en toewijzen aan variabelen var variabele_naam type
var variabele_naam type = waarde
var variabele_naam1, variabele_naam2 = waarde1, waarde2
variabele_naam:= waarde
constanten Variabelen waarvan de waarde niet kan worden gewijzigd nadat deze is toegewezen const variabele = waarde
For loop Voer instructies in een lus uit. voor initialisatie_expressie; evaluatie_expressie; iteratie_expressie{
// een of meer verklaringen
}
Als anders Het is een voorwaardelijke verklaring als voorwaarde{
// verklaringen_1
Else {}
// verklaringen_2
}
schakelaar Voorwaardelijke verklaring met meerdere gevallen schakel expressie {
casuswaarde_1:
verklaringen_1
casuswaarde_2:
verklaringen_2
hoofdletterwaarde_n:
verklaringen_n
default:
verklaringen_default
}
reeks Vaste grootte benoemde reeks elementen van hetzelfde type arraynaam:= [grootte] type {waarde_0,waarde_1,…,waarde_grootte-1}
Plak Gedeelte of segment van een array var slice_name [] type = array_name[start:eind]
Functies Blok met instructies dat een specifieke taak uitvoert func functienaam(parameter_1 type, parameter_n type) return_type {
//verklaringen
}
Pakketten Worden gebruikt om de code te ordenen. Verhoogt de leesbaarheid en herbruikbaarheid van code importeer pakketnaam
Uitstellen Stelt de uitvoering van een functie uit totdat de bevattende functie de uitvoering voltooit functie_naam uitstellen(parameterlijst)
Pointers Slaat het geheugenadres van een andere variabele op. var variabelenaam *type
Structuur Door de gebruiker gedefinieerd datatype dat zelf nog een element van hetzelfde of een ander type bevat type structnaam struct {
variabele_1 variabele_1_type
variabele_2 variabele_2_type
variabele_n variabele_n_type
}
Methoden Een methode is een functie met een receiver-argument func (variabele variabeletype) methodName(parameterlijst) {
}
Goroutine Een functie die gelijktijdig met andere functies kan worden uitgevoerd. ga naar functienaam(parameterlijst)
Kanaal Manier waarop functies met elkaar kunnen communiceren. Een medium waarop de ene routine gegevens plaatst en waartoe een andere routine toegang heeft. Verklaren:
ch := make(chan int)
Gegevens naar kanaal verzenden:
kanaalvariabele <- variabele_naam
Ontvangen van kanaal:
variabele_naam := <- kanaal_variabele
kies Switch-statement dat op kanalen werkt. De case-statements zijn een kanaalbewerking. Wanneer een van de kanalen klaar is met data, wordt de statement die aan die case is gekoppeld uitgevoerd. selecteer {
geval x := <-chan1:
fmt.Println(x)
geval y := <-chan2:
fmt.Println(y)
}
mutex Mutex wordt gebruikt als u niet wilt dat meerdere subroutines tegelijkertijd toegang hebben tot een bron. Mutex heeft 2 methoden: vergrendelen en ontgrendelen mutex.Lock()
//verklaringen
mutex.Ontgrendelen().
Lees bestanden Leest de gegevens en retourneert een bytereeks. Gegevens, fout := ioutil.ReadFile(bestandsnaam)
Schrijf bestand Schrijft gegevens naar een bestand l, fout := f.WriteString(text_to_write)