Golang-tutorial: Lær Go-programmeringssprog for begyndere

Hvad er Go?

Go (også kendt som Golang) er et open source programmeringssprog udviklet af Google. Det er et statisk skrevet kompileret sprog. Go understøtter samtidig programmering, dvs. det tillader at køre flere processer samtidigt. Dette opnås ved hjælp af kanaler, goroutiner osv. Go Language har skraldopsamling, som selv udfører hukommelseshåndteringen og tillader udskudt udførelse af funktioner.

Vi vil lære alt det grundlæggende om Golang i denne Lær Go Language Tutorial.

Sådan downloades og installeres GO

Trin 1) Gå til https://golang.org/dl/. Download binær til dit OS.

Trin 2) Double klik på installationsprogrammet og klik på Kør.

Trin 3) Klik på Næste

Trin 4) Vælg installationsmappen, og klik på Næste.

Trin 5) Klik på Udfør, når installationen er fuldført.

Trin 6) Når installationen er færdig, kan du bekræfte den ved at åbne terminalen og skrive

go version

Dette vil vise versionen af ​​go installeret

Dit First Go-program – Go Hello World!

Opret en mappe kaldet studyGo. I denne Go-sprogtutorial vil vi oprette vores go-programmer i denne mappe. Go-filer oprettes med udvidelsen .gå. Du kan køre Go-programmer ved hjælp af syntaksen

go run <filename>

Opret en fil kaldet first.go og tilføj nedenstående kode i den og gem

package main
import ("fmt")

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

Naviger til denne mappe i din terminal. Kør programmet ved hjælp af kommandoen

gå løb først.gå

Du kan se output-udskrivningen

Hello World! This is my first Go program

Lad os nu diskutere ovenstående program.

hovedpakke – Hvert Go Language-program skal starte med et pakkenavn. Go giver os mulighed for at bruge pakker i andre go-programmer og understøtter derfor genbrugbar kode. Udførelse af et Go-program begynder med koden inde i pakken med navnet main.

import fmt – importerer pakken fmt. Denne pakke implementerer I/O-funktionerne.

func main() – Dette er den funktion, hvorfra programafviklingen begynder. Hovedfunktionen skal altid placeres i hovedpakken. Under main() kan du skrive koden inde i { }.

fmt.Println – Dette vil udskrive teksten på skærmen ved hjælp af Println-funktionen i fmt.

Bemærk: I nedenstående sektioner af denne Go-tutorial, når du nævner eksekver/kør koden, betyder det at gemme koden i en fil med .go-udvidelsen og køre den ved hjælp af syntaksen

    go run <filename>

Datatyper

Typer (datatyper) repræsenterer typen af ​​værdien gemt i en variabel, typen af ​​værdien en funktion returnerer osv.

Der er tre grundlæggende typer i Go Language

Numeriske typer – Repræsenterer numeriske værdier, som inkluderer heltal, flydende komma og komplekse værdier. Forskellige numeriske typer er:

int8 – 8 bit signerede heltal.

int16 – 16 bit signerede heltal.

int32 – 32 bit signerede heltal.

int64 – 64 bit signerede heltal.

uint8 – 8 bit usignerede heltal.

uint16 – 16 bit usignerede heltal.

uint32 – 32 bit usignerede heltal.

uint64 – 64 bit usignerede heltal.

flydende 32 – 32 bit flydende kommatal.

flydende 64 – 64 bit flydende kommatal.

complex64 – har float32 reelle og imaginære dele.

complex128 – har float32 reelle og imaginære dele.

Strengetyper – Repræsenterer en sekvens af bytes(tegn). Du kan udføre forskellige operationer på strenge som strengsammenkædning, udtrækning af understreng osv

booleske typer – Repræsenterer 2 værdier, enten sande eller falske.

Golang grænseflade

Golang grænseflade er en samling af metodesignaturer, der bruges af en Type til at implementere objekters adfærd. Hovedmålet med Golang-grænsefladen er at give metodesignaturer med navne, argumenter og returtyper. Det er op til en Type at erklære og implementere metoden. En grænseflade i Golang kan erklæres ved hjælp af søgeordet "grænseflade".

Variabler

Variabler peger på en hukommelsesplacering, som gemmer en form for værdi. Typeparameteren (i nedenstående syntaks) repræsenterer den type værdi, der kan gemmes i hukommelsesplaceringen.

Variabel kan erklæres ved hjælp af syntaksen

    var <variable_name> <type>

Når du erklærer en variabel af en type, kan du tildele variablen til enhver værdi af den type.

Du kan også give en startværdi til en variabel under selve deklarationen ved hjælp af

    var <variable_name> <type> = <value>

Hvis du erklærer variablen med en begyndelsesværdi, skal du gå og udlede variablens type ud fra den tildelte værditype. Så du kan udelade typen under erklæringen ved hjælp af syntaksen

    var <variable_name> = <value>

Du kan også erklære flere variabler med syntaksen

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

Nedenstående program i denne Go-tutorial har nogle Golang-eksempler på variable erklæringer

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

Udgangen bliver

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

Go Language giver også en nem måde at erklære variablerne med værdi ved at udelade nøgleordet var ved at bruge

    <variable_name> := <value>

Bemærk, at du brugte := i stedet for =. Du kan ikke bruge := bare til at tildele en værdi til en variabel, som allerede er deklareret. := bruges til at erklære og tildele værdi.

Opret en fil kaldet assign.go med følgende kode

package main
import ("fmt")

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

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

Udfør go run assign.go for at se resultatet som

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

Variabler erklæret uden en startværdi vil have 0 for numeriske typer, falsk for boolesk og tom streng for strenge

Konstanter

Konstante variabler er de variable, hvis værdi ikke kan ændres, når de først er tildelt. En konstant i Go programmeringssprog erklæres ved at bruge søgeordet "const"

Opret en fil kaldet constant.go og med følgende kode

package main
import ("fmt")

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

Udfør go run constant.go for at se resultatet som

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

For løkkeeksempler

Sløjfer bruges til at udføre en blok af udsagn gentagne gange baseret på en betingelse. De fleste programmeringssprog giver 3 typer loops - for, mens, do while. Men Go-programmeringssproget understøtter kun loop.

Syntaksen for en Golang for loop er

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

Initialiseringsudtrykket udføres først (og kun én gang) i Golang for loop.

Derefter evalueres evaluation_expression, og hvis det er sandt, udføres koden inde i blokken.

Iteration_expression-id'et udføres, og evaluation_expression evalueres igen. Hvis det er sandt, udføres sætningsblokken igen. Dette vil fortsætte, indtil evaluation_expression bliver falsk.

Kopier nedenstående program ind i en fil og kør den for at se Golang for loop-udskrivningsnumre fra 1 til 5

package main
import "fmt"

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

Output er

1
2
3
4
5

Hvis ellers

Hvis andet er en betinget erklæring. Synaksen er

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

Her evalueres betingelsen, og hvis den er sand, vil statements_1 blive eksekveret, ellers vil statements_2 blive eksekveret.

Du kan også bruge if-sætning uden andet. Du kan også have lænket if else-udsagn. Nedenstående programmer vil forklare mere om, hvis andet.

Udfør nedenstående program. Den kontrollerer, om et tal, x, er mindre end 10. Hvis det er tilfældet, vil den udskrive "x er mindre end 10"

package main
import "fmt"

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

Da værdien af ​​x her er større end 10, vil sætningen inde i if-blokbetingelsen ikke blive udført.

Se nu nedenstående program. I denne Go-programmeringssprogstutorial har vi en anden blok, som vil blive udført ved fejl i if-evaluering.

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

Dette program vil give dig output

x is greater than or equals 10

Nu i denne Go-tutorial vil vi se et program med flere if else-blokke (kædet hvis andet). Udfør nedenstående Go-eksempel. Den kontrollerer, om et tal er mindre end 10 eller er mellem 10-90 eller større end 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")
    }
}

Her kontrollerer først if-betingelsen, om x er mindre end 10, og det er den ikke. Så det tjekker den næste betingelse (ellers hvis), om den er mellem 10 og 90, hvilket også er falsk. Så den udfører derefter blokken under else-sektionen, som giver output

x is greater than 90

Kontakt

Switch er en anden betinget erklæring. Switch-sætninger evaluerer et udtryk, og resultatet sammenlignes med et sæt tilgængelige værdier(cases). Når et match er fundet, udføres de udsagn, der er knyttet til det match(casus). Hvis der ikke findes noget match, vil intet blive udført. Du kan også tilføje en standard case til at skifte, som vil blive udført, hvis der ikke findes andre matches. Syntaksen for switchen er

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

Her sammenlignes udtrykkets værdi med værdierne i hvert enkelt tilfælde. Når et match er fundet, udføres de erklæringer, der er knyttet til den pågældende sag. Hvis der ikke findes noget match, udføres sætningerne under standardafsnittet.

Udfør nedenstående program

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

Du får output som

Sum is 3		

Ændre værdien af ​​a og b til 3 og resultatet bliver

Printing default

Du kan også have flere værdier i en sag ved at adskille dem med et komma.

Arrays

Array repræsenterer en fast størrelse, navngivet sekvens af elementer af samme type. Du kan ikke have en matrix, der indeholder både heltal og tegn. Du kan ikke ændre størrelsen på et array, når først du har defineret størrelsen.

Syntaksen til at erklære et array er

var arrayname [size] type

Hvert array-element kan tildeles værdi ved hjælp af syntaksen

arrayname [index] = value

Array-indeks starter fra 0 til størrelse-1.

Du kan tildele værdier til matrixelementer under erklæringen ved hjælp af syntaksen

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

Du kan også ignorere størrelsesparameteren, mens du erklærer arrayet med værdier ved at erstatte størrelse med ... og compileren vil finde længden ud fra antallet af værdier. Syntaks er

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

Du kan finde længden af ​​arrayet ved at bruge syntaksen

len(arrayname)

Udfør nedenstående Go-eksempel for at forstå arrayet

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

Produktion

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

Golang Slice and Append-funktion

En skive er en del eller et segment af et array. Eller det er en visning eller delvis visning af en underliggende matrix, som den peger på. Du kan få adgang til elementerne i et udsnit ved hjælp af udsnitsnavnet og indeksnummeret, ligesom du gør i et array. Du kan ikke ændre længden af ​​et array, men du kan ændre størrelsen på et udsnit.

Indholdet af en skive er faktisk pejlemærkerne til elementerne i et array. Det betyder hvis du ændrer et element i et udsnit, vil det underliggende matrixindhold også blive påvirket.

Syntaksen for at oprette et udsnit er

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

Dette vil oprette et udsnit ved navn udsnit_navn fra et array ved navn array_navn med elementerne ved indekset start til slut-1.

Nu i denne Golang tutorial, vil vi udføre nedenstående program. Programmet vil oprette et udsnit fra arrayet og udskrive det. Du kan også se, at ændring af indholdet i udsnittet vil ændre det faktiske array.

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

Dette vil udskrive resultatet som

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]

Der er visse funktioner som Golang len, Golang append, som du kan anvende på skiver

len(slice_name) – returnerer længden af ​​skiven

tilføje(udsnit_navn, værdi_1, værdi_2) – Golang append bruges til at tilføje værdi_1 og værdi_2 til et eksisterende udsnit.

tilføje(udsnit_nale1,udsnit_navn2...) – føjer udsnit_navn2 til udsnit_navn1

Udfør følgende program.

package main
import "fmt"

func main() {  
	a := [5] string {"1","2","3","4","5"}
	slice_a := a[1:3]
	b := [5] string {"one","two","three","four","five"}
	slice_b := b[1:3]

    fmt.Println("Slice_a:", slice_a)
    fmt.Println("Slice_b:", slice_b)
    fmt.Println("Length of slice_a:", len(slice_a))
    fmt.Println("Length of slice_b:", len(slice_b))

    slice_a = append(slice_a,slice_b...) // appending slice
    fmt.Println("New Slice_a after appending slice_b :", slice_a)
    
    slice_a = append(slice_a,"text1") // appending value
    fmt.Println("New Slice_a after appending text1 :", slice_a)
}

Udgangen bliver

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]

Programmet opretter først 2 skiver og udskrev dens længde. Derefter føjede den en skive til den anden og føjede derefter en streng til den resulterende skive.

Funktioner

En funktion repræsenterer en blok af udsagn, som udfører en bestemt opgave. En funktionserklæring fortæller os funktionsnavn, returtype og inputparametre. Funktionsdefinition repræsenterer koden indeholdt i funktionen. Syntaksen til at erklære funktionen er

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

Parametrene og returtyperne er valgfrie. Du kan også returnere flere værdier fra en funktion.

Lad os nu i denne Golang-tutorial køre følgende Golang-eksempel. Her vil en funktion kaldet calc acceptere 2 tal og udføre addition og subtraktion og returnerer begge værdier.

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

Udgangen bliver

Sum 25
Diff 5

Pakker

Pakker bruges til at organisere koden. I et stort projekt er det ikke muligt at skrive kode i en enkelt fil. Go programmeringssprog giver os mulighed for at organisere koden under forskellige pakker. Dette øger kodelæsbarheden og genbrugbarheden. Et eksekverbart Go-program bør indeholde en pakke med navnet main, og programafviklingen starter fra funktionen med navnet main. Du kan importere andre pakker i vores program ved hjælp af syntaksen

import package_name

Vi vil se og diskutere i denne Golang-tutorial, hvordan man opretter og bruger pakker i det følgende Golang-eksempel.

Trin 1) Opret en fil kaldet package_example.go og tilføj nedenstående kode

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

I ovenstående program er fmt en pakke, som Go-programmeringssproget giver os hovedsageligt til I/O-formål. Du kan også se en pakke med navnet beregning. Inde i main() kan du se en trinsum := beregning.Do_add(x,y). Det betyder, at du aktiverer funktionen Do_add fra pakkeberegning.

Trin 2) Først skal du oprette pakkeberegningen inde i en mappe med samme navn under src-mappen på farten. Den installerede sti til go kan findes fra PATH-variablen.

For mac, find stien ved at udføre echo $PATH

Så stien er /usr/local/go

For Windows, find stien ved at udføre echo %GOROOT%

Her er stien C:\Go\

Trin 3) Naviger til mappen src (/usr/local/go/src til mac og C:\Go\src til Windows). Nu fra koden er pakkenavnet beregning. Go kræver, at pakken skal placeres i en mappe af samme navn under src-mappen. Opret en mappe med navnet beregning i mappen src.

Trin 4) Opret en fil kaldet calc.go (Du kan give et hvilket som helst navn, men pakkenavnet i koden betyder noget. Her skal det være beregning) inde i beregningsmappen og tilføj nedenstående kode

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

Trin 5) Kør kommandoen go install fra beregningsmappen, som vil kompilere calc.go.

Trin 6) Gå nu tilbage til package_example.go og kør go run package_example.go. Outputtet vil være Sum 25.

Bemærk, at navnet på funktionen Do_add starter med et stort bogstav. Dette skyldes, at i Go, hvis funktionsnavnet starter med et stort bogstav, betyder det, at andre programmer kan se (få adgang), ellers kan andre programmer ikke få adgang til det. Hvis funktionsnavnet var do_add , så ville du have fået fejlen

kan ikke henvise til ueksporteret navneberegning.beregning..

Defer og stabling udskyder

Defer-sætninger bruges til at udskyde udførelsen af ​​et funktionskald, indtil funktionen, der indeholder defer-sætningen, fuldfører udførelsen.

Lad os lære dette med et eksempel:

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

Udgangen bliver

Inside the main()
Inside the sample()

Her udsættes udførelsen af ​​sample() indtil udførelsen af ​​den omsluttende funktion(main()) er fuldført.

Stacking defer bruger flere defer-udsagn. Antag, at du har flere defer-sætninger inde i en funktion. Go placerer alle de udskudte funktionskald i en stak, og når den omsluttende funktion vender tilbage, udføres de stablede funktioner i Last In First Out (LIFO) rækkefølge. Du kan se dette i eksemplet nedenfor.

Udfør nedenstående kode

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

Udgangen bliver

4
3
2
1			

Her udføres koden inde i main() først, og derefter udføres de udskudte funktionskald i omvendt rækkefølge, dvs. 4, 3,2,1.

Pointers

Før vi forklarer pointer, lad os først diskutere '&'-operatoren. Operatoren '&' bruges til at få adressen på en variabel. Det betyder, at '&a' vil udskrive hukommelsesadressen for variabel a.

I denne Golang tutorial vil vi udføre nedenstående program for at vise værdien af ​​en variabel og adressen på den variabel

package main
import "fmt"

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

Resultatet bliver

Address: 0xc000078008
Value: 20

En pointervariabel gemmer hukommelsesadressen for en anden variabel. Du kan definere en markør ved hjælp af syntaksen

	var variable_name *type

Stjernen(*) repræsenterer variablen er en pointer. Du vil forstå mere ved at udføre nedenstående program

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

Udgangen bliver

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

Strukturer

En struktur er en brugerdefineret datatype, som i sig selv indeholder et element mere af samme eller anden type.

Brug af en struktur er en 2-trins proces.

Først skal du oprette (erklære) en strukturtype

For det andet skal du oprette variabler af den type for at gemme værdier.

Strukturer bruges hovedsageligt, når du vil gemme relaterede data sammen.

Overvej et stykke medarbejderinformation, som har navn, alder og adresse. Du kan håndtere dette på 2 måder

Opret 3 arrays – et array gemmer medarbejdernes navne, et lagrer alder og det tredje lagrer alder.

Angiv en strukturtype med 3 felter - navn, adresse og alder. Opret en matrix af den strukturtype, hvor hvert element er et strukturobjekt med navn, adresse og alder.

Den første tilgang er ikke effektiv. I den slags scenarier er strukturer mere bekvemme.

Syntaksen til at erklære en struktur er

type structname struct {
   variable_1 variable_1_type
   variable_2 variable_2_type
   variable_n variable_n_type
}

Et eksempel på en strukturdeklaration er

type emp struct {
    name string
    address string
    age int
}

Her oprettes en ny brugerdefineret type ved navn emp. Nu kan du oprette variabler af typen emp ved hjælp af syntaksen

	var variable_name struct_name

Et eksempel er

var empdata1 emp 

Du kan indstille værdier for empdata1 as

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

Du kan også oprette en strukturvariabel og tildele værdier ved

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

Her skal du bevare rækkefølgen af ​​elementer. Raj vil blive kortlagt til navn, næste element til adresse og det sidste til alder.

Udfør koden nedenfor

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

Produktion

John
Raj

Metoder (ikke funktioner)

En metode er en funktion med et modtagerargument. Archirent teknisk er det mellem func nøgleordet og metodenavnet. Syntaksen for en metode er

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

Lad os konvertere ovenstående eksempelprogram til at bruge metoder i stedet for funktion.

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 er ikke et objektorienteret sprog, og det har ikke begrebet klasse. Metoder giver en fornemmelse af, hvad du gør i objektorienterede programmer, hvor funktionerne i en klasse påkaldes ved hjælp af syntaksen objektnavn.funktionsnavn()

samtidighed

Go understøtter samtidig udførelse af opgaver. Det betyder, at Go kan udføre flere opgaver samtidigt. Det er forskelligt fra begrebet parallelisme. I parallelisme er en opgave opdelt i små delopgaver og udføres parallelt. Men samtidig udføres flere opgaver samtidigt. Samtidig opnås i Go ved hjælp af Goroutines og Channels.

Goroutiner

En goroutine er en funktion, der kan køre samtidig med andre funktioner. Normalt, når en funktion påkaldes, overføres kontrollen til den kaldte funktion, og når dens afsluttede udførelseskontrol vender tilbage til den kaldende funktion. Den kaldende funktion fortsætter derefter sin udførelse. Den kaldende funktion venter på, at den påkaldte funktion fuldfører udførelsen, før den fortsætter med resten af ​​sætningerne.

Men i tilfælde af goroutine, vil den kaldende funktion ikke vente på, at udførelsen af ​​den påkaldte funktion er fuldført. Det vil fortsætte med at udføre med de næste erklæringer. Du kan have flere goroutiner i et program.

Hovedprogrammet afsluttes også, når det er færdigt med at udføre sine udsagn, og det vil ikke vente på færdiggørelsen af ​​de påberåbte goroutiner.

Goroutine påkaldes ved hjælp af nøgleordet go efterfulgt af et funktionskald.

Eksempel

go add(x,y)

Du vil forstå goroutiner med nedenstående Golang-eksempler. Udfør nedenstående program

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

Udgangen bliver

In main
In main
In main
In main
In main

Her afsluttede hovedprogrammet eksekveringen, allerede før goroutinen startede. Display() er en goroutine, som fremkaldes ved hjælp af syntaksen

go function_name(parameter list)

I ovenstående kode venter main() ikke på, at display() er færdig, og main() fuldførte sin udførelse, før display() udførte sin kode. Så print-erklæringen inde i display() blev ikke udskrevet.

Nu ændrer vi programmet til også at udskrive udsagn fra display(). Vi tilføjer en tidsforsinkelse på 2 sek. i for-løkken i main() og en forsinkelse på 1 sek. i for-løkken på 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")
	}
}

Outputtet vil ligne noget

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

Her kan du se, at begge loops udføres på en overlappende måde på grund af den samtidige udførelse.

Kanaler

Kanaler er en måde, hvorpå funktioner kan kommunikere med hinanden. Det kan opfattes som et medium til, hvor en rutine placerer data og tilgås af en anden rutine i Golang-serveren.

En kanal kan erklæres med syntaksen

channel_variable := make(chan datatype)

Eksempel:

	ch := make(chan int)

Du kan sende data til en kanal ved hjælp af syntaksen

channel_variable <- variable_name

Eksempel

    ch <- x

Du kan modtage data fra en kanal ved hjælp af syntaksen

    variable_name := <- channel_variable

Eksempel

   y := <- ch

I ovenstående Go-sprogeksempler på goroutine har du set, at hovedprogrammet ikke venter på goroutinen. Men det er ikke tilfældet, når kanaler er involveret. Antag, at hvis en goroutine skubber data til kanal, vil main() vente på sætningen, der modtager kanaldata, indtil den får dataene.

Du vil se dette i nedenstående Go sprogeksempler. Skriv først en normal goroutine og se adfærden. Rediger derefter programmet til at bruge kanaler og se adfærden.

Udfør nedenstående program

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

Udgangen bliver

Inside main()

Main() afsluttede udførelsen og afsluttede før goroutinen eksekveres. Så udskriften inde i display() blev ikke udført.

Rediger nu ovenstående program for at bruge kanaler og se adfærden.

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

Udgangen bliver

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

Her, hvad der sker, er main() ved at nå x := <-ch vil vente på data på kanal ch. Displayet() har en ventetid på 5 sekunder og skubber derefter data til kanalen ch. Main() ved modtagelse af data fra kanalen bliver blokeret og fortsætter sin eksekvering.

Afsenderen, der pusher data til kanal, kan informere modtagerne om, at der ikke vil blive tilføjet flere data til kanalen ved at lukke kanalen. Dette bruges hovedsageligt, når du bruger en loop til at skubbe data til en kanal. En kanal kan lukkes vha

close(channel_name)

Og i modtagerenden er det muligt at kontrollere, om kanalen er lukket ved hjælp af en ekstra variabel, mens der hentes data fra kanalen vha.

variable_name, status := <- channel_variable

Hvis status er Sand, betyder det, at du har modtaget data fra kanalen. Hvis falsk, betyder det, at du forsøger at læse fra en lukket kanal

Du kan også bruge kanaler til kommunikation mellem goroutiner. Skal bruge 2 goroutiner - den ene skubber data til kanalen og den anden modtager dataene fra kanalen. Se nedenstående program

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

Her er der 2 underrutiner, den ene skubber data til kanalen og den anden udskriver data til kanalen. Funktionen add_to_channel tilføjer tallene fra 0 til 9 og lukker kanalen. Samtidig venter funktionen fetch_from_channel kl

x, flag := <- ch og når dataene bliver tilgængelige, udskriver den dataene. Den afsluttes, når flaget er falsk, hvilket betyder, at kanalen er lukket.

Ventetiden i main() er givet for at forhindre, at main() forlades, indtil goroutinerne afslutter udførelsen.

Udfør koden og se output som

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

Type

Select kan ses som en switch-erklæring, der fungerer på kanaler. Her vil sagsfremstillingerne være en kanaloperation. Normalt vil hver case-udsagn blive læst forsøg fra kanalen. Når nogen af ​​sagerne er klar (kanalen læses), udføres den erklæring, der er knyttet til sagen. Hvis flere sager er klar, vil den vælge en tilfældig. Du kan have en standardsag, som udføres, hvis ingen af ​​sagerne er klar.

Lad os se nedenstående kode

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

Udførelse af ovenstående program vil give output:

from data2()

Her venter select-erklæringen på, at data er tilgængelige i nogen af ​​kanalerne. Data2() tilføjer data til kanalen efter en dvale på 2 sekunder, hvilket vil få det andet tilfælde til at udføres.

Tilføj en standard case til valget i det samme program og se outputtet. Her, når den valgte blok er nået, hvis ingen sag har data klar på kanalen, vil den udføre standardblokken uden at vente på, at data er tilgængelige på nogen kanal.

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

Dette program vil give output:

Default case executed			

Dette skyldes, at når den valgte blok nåede, havde ingen kanal data til læsning. Så standardsagen udføres.

mutex

Mutex er den korte form for gensidig udelukkelse. Mutex bruges, når du ikke ønsker at tillade, at en ressource skal tilgås af flere underrutiner på samme tid. Mutex har 2 metoder - Lås og Lås op. Mutex er indeholdt i sync-pakken. Så du skal importere synkroniseringspakken. Udsagn, der skal udføres gensidigt, kan placeres i mutex.Lock() og mutex.Unlock().

Lad os lære mutex med et eksempel, der tæller antallet af gange, en loop udføres. I dette program forventer vi, at rutinen kører loop 10 gange, og tællingen er gemt i sum. Du kalder denne rutine 3 gange, så det samlede antal skal være 30. Optællingen er gemt i en global variabel optælling.

Først kører du programmet uden 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)
}

Se resultatet

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

Resultatet kan være anderledes, når du udfører det, men det endelige resultat vil ikke være 30.

Her, hvad der sker, er 3 goroutiner, der forsøger at øge sløjfeantallet, der er gemt i det variable antal. Antag, at tallet på et tidspunkt er 5, og goroutine1 vil øge tallet til 6. De vigtigste trin omfatter

Kopier tæller til temp

Øg temp

Gem temperaturen tilbage for at tælle

Antag kort efter at have udført trin 3 ved goroutine1; en anden goroutine kan have en gammel værdi, f.eks. 3 udfører ovenstående trin og gemmer 4 tilbage, hvilket er forkert. Dette kan forhindres ved at bruge mutex, som får andre rutiner til at vente, når en rutine allerede bruger variablen.

Nu vil du køre programmet med mutex. Her udføres de ovennævnte 3 trin i en 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 bliver outputtet

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

Her får vi det forventede resultat som endeligt output. Fordi udsagn læsning, stigning og tilbageskrivning af optælling udføres i en mutex.

Fejl ved håndtering

Fejl er unormale forhold som at lukke en fil, der ikke er åbnet, åbne en fil, der ikke eksisterer, osv. Funktioner returnerer normalt fejl som den sidste returværdi.

Nedenstående eksempel forklarer mere om fejlen.

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

Outputtet vil være:

open /invalid.txt: no such file or directory

Her forsøgte vi at åbne en ikke-eksisterende fil, og den returnerede fejlen til er variabel. Hvis filen er gyldig, vil fejlen være nul

Brugerdefinerede fejl

Ved at bruge denne funktion kan du oprette brugerdefinerede fejl. Dette gøres ved at bruge New() i fejlpakken. Vi vil omskrive ovenstående program for at gøre brug af brugerdefinerede fejl.

Kør nedenstående program

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

Outputtet vil være:

Custom error message:File name is wrong

Her returnerer arealet () arealet af et kvadrat. Hvis input er mindre end 1, returnerer area() en fejlmeddelelse.

Læsning af filer

Filer bruges til at gemme data. Go giver os mulighed for at læse data fra filerne

Opret først en fil, data.txt, i din nuværende mappe med nedenstående indhold.

Line one
Line two
Line three

Kør nu nedenstående program for at se, at det udskriver indholdet af hele filen som output

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

Her læser dataene, err := ioutil.ReadFile(“data.txt”) dataene og returnerer en bytesekvens. Under udskrivning konverteres den til strengformat.

Skrivning af filer

Du vil se dette med et program

package main
import "fmt"
import "os"

func main() {  
    f, err := os.Create("file1.txt")
    if err != nil {
        fmt.Println(err)
        return
    }
    l, err := f.WriteString("Write Line one")
    if err != nil {
        fmt.Println(err)
        f.Close()
        return
    }
    fmt.Println(l, "bytes written")
    err = f.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
}

Her oprettes en fil, test.txt. Hvis filen allerede eksisterer, afkortes indholdet af filen. Writeline() bruges til at skrive indholdet til filen. Derefter lukkede du filen ved hjælp af Close().

Cheat Sheet

I denne Go-tutorial dækkede vi,

Emne Description Syntaks
Grundlæggende typer Numerisk, streng, bool
Variabler Erklære og tildele værdier til variabler var variabel_navn type
var variabelnavn type = værdi
var variabel_navn1, variabel_navn2 = værdi1, værdi2
variabelnavn := værdi
Konstanter Variabler, hvis værdi ikke kan ændres, når de først er tildelt const variabel = værdi
Til Loop Udfør sætninger i en løkke. for initialiseringsudtryk; evaluation_expression; iteration_expression{
// en eller flere udsagn
}
Hvis ellers Det er en betinget erklæring hvis betingelse{
// udsagn_1
Else {}
// udsagn_2
}
skifte Betinget erklæring med flere sager skifte udtryk {
case value_1:
udsagn_1
case value_2:
udsagn_2
case value_n:
udsagn_n
Standard:
statements_default
}
Array Fast størrelse navngivet sekvens af elementer af samme type matrixnavn := [størrelse] type {værdi_0, værdi_1,..., værdi_størrelse-1}
Slice Del eller segment af et array var slice_name [] type = array_name[start:slut]
Funktioner Blok af udsagn, der udfører en bestemt opgave func funktionsnavn(parameter_1 type, parameter_n type) return_type {
//udsagn
}
Pakker Bruges til at organisere koden. Øger kodelæsbarhed og genbrugbarhed importer pakke_nam
Udsætte Udsætter udførelsen af ​​en funktion, indtil den indeholdende funktion afslutter udførelsen udskyde funktionsnavn (parameterliste)
Pointers Gemmer hukommelsesadressen for en anden variabel. var variabelnavn *type
Struktur Brugerdefineret datatype, som i sig selv indeholder et element mere af samme eller anden type skriv structname struct {
variabel_1 variabel_1_type
variabel_2 variabel_2_type
variabel_n variabel_n_type
}
Metoder En metode er en funktion med et modtagerargument func (variabel variabeltype) methodName(parameter_list) {
}
Goroutine En funktion, der kan køre samtidig med andre funktioner. gå funktionsnavn (parameterliste)
Kanal Måde for funktioner at kommunikere med hinanden. Et medie, hvor en rutine placerer data og tilgås af en anden rutine. Erklære:
ch := make(chan int)
Send data til kanal:
kanalvariabel <- variabel_navn
Modtag fra kanal:
variabel_navn := <- kanalvariabel
Type Switch statement, der virker på kanaler. Sagsudtalelserne vil være en kanaloperation. Når en af ​​kanalerne er klar med data, udføres den erklæring, der er knyttet til den pågældende sag Vælg {
case x := <-chan1:
fmt.Println(x)
case y := <-chan2:
fmt.Println(y)
}
mutex Mutex bruges, når du ikke ønsker at tillade, at en ressource skal tilgås af flere underrutiner på samme tid. Mutex har 2 metoder - Lås og Lås op mutex.Lock()
//udsagn
mutex.Unlock().
Læs filer Læser dataene og returnerer en bytesekvens. Data, fejl := ioutil.ReadFile(filnavn)
Skriv fil Skriver data til en fil l, fejl := f.WriteString(text_to_write)