Výukový program Golangu

Co je Go?

Go (také známý jako Golang) je programovací jazyk s otevřeným zdrojovým kódem vyvinutý společností Google. Je to staticky typovaný kompilovaný jazyk. Go podporuje souběžné programování, tj. umožňuje spouštět více procesů současně. Toho je dosaženo pomocí kanálů, goroutin atd. Go Language má garbage collection, který sám provádí správu paměti a umožňuje odložené provádění funkcí.

V tomto výukovém programu Learn Go Language se naučíme všechny základy golangu.

Jak stáhnout a nainstalovat GO

Krok 1) Přejít https://golang.org/dl/. Stáhněte si binární soubor pro váš OS.

Krok 2) Double klikněte na instalační program a klikněte na Spustit.

Krok 3) Klepněte na tlačítko Další

Krok 4) Vyberte instalační složku a klikněte na Další.

Krok 5) Po dokončení instalace klikněte na Dokončit.

Krok 6) Jakmile je instalace dokončena, můžete ji ověřit otevřením terminálu a zadáním

go version

Tím se zobrazí nainstalovaná verze go

Váš program First Go – Go Hello World!

Vytvořte složku s názvem studyGo. V tomto kurzu jazyka Go vytvoříme naše programy go uvnitř této složky. Go soubory jsou vytvořeny s příponou .jít. Programy Go můžete spouštět pomocí syntaxe

go run <filename>

Vytvořte soubor s názvem first.go a přidejte do něj níže uvedený kód a uložte

package main
import ("fmt")

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

Přejděte do této složky ve svém terminálu. Spusťte program pomocí příkazu

běž první běžet

Můžete vidět výstupní tisk

Hello World! This is my first Go program

Nyní pojďme diskutovat o výše uvedeném programu.

package main – Každý program Go Language by měl začínat názvem balíčku. Go nám umožňuje používat balíčky v jiných go programech, a proto podporuje opětovné použití kódu. Spuštění programu Go začíná kódem uvnitř balíčku s názvem main.

import fmt – importuje balíček fmt. Tento balíček implementuje I/O funkce.

func main() – Toto je funkce, od které začíná provádění programu. Hlavní funkce by měla být vždy umístěna v hlavním balíčku. Pod main() můžete napsat kód dovnitř { }.

fmt.Println – Toto vytiskne text na obrazovku pomocí funkce Println funkce fmt.

Poznámka: Když v níže uvedených částech tohoto tutoriálu Go zmíníte spustit/spustit kód, znamená to uložit kód do souboru s příponou .go a spustit jej pomocí syntaxe

    go run <filename>

Typy dat

Typy (datové typy) představují typ hodnoty uložené v proměnné, typ hodnoty, kterou funkce vrací atd.

V jazyce Go existují tři základní typy

Číselné typy – Představují číselné hodnoty, které zahrnují celé číslo, plovoucí desetinnou čárku a komplexní hodnoty. Různé číselné typy jsou:

int8 – 8bitová celá čísla se znaménkem.

int16 – 16bitová celá čísla se znaménkem.

int32 – 32bitová celá čísla se znaménkem.

int64 – 64bitová celá čísla se znaménkem.

uint8 – 8bitová celá čísla bez znaménka.

uint16 – 16bitová celá čísla bez znaménka.

uint32 – 32bitová celá čísla bez znaménka.

uint64 – 64bitová celá čísla bez znaménka.

float32 – 32bitová čísla s plovoucí desetinnou čárkou.

float64 – 64bitová čísla s plovoucí desetinnou čárkou.

complex64 – má float32 reálné a imaginární části.

complex128 – má float32 reálné a imaginární části.

Typy řetězců – Představuje posloupnost bajtů (znaků). S řetězci můžete provádět různé operace, jako je zřetězení řetězců, extrahování podřetězců atd

Booleovské typy – Představuje 2 hodnoty, buď true nebo false.

Rozhraní Golang

Rozhraní Golang je kolekce signatur metod používaných typem k implementaci chování objektů. Hlavním cílem rozhraní Golang je poskytnout podpisy metod s názvy, argumenty a návratovými typy. Je na typu, aby deklaroval a implementoval metodu. Rozhraní v Golangu lze deklarovat pomocí klíčového slova „rozhraní“.

Proměnné

Proměnné ukazují na paměťové místo, které ukládá nějaký druh hodnoty. Parametr type (v níže uvedené syntaxi) představuje typ hodnoty, kterou lze uložit do paměti.

Proměnnou lze deklarovat pomocí syntaxe

    var <variable_name> <type>

Jakmile deklarujete proměnnou typu, můžete proměnnou přiřadit libovolné hodnotě tohoto typu.

Můžete také zadat počáteční hodnotu proměnné během samotné deklarace pomocí

    var <variable_name> <type> = <value>

Pokud deklarujete proměnnou s počáteční hodnotou, Go a odvodit typ proměnné z typu přiřazené hodnoty. Takže můžete typ během deklarace vynechat pomocí syntaxe

    var <variable_name> = <value>

Můžete také deklarovat více proměnných pomocí syntaxe

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

Níže uvedený program v tomto tutoriálu Go obsahuje některé příklady Golang deklarací proměnných

 
package main
import "fmt"

func main() {
    //declaring a integer variable x
    var x int
    x=3 //assigning x the value 3 
    fmt.Println("x:", x) //prints 3
    
    //declaring a integer variable y with value 20 in a single statement and prints it
    var y int=20
    fmt.Println("y:", y)
    
    //declaring a variable z with value 50 and prints it
    //Here type int is not explicitly mentioned 
    var z=50
    fmt.Println("z:", z)
    
    //Multiple variables are assigned in single line- i with an integer and j with a string
    var i, j = 100,"hello"
    fmt.Println("i and j:", i,j)
}

Výstup bude

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

Go Language také poskytuje snadný způsob, jak deklarovat proměnné s hodnotou vynecháním klíčového slova var using

    <variable_name> := <value>

Všimněte si, že jste použili := místo =. Nemůžete použít := pouze k přiřazení hodnoty proměnné, která je již deklarována. := se používá k deklaraci a přiřazení hodnoty.

Vytvořte soubor s názvem assign.go s následujícím kódem

package main
import ("fmt")

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

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

Proveďte spuštění příkazu assign.go, abyste viděli výsledek jako

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

Proměnné deklarované bez počáteční hodnoty budou mít 0 pro číselné typy, false pro booleovské a prázdný řetězec pro řetězce

Konstanty

Konstantní proměnné jsou ty proměnné, jejichž hodnotu nelze po přiřazení změnit. Konstanta v programovacím jazyce Go je deklarována pomocí klíčového slova „const“

Vytvořte soubor s názvem konstantní.go a s následujícím kódem

package main
import ("fmt")

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

Proveďte go run konstantní.go, abyste viděli výsledek jako

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

Pro příklady smyčky

Smyčky se používají k opakovanému provádění bloku příkazů na základě podmínky. Většina programovacích jazyků poskytuje 3 typy smyček – for, while, do while. Ale programovací jazyk Go podporuje pouze smyčku.

Syntaxe smyčky Golang for je

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

Inicializační_výraz je proveden jako první (a pouze jednou) ve smyčce Golang for.

Poté je vyhodnocen výraz_vyhodnocení a pokud je pravdivý, provede se kód uvnitř bloku.

Provede se id iteration_expression a znovu se vyhodnotí evaluační_výraz. Pokud je to pravda, blok příkazů se provede znovu. To bude pokračovat, dokud se výraz evaluace nestane nepravdivým.

Zkopírujte níže uvedený program do souboru a spusťte jej, abyste viděli čísla pro tisk smyček Golang for od 1 do 5

package main
import "fmt"

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

Výstup je

1
2
3
4
5

Pokud jinak

If else je podmíněný příkaz. Synax je

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

Zde se vyhodnotí podmínka a pokud je pravdivá, budou provedeny příkazy_1, jinak budou provedeny příkazy_2.

Můžete použít příkaz if bez jiného také. Můžete také mít zřetězené příkazy if else. Níže uvedené programy vysvětlí více o tom, jestli jinak.

Spusťte níže uvedený program. Zkontroluje, zda je číslo x menší než 10. Pokud ano, vypíše „x je menší než 10“

package main
import "fmt"

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

Protože hodnota x je větší než 10, příkaz uvnitř bloku if nebude proveden.

Nyní se podívejte na níže uvedený program. V tomto tutoriálu programovacího jazyka Go máme blok else, který se provede při selhání vyhodnocení if.

package main
import "fmt"

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

Tento program vám poskytne výstup

x is greater than or equals 10

Nyní v tomto tutoriálu Go uvidíme program s více bloky if else (zřetězenými, pokud jinak). Proveďte níže uvedený příklad Go. Kontroluje, zda je číslo menší než 10 nebo mezi 10-90 nebo větší než 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")
    }
}

Zde nejprve podmínka if zkontroluje, zda je x menší než 10 a není. Takže zkontroluje další podmínku (else if), zda je mezi 10 a 90, což je také nepravdivé. Takže pak provede blok v sekci else, která dává výstup

x is greater than 90

Vypínač

Switch je další podmíněný příkaz. Příkazy Switch vyhodnotí výraz a výsledek se porovná se sadou dostupných hodnot (případů). Jakmile je nalezena shoda, jsou provedeny příkazy spojené s touto shodou (případem). Pokud není nalezena žádná shoda, nic se neprovede. Můžete také přidat výchozí případ pro přepnutí, který se provede, pokud nebudou nalezeny žádné jiné shody. Syntaxe přepínače je

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

Zde se hodnota výrazu porovnává s hodnotami v každém případě. Jakmile je nalezena shoda, jsou provedeny příkazy spojené s daným případem. Pokud není nalezena žádná shoda, provedou se příkazy ve výchozí sekci.

Spusťte níže uvedený 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")
    }
}

Získáte výstup jako

Sum is 3		

Změňte hodnotu a a b na 3 a výsledek bude

Printing default

Můžete také mít více hodnot v případě, když je oddělíte čárkou.

Pole

Pole představuje pevnou velikost, pojmenovanou sekvenci prvků stejného typu. Nemůžete mít pole, které obsahuje celé číslo i znaky. Jakmile definujete velikost, nemůžete změnit velikost pole.

Syntaxe pro deklaraci pole je

var arrayname [size] type

Každému prvku pole lze přiřadit hodnotu pomocí syntaxe

arrayname [index] = value

Index pole začíná od 0 až velikost-1.

Hodnoty prvkům pole můžete přiřadit během deklarace pomocí syntaxe

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

Parametr size můžete také ignorovat při deklarování pole s hodnotami nahrazením size za ... a překladač zjistí délku z počtu hodnot. Syntaxe je

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

Délku pole můžete zjistit pomocí syntaxe

len(arrayname)

Chcete-li porozumět poli, spusťte níže uvedený příklad Go

package main
import "fmt"

func main() {  
    var numbers [3] string //Declaring a string array of size 3 and adding elements 
    numbers[0] = "One"
    numbers[1] = "Two"
    numbers[2] = "Three"
    fmt.Println(numbers[1]) //prints Two
    fmt.Println(len(numbers)) //prints 3
    fmt.Println(numbers) // prints [One Two Three]

    directions := [...] int {1,2,3,4,5} // creating an integer array and the size of the array is defined by the number of elements 
    fmt.Println(directions) //prints [1 2 3 4 5]
    fmt.Println(len(directions)) //prints 5

    //Executing the below commented statement prints invalid array index 5 (out of bounds for 5-element array)
    //fmt.Println(directions[5]) 
}

Výstup

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

Funkce Golang Slice and Append

Řez je část nebo segment pole. Nebo je to pohled nebo částečný pohled na základní pole, na které ukazuje. K prvkům řezu můžete přistupovat pomocí názvu řezu a čísla indexu stejně jako v poli. Nemůžete změnit délku pole, ale můžete změnit velikost řezu.

Obsah řezu jsou ve skutečnosti ukazatele na prvky pole. To znamená pokud změníte jakýkoli prvek v řezu, bude ovlivněn i obsah základního pole.

Syntaxe pro vytvoření řezu je

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

Tím se vytvoří řez s názvem název_řezu z pole s názvem název_pole s prvky na začátku indexu až na konci-1.

Nyní v tomto tutoriálu Golang spustíme níže uvedený program. Program z pole vytvoří řez a vytiskne jej. Také můžete vidět, že úprava obsahu v řezu změní skutečné pole.

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

Tím se vytiskne výsledek jako

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]

Existují určité funkce jako Golang len, Golang append, které můžete použít na řezy

len(název_slice) – vrátí délku řezu

připojit(název_dílce, hodnota_1, hodnota_2) – Golang append se používá k připojení value_1 a value_2 k existujícímu řezu.

append(nale_slice1,nazev_slice2…) – připojí název_dílu2 k názvu_dílu1

Spusťte následující 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)
}

Výstup bude

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]

Program nejprve vytvoří 2 řezy a vytiskne jejich délku. Poté připojil jeden plátek k druhému a poté k výslednému plátku připojil řetězec.

Funkce

Funkce představuje blok příkazů, který provádí určitou úlohu. Deklarace funkce nám říká název funkce, návratový typ a vstupní parametry. Definice funkce představuje kód obsažený ve funkci. Syntaxe pro deklaraci funkce je

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

Parametry a návratové typy jsou volitelné. Z funkce můžete také vrátit více hodnot.

Nyní v tomto tutoriálu Golang spustíme následující příklad Golang. Zde funkce s názvem calc přijme 2 čísla a provede sčítání a odčítání a vrací obě hodnoty.

package main
import "fmt"

//calc is the function name which accepts two integers num1 and num2
//(int, int) says that the function returns two values, both of integer type.
func calc(num1 int, num2 int)(int, int) {  
    sum := num1 + num2
    diff := num1 - num2
    return sum, diff
}

func main() {  
    x,y := 15,10

    //calls the function calc with x and y an d gets sum, diff as output
    sum, diff := calc(x,y) 
    fmt.Println("Sum",sum)
    fmt.Println("Diff",diff) 
}

Výstup bude

Sum 25
Diff 5

Balíčky

Balíčky se používají k uspořádání kódu. Ve velkém projektu není možné napsat kód do jednoho souboru. Programovací jazyk Go nám umožňuje organizovat kód do různých balíčků. To zvyšuje čitelnost kódu a opětovnou použitelnost. Spustitelný program Go by měl obsahovat balíček s názvem main a provádění programu začíná funkcí s názvem main. Pomocí syntaxe můžete importovat další balíčky do našeho programu

import package_name

V tomto tutoriálu Golang uvidíme a probereme, jak vytvářet a používat balíčky v následujícím příkladu Golang.

Krok 1) Vytvořte soubor s názvem package_example.go a přidejte níže uvedený kód

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

Ve výše uvedeném programu fmt je balíček, který nám programovací jazyk Go poskytuje především pro I/O účely. Můžete také vidět balíček s názvem výpočet. Uvnitř main() můžete vidět krokový součet := výpočet.Do_add(x,y). To znamená, že vyvoláváte funkci Do_add z výpočtu balíčku.

Krok 2) Nejprve byste měli vytvořit výpočet balíčku ve složce se stejným názvem ve složce src v go. Instalovanou cestu go lze zjistit z proměnné PATH.

Pro Mac najděte cestu spuštěním echo $PATH

Cesta je tedy /usr/local/go

Pro Windows najděte cestu spuštěním echo %GOROOT%

Zde je cesta C:\Go\

Krok 3) Přejděte do složky src (/usr/local/go/src pro Mac a C:\Go\src pro Windows). Nyní z kódu je název balíčku výpočet. Go vyžaduje, aby byl balíček umístěn ve stejnojmenném adresáři v adresáři src. Vytvořte adresář s názvem výpočet ve složce src.

Krok 4) Vytvořte soubor s názvem calc.go (Můžete zadat libovolný název, ale na názvu balíčku v kódu záleží. Zde by to měl být výpočet) v adresáři výpočtu a přidejte níže uvedený kód

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

Krok 5) Spusťte příkaz go install z adresáře pro výpočty, který zkompiluje soubor calc.go.

Krok 6) Nyní se vraťte na package_example.go a spusťte go run package_example.go. Výstupem bude součet 25.

Všimněte si, že název funkce Do_add začíná velkým písmenem. Je to proto, že pokud název funkce v Go začíná velkým písmenem, znamená to, že ji ostatní programy mohou vidět (přistupovat), jiné programy k ní nemají přístup. Pokud by název funkce byl do_add , dostali byste chybu

nemůže odkazovat na neexportovaný výpočet názvu.

Odložit a stohování odloží

Příkazy odložit se používají k odložení provedení volání funkce, dokud funkce obsahující příkaz odložení nedokončí provedení.

Pojďme se to naučit na příkladu:

package main
import "fmt"

func sample() {  
    fmt.Println("Inside the sample()")
}
func main() {  
    //sample() will be invoked only after executing the statements of main()
    defer sample()
    fmt.Println("Inside the main()")
}

Výstup bude

Inside the main()
Inside the sample()

Zde je provedení sample() odloženo, dokud se nedokončí provádění uzavírací funkce (main()).

Stacking odložit používá více příkazů odložení. Předpokládejme, že máte ve funkci více příkazů odložení. Go umístí všechna odložená volání funkcí do zásobníku, a jakmile se vrátí uzavírací funkce, složené funkce se provedou v Pořadí Last In First Out (LIFO). Můžete to vidět na níže uvedeném příkladu.

Spusťte níže uvedený kód

package main
import "fmt"

func display(a int) {  
    fmt.Println(a)
}
func main() {  
    defer display(1)
    defer display(2)
    defer display(3)
    fmt.Println(4)
}

Výstup bude

4
3
2
1			

Zde se nejprve provede kód uvnitř main() a poté se provedou odložená volání funkcí v opačném pořadí, tj. 4, 3,2,1.

Pointers

Před vysvětlením ukazatelů nejprve probereme operátor '&'. Operátor '&' se používá k získání adresy proměnné. Znamená to, že '&a' vytiskne adresu paměti proměnné a.

V tomto tutoriálu Golang spustíme níže uvedený program pro zobrazení hodnoty proměnné a adresy této proměnné

package main
import "fmt"

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

Výsledkem bude

Address: 0xc000078008
Value: 20

Ukazatelská proměnná ukládá paměťovou adresu jiné proměnné. Ukazatel můžete definovat pomocí syntaxe

	var variable_name *type

Hvězdička(*) představuje, že proměnná je ukazatel. Více pochopíte spuštěním níže uvedeného programu

package main
import "fmt"

func main() {
	//Create an integer variable a with value 20
	a := 20
	
	//Create a pointer variable b and assigned the address of a
	var b *int = &a

	//print address of a(&a) and value of a  
	fmt.Println("Address of a:",&a)
	fmt.Println("Value of a:",a)

	//print b which contains the memory address of a i.e. &a
	fmt.Println("Address of pointer b:",b)

	//*b prints the value in memory address which b contains i.e. the value of a
	fmt.Println("Value of pointer b",*b)

	//increment the value of variable a using the variable b
	*b = *b+1

	//prints the new value using a and *b
	fmt.Println("Value of pointer b",*b)
	fmt.Println("Value of a:",a)}

Výstup bude

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

Struktury

Struktura je uživatelsky definovaný datový typ, který sám o sobě obsahuje ještě jeden prvek stejného nebo odlišného typu.

Použití struktury je proces o 2 krocích.

Nejprve vytvořte (deklarujte) typ struktury

Zadruhé vytvořte proměnné tohoto typu pro ukládání hodnot.

Struktury se používají hlavně, když chcete ukládat související data dohromady.

Zvažte část informace o zaměstnanci, která obsahuje jméno, věk a adresu. Můžete to zvládnout 2 způsoby

Vytvořte 3 pole – jedno pole obsahuje jména zaměstnanců, jedno věk a třetí věk.

Deklarujte typ struktury se 3 poli – jméno, adresa a věk. Vytvořte pole tohoto typu struktury, kde každý prvek je objekt struktury se jménem, ​​adresou a stářím.

První přístup není účinný. V těchto typech scénářů jsou struktury pohodlnější.

Syntaxe pro deklaraci struktury je

type structname struct {
   variable_1 variable_1_type
   variable_2 variable_2_type
   variable_n variable_n_type
}

Příkladem deklarace struktury je

type emp struct {
    name string
    address string
    age int
}

Zde se vytvoří nový uživatelsky definovaný typ s názvem emp. Nyní můžete vytvořit proměnné typu emp pomocí syntaxe

	var variable_name struct_name

Příkladem je

var empdata1 emp 

Hodnoty pro empdata1 můžete nastavit jako

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

Můžete také vytvořit proměnnou struktury a přiřadit hodnoty podle

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

Zde musíte zachovat pořadí prvků. Raj bude mapován na jméno, další prvek na adresu a poslední na věk.

Spusťte níže uvedený kód

package main
import "fmt"

//declared the structure named emp
type emp struct {
        name string
        address string
        age int
}       

//function which accepts variable of emp type and prints name property
func display(e emp) {
          fmt.Println(e.name)
}

func main() {
// declares a variable, empdata1, of the type emp
var empdata1 emp
//assign values to members of empdata1
empdata1.name = "John"
empdata1.address = "Street-1, London"
empdata1.age = 30

//declares and assign values to variable empdata2 of type emp
empdata2 := emp{"Raj", "Building-1, Paris", 25}

//prints the member name of empdata1 and empdata2 using display function
display(empdata1)
display(empdata2)
}

Výstup

John
Raj

Metody (ne funkce)

Metoda je funkce s argumentem příjemce. Architechnicky je mezi klíčovým slovem func a názvem metody. Syntaxe metody je

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

Pojďme převést výše uvedený příklad programu tak, aby používal metody místo funkce.

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 není objektově orientovaný jazyk a nemá koncept třídy. Metody poskytují pocit toho, co děláte v objektově orientovaných programech, kde jsou funkce třídy vyvolány pomocí syntaxe objectname.functionname()

Konkurence

Go podporuje souběžné provádění úloh. To znamená, že Go může provádět více úkolů současně. Liší se od konceptu paralelismu. V paralelismu je úloha rozdělena na malé dílčí úlohy a jsou prováděny paralelně. Ale souběžně se současně provádí několik úkolů. Souběžnosti je dosaženo v Go pomocí Goroutines a Channels.

Goroutines

Gorutina je funkce, která může běžet souběžně s jinými funkcemi. Obvykle, když je funkce vyvolána, ovládací prvek se přenese do volané funkce a jakmile je dokončeno řízení provádění, vrátí se do volající funkce. Volající funkce pak pokračuje ve svém provádění. Volající funkce čeká, až vyvolaná funkce dokončí provádění, než bude pokračovat se zbytkem příkazů.

Ale v případě goroutine nebude volající funkce čekat na dokončení spuštěné funkce. Bude pokračovat v provádění s dalšími příkazy. V programu můžete mít více goroutin.

Také se hlavní program ukončí, jakmile dokončí provádění svých příkazů, a nebude čekat na dokončení vyvolaných goroutin.

Goroutine se vyvolá pomocí klíčového slova go následovaného voláním funkce.

Příklad

go add(x,y)

Golangům níže porozumíte golangovým příkladům. Spusťte níže uvedený 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")
	}
}

Výstup bude

In main
In main
In main
In main
In main

Zde hlavní program dokončil provádění ještě před zahájením goroutiny. Display() je rutina, která se vyvolává pomocí syntaxe

go function_name(parameter list)

Ve výše uvedeném kódu main() nečeká na dokončení display() a main() dokončilo své provedení dříve, než display() provedlo svůj kód. Takže příkaz k tisku uvnitř display() se nevytiskl.

Nyní upravíme program tak, aby tiskl i výpisy z display(). Přidáme časové zpoždění 2 sekundy ve smyčce for funkce main() a zpoždění 1 sekundy ve smyčce for 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")
	}
}

Výstup bude poněkud podobný

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

Zde můžete vidět, že se obě smyčky provádějí překrývajícím se způsobem kvůli souběžnému provádění.

Kanály

Kanály představují způsob, jak funkce vzájemně komunikovat. Lze jej považovat za médium, kam jedna rutina umísťuje data a je přístupná jinou rutinou na serveru Golang.

Kanál lze deklarovat pomocí syntaxe

channel_variable := make(chan datatype)

Příklad:

	ch := make(chan int)

Data můžete odesílat do kanálu pomocí syntaxe

channel_variable <- variable_name

Příklad

    ch <- x

Data z kanálu můžete přijímat pomocí syntaxe

    variable_name := <- channel_variable

Příklad

   y := <- ch

Ve výše uvedených příkladech goroutinu v jazyce Go jste viděli, že hlavní program na goroutinu nečeká. To však není případ, kdy se jedná o kanály. Předpokládejme, že pokud gorrutina posílá data do kanálu, main() počká na příkaz přijímající data kanálu, dokud data nezíská.

Uvidíte to v níže uvedených příkladech jazyka Go. Nejprve napište normální rutinu a podívejte se na chování. Poté upravte program tak, aby používal kanály a sledujte chování.

Spusťte níže uvedený 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()")
}

Výstup bude

Inside main()

Main() dokončilo provádění a skončilo dříve, než se spustí goroutine. Takže tisk uvnitř display() nebyl proveden.

Nyní upravte výše uvedený program tak, aby používal kanály a sledujte chování.

package main
import "fmt"
import "time"
    
func display(ch chan int) {
	time.Sleep(5 * time.Second)
	fmt.Println("Inside display()")
	ch <- 1234
}

func main() {
	ch := make(chan int) 
	go display(ch)
	x := <-ch
	fmt.Println("Inside main()")
	fmt.Println("Printing x in main() after taking from channel:",x)
}

Výstup bude

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

Zde se stane, že main() při dosažení x := <-ch bude čekat na data na kanálu ch. Display() čeká 5 sekund a poté odešle data do kanálu ch. Main() při příjmu dat z kanálu se odblokuje a pokračuje ve svém provádění.

Odesílatel, který posílá data do kanálu, může informovat příjemce, že do kanálu nebudou přidána žádná další data uzavřením kanálu. To se používá hlavně, když používáte smyčku k přenosu dat do kanálu. Kanál lze uzavřít pomocí

close(channel_name)

A na konci přijímače je možné zkontrolovat, zda je kanál uzavřen pomocí další proměnné při načítání dat z kanálu pomocí

variable_name, status := <- channel_variable

Pokud je stav True, znamená to, že jste přijali data z kanálu. Pokud je false, znamená to, že se pokoušíte číst z uzavřeného kanálu

Můžete také použít kanály pro komunikaci mezi goroutiny. Je třeba použít 2 goroutiny – jeden posílá data do kanálu a druhý přijímá data z kanálu. Viz níže uvedený 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()")
}

Zde jsou 2 podprogramy, jeden posílá data do kanálu a druhý tiskne data do kanálu. Funkce add_to_channel přidá čísla od 0 do 9 a zavře kanál. Současně funkce fetch_from_channel čeká na

x, příznak := <- ch a jakmile budou data dostupná, data vytiskne. Ukončí se, jakmile je příznak nepravdivý, což znamená, že kanál je uzavřen.

Čekání v main() je dáno, aby se zabránilo ukončení main(), dokud goroutiny nedokončí provádění.

Spusťte kód a podívejte se na výstup jako

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

vybrat

Select lze zobrazit jako příkaz switch, který funguje na kanálech. Zde budou případová prohlášení operací kanálu. Obvykle se každý případový příkaz pokusí přečíst z kanálu. Když je některý z případů připraven (kanál je přečten), provede se příkaz spojený s tímto případem. Pokud je připraveno více případů, vybere náhodný. Můžete mít výchozí případ, který se provede, pokud není připraven žádný z případů.

Podívejme se na níže uvedený kód

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

Spuštěním výše uvedeného programu získáte výstup:

from data2()

Zde příkaz select čeká, až budou data dostupná v některém z kanálů. Data2() přidá data do kanálu po 2 sekundách spánku, což způsobí provedení druhého případu.

Přidejte výchozí případ k výběru ve stejném programu a podívejte se na výstup. Zde, po dosažení vybraného bloku, pokud žádný případ nemá připravena data na kanálu, provede výchozí blok bez čekání, až budou data dostupná na jakémkoli kanálu.

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

Tento program poskytne výstup:

Default case executed			

Je to proto, že když byl dosažen blok výběru, žádný kanál neměl data pro čtení. Takže se provede výchozí případ.

Mutex

Mutex je zkratka pro vzájemné vyloučení. Mutex se používá, když nechcete povolit přístup k prostředku více podprogramům současně. Mutex má 2 způsoby – zamknout a odemknout. Mutex je obsažen v synchronizačním balíčku. Musíte tedy importovat synchronizační balíček. Příkazy, které musí být vzájemně výhradně provedeny, mohou být umístěny uvnitř mutex.Lock() a mutex.Unlock().

Pojďme se naučit mutex s příkladem, který počítá, kolikrát je smyčka vykonána. V tomto programu očekáváme, že rutina spustí smyčku 10krát a počet je uložen v součtu. Tuto rutinu voláte 3krát, takže celkový počet by měl být 30. Počet je uložen v globální proměnné count.

Nejprve spustíte program bez mutexu

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

Podívejte se na výsledek

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

Výsledek se může při spuštění lišit, ale konečný výsledek nebude 30.

Zde se stane, že se 3 goroutiny pokoušejí zvýšit počet smyček uložený v proměnné count. Předpokládejme, že v okamžiku je počet 5 a goroutine1 zvýší počet na 6. Mezi hlavní kroky patří

Kopírovat počet do temp

Zvýšení teploty

Uložte teplotu zpět k počítání

Předpokládejme, že brzy po provedení kroku 3 goroutine1; jiná goroutine může mít starou hodnotu, řekněme, že 3 provede výše uvedené kroky a uloží 4 zpět, což je špatně. Tomu lze zabránit použitím mutexu, který způsobí, že ostatní rutiny čekají, když jedna rutina již proměnnou používá.

Nyní spustíte program s mutexem. Zde jsou výše uvedené 3 kroky provedeny v mutexu.

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

Nyní bude výstup

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

Zde dostáváme očekávaný výsledek jako konečný výstup. Protože čtení příkazů, inkrementace a zpětný zápis počtu se provádí v mutexu.

Chyba při zpracování

Chyby jsou abnormální stavy, jako je zavření souboru, který není otevřen, otevření souboru, který neexistuje atd. Funkce obvykle vrací chyby jako poslední návratovou hodnotu.

Níže uvedený příklad vysvětluje více o chybě.

package main
import "fmt"
import "os"

//function accepts a filename and tries to open it.
func fileopen(name string) {
    f, er := os.Open(name)

    //er will be nil if the file exists else it returns an error object  
    if er != nil {
        fmt.Println(er)
        return
    }else{
    	fmt.Println("file opened", f.Name())
    }
}

func main() {  
    fileopen("invalid.txt")
}

Výstup bude:

open /invalid.txt: no such file or directory

Zde jsme se pokusili otevřít neexistující soubor a vrátilo to chybu do proměnné er. Pokud je soubor platný, bude chyba nulová

Vlastní chyby

Pomocí této funkce můžete vytvářet vlastní chyby. To se provádí pomocí New() chybového balíčku. Výše uvedený program přepíšeme, abychom využili vlastní chyby.

Spusťte níže uvedený 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)
    }  
}

Výstup bude:

Custom error message:File name is wrong

Zde area() vrací plochu čtverce. Pokud je vstup menší než 1, pak area() vrátí chybovou zprávu.

Čtení souborů

Soubory slouží k ukládání dat. Go nám umožňuje číst data ze souborů

Nejprve vytvořte soubor, data.txt, ve vašem aktuálním adresáři s níže uvedeným obsahem.

Line one
Line two
Line three

Nyní spusťte níže uvedený program, abyste viděli, že vytiskne obsah celého souboru jako výstup

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

Zde data, err := ioutil.ReadFile(“data.txt”) načte data a vrátí sekvenci bajtů. Při tisku je převeden do formátu řetězce.

Psaní souborů

Uvidíte to pomocí programu

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

Zde se vytvoří soubor test.txt. Pokud soubor již existuje, bude obsah souboru zkrácen. Writeline() se používá k zápisu obsahu do souboru. Poté jste soubor zavřeli pomocí Close().

Cheat Sheet

V tomto tutoriálu Go jsme probrali

Téma Description Syntax
Základní typy Numerický, řetězec, bool
Proměnné Deklarujte a přiřazujte hodnoty proměnným var typ název_proměnné
var název_proměnné typ = hodnota
var název_proměnné1, název_proměnné2 = hodnota1, hodnota2
název_proměnné := hodnota
Konstanty Proměnné, jejichž hodnotu nelze po přiřazení změnit konst proměnná = hodnota
Pro smyčku Provádějte příkazy ve smyčce. pro inicializační_výraz; hodnocení_výraz; iterační_výraz{
// jeden nebo více příkazů
}
Pokud jinak Je to podmíněné prohlášení if podmínka{
// statement_1
Else {}
// statement_2
}
přepnout Podmíněné prohlášení s více případy přepnout výraz {
case value_1:
prohlášení_1
case value_2:
prohlášení_2
case value_n:
prohlášení_n
default:
statement_default
}
Řada Pevná velikost pojmenované sekvence prvků stejného typu arrayname := [velikost] typ {value_0,value_1,…,value_size-1}
Plátek Část nebo segment pole var název_části [] typ = název_pole[start:konec]
Funkce Blok příkazů, který provádí konkrétní úkol func název_funkce (typ parametru_1, typ parametru_n) return_type {
//výroky
}
Balíčky Používají se k uspořádání kódu. Zvyšuje čitelnost kódu a jeho opětovné použití importovat název_balíčku
Odložit Odloží provádění funkce, dokud funkce, která obsahuje, nedokončí provádění odložit název_funkce (seznam_parametrů)
Pointers Ukládá paměťovou adresu jiné proměnné. var název_proměnné *typ
Struktura Uživatelsky definovaný datový typ, který sám obsahuje ještě jeden prvek stejného nebo jiného typu zadejte název struktury struct {
proměnná_1 typ_proměnné_1
proměnná_2 typ_proměnné_2
variable_n variable_n_type
}
Metody Metoda je funkce s argumentem příjemce func (variable variabletype) methodName(seznam_parametrů) {
}
Gorutine Funkce, která může běžet současně s jinými funkcemi. go function_name (seznam_parametrů)
Kanál Způsob, jakým spolu funkce komunikují. Médium, na které jedna rutina umísťuje data a k níž přistupuje jiná rutina. Prohlásit:
ch := make(chan int)
Odeslat data do kanálu:
kanálová_proměnná <- název_proměnné
Příjem z kanálu:
název_proměnné := <- proměnná_kanálu
vybrat Příkaz Switch, který funguje na kanálech. Případová prohlášení budou kanálovou operací. Když je některý z kanálů připraven s daty, provede se příkaz spojený s tímto případem vybrat {
případ x := <-kan1:
fmt.Println(x)
případ y := <-kan2:
fmt.Println(y)
}
Mutex Mutex se používá, když nechcete povolit přístup k prostředku více podprogramům současně. Mutex má 2 způsoby – zamknout a odemknout mutex.Lock()
//výroky
mutex.Unlock().
Čtení souborů Přečte data a vrátí sekvenci bajtů. Data, err := ioutil.ReadFile(název souboru)
Zapsat soubor Zapisuje data do souboru l, err := f.WriteString(text_k_zápisu)

Shrňte tento příspěvek takto: