Tutorial de Golang
O que รฉ ir?
Go (tambรฉm conhecido como Golang) รฉ uma linguagem de programaรงรฃo de cรณdigo aberto desenvolvida pelo Google. ร uma linguagem compilada de tipo estatรญstico. Go suporta programaรงรฃo simultรขnea, ou seja, permite executar vรกrios processos simultaneamente. Isso รฉ conseguido usando canais, goroutines, etc. Go Language possui coleta de lixo que por si sรณ faz o gerenciamento de memรณria e permite a execuรงรฃo diferida de funรงรตes.
Aprenderemos todos os fundamentos do Golang neste tutorial de idiomas do Learn Go.
Como baixar e instalar o GO
Passo 1) Acesse https://golang.org/dl/. Baixe o binรกrio para o seu sistema operacional.
Passo 2) Double clique no instalador e clique em Executar.
Passo 3) Clique em Avanรงar

Passo 4) Selecione a pasta de instalaรงรฃo e clique em Avanรงar.

Passo 5) Clique em Concluir quando a instalaรงรฃo estiver concluรญda.

Passo 6) Assim que a instalaรงรฃo for concluรญda, vocรช pode verificรก-la abrindo o terminal e digitando
go version
Isso exibirรก a versรฃo do go instalada

Seu programa First Go โ Go Hello World!
Crie uma pasta chamada studyGo. Neste tutorial da linguagem Go, criaremos nossos programas go dentro desta pasta. Os arquivos Go sรฃo criados com a extensรฃo .ir. Vocรช pode executar programas Go usando a sintaxe
go run <filename>
Crie um arquivo chamado first.go e adicione o cรณdigo abaixo nele e salve
package main
import ("fmt")
func main() {
fmt.Println("Hello World! This is my first Go program\n")
}

Navegue atรฉ esta pasta em seu terminal. Execute o programa usando o comando
vรก correr primeiro. vรก
Vocรช pode ver a impressรฃo de saรญda
Hello World! This is my first Go program

Agora vamos discutir o programa acima.
package main โ Todo programa Go Language deve comeรงar com um nome de pacote. Go nos permite usar pacotes em outros programas go e, portanto, oferece suporte ร reutilizaรงรฃo de cรณdigo. A execuรงรฃo de um programa Go comeรงa com o cรณdigo dentro do pacote denominado main.
importar fmt โ importa o pacote fmt. Este pacote implementa as funรงรตes de E/S.
func main() โ Esta รฉ a funรงรฃo a partir da qual comeรงa a execuรงรฃo do programa. A funรงรฃo principal deve sempre ser colocada no pacote principal. Sob main(), vocรช pode escrever o cรณdigo dentro de {}.
fmt.Println โ Imprimirรก o texto na tela pela funรงรฃo Println do fmt.
Nota: Nas seรงรตes abaixo deste tutorial Go, quando vocรช menciona executar/executar o cรณdigo, significa salvar o cรณdigo em um arquivo com extensรฃo .go e executรก-lo usando a sintaxe
go run <filename>
Tipos de dados
Tipos (tipos de dados) representam o tipo do valor armazenado em uma variรกvel, o tipo do valor que uma funรงรฃo retorna, etc.
Existem trรชs tipos bรกsicos em Go Language
Tipos numรฉricos โ Representa valores numรฉricos que incluem nรบmeros inteiros, ponto flutuante e valores complexos. Vรกrios tipos numรฉricos sรฃo:
int8 โ inteiros com sinal de 8 bits.
int16 โ inteiros com sinal de 16 bits.
int32 โ inteiros com sinal de 32 bits.
int64 โ inteiros com sinal de 64 bits.
uint8 โ inteiros sem sinal de 8 bits.
uint16 โ inteiros sem sinal de 16 bits.
uint32 โ inteiros sem sinal de 32 bits.
uint64 โ inteiros sem sinal de 64 bits.
float32 โ nรบmeros de ponto flutuante de 32 bits.
float64 โ nรบmeros de ponto flutuante de 64 bits.
complex64 โ possui float32 partes reais e imaginรกrias.
complex128 โ possui float32 partes reais e imaginรกrias.
Tipos de string โ Representa uma sequรชncia de bytes (caracteres). Vocรช pode realizar vรกrias operaรงรตes em strings, como concatenaรงรฃo de strings, extraรงรฃo de substring, etc.
tipos booleanos โ Representa 2 valores, verdadeiro ou falso.
Interface Golang
Interface Golang รฉ uma coleรงรฃo de assinaturas de mรฉtodos usadas por um Type para implementar o comportamento de objetos. O principal objetivo da interface Golang รฉ fornecer assinaturas de mรฉtodos com nomes, argumentos e tipos de retorno. Cabe a um Type declarar e implementar o mรฉtodo. Uma interface em Golang pode ser declarada usando a palavra-chave โinterfaceโ.
Variรกveis
Variรกveis โโapontam para um local de memรณria que armazena algum tipo de valor. O parรขmetro type (na sintaxe abaixo) representa o tipo de valor que pode ser armazenado no local da memรณria.
A variรกvel pode ser declarada usando a sintaxe
var <variable_name> <type>
Depois de declarar uma variรกvel de um tipo, vocรช pode atribuir a variรกvel a qualquer valor desse tipo.
Vocรช tambรฉm pode atribuir um valor inicial a uma variรกvel durante a prรณpria declaraรงรฃo usando
var <variable_name> <type> = <value>
Se vocรช declarar a variรกvel com um valor inicial, vรก e infira o tipo da variรกvel a partir do tipo de valor atribuรญdo. Entรฃo vocรช pode omitir o tipo durante a declaraรงรฃo usando a sintaxe
var <variable_name> = <value>
Alรฉm disso, vocรช pode declarar mรบltiplas variรกveis โโcom a sintaxe
var <variable_name1>, <variable_name2> = <value1>, <value2>
O programa abaixo neste tutorial Go tem alguns exemplos Golang de declaraรงรตes de variรกveis
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)
}
A saรญda serรก
x: 3 y: 20 z: 50 i and j: 100 hello
Go Language tambรฉm fornece uma maneira fรกcil de declarar variรกveis โโcom valor, omitindo a palavra-chave var usando
<variable_name> := <value>
Observe que vocรช usou := em vez de =. Vocรช nรฃo pode usar := apenas para atribuir um valor a uma variรกvel que jรก estรก declarada. := รฉ usado para declarar e atribuir valor.
Crie um arquivo chamado assign.go com o seguinte cรณdigo
package main
import ("fmt")
func main() {
a := 20
fmt.Println(a)
//gives error since a is already declared
a := 30
fmt.Println(a)
}
Execute go run assign.go para ver o resultado como
./assign.go:7:4: no new variables on left side of :=
Variรกveis โโdeclaradas sem valor inicial terรฃo 0 para tipos numรฉricos, false para Boolean e string vazia para strings
Constante
Variรกveis โโconstantes sรฃo aquelas variรกveis โโcujo valor nรฃo pode ser alterado depois de atribuรญdo. Uma constante na linguagem de programaรงรฃo Go รฉ declarada usando a palavra-chave โconstโ
Crie um arquivo chamado constante.go e com o seguinte cรณdigo
package main
import ("fmt")
func main() {
const b =10
fmt.Println(b)
b = 30
fmt.Println(b)
}
Execute go run constante.go para ver o resultado como
.constant.go:7:4: cannot assign to b
Exemplos de loop para
Loops sรฃo usados โโpara executar um bloco de instruรงรตes repetidamente com base em uma condiรงรฃo. A maioria das linguagens de programaรงรฃo fornece 3 tipos de loops โ for, while, do while. Mas a linguagem de programaรงรฃo Go oferece suporte apenas para loop.
A sintaxe de um loop for Golang รฉ
for initialisation_expression; evaluation_expression; iteration_expression{
// one or more statement
}
A expressรฃo_de_inicializaรงรฃo รฉ executada primeiro (e apenas uma vez) no loop for Golang.
Entรฃo a expressรฃo_avaliaรงรฃo รฉ avaliada e se for verdadeira o cรณdigo dentro do bloco รฉ executado.
O ID iteration_expression รฉ executado e a avaliaรงรฃo_expression รฉ avaliada novamente. Se for verdade, o bloco de instruรงรตes serรก executado novamente. Isso continuarรก atรฉ que a expressรฃo_avaliaรงรฃo se torne falsa.
Copie o programa abaixo em um arquivo e execute-o para ver o Golang para imprimir nรบmeros de loop de 1 a 5
package main
import "fmt"
func main() {
var i int
for i = 1; i <= 5; i++ {
fmt.Println(i)
}
}
A saรญda รฉ
1 2 3 4 5
Se mais
If else รฉ uma declaraรงรฃo condicional. A sinax รฉ
if condition{
// statements_1
}else{
// statements_2
}
Aqui a condiรงรฃo รฉ avaliada e se for verdadeira, as instruรงรตes_1 serรฃo executadas, caso contrรกrio, as instruรงรตes_2 serรฃo executadas.
Vocรช tambรฉm pode usar a instruรงรฃo if sem else. Vocรช tambรฉm pode ter instruรงรตes if else encadeadas. Os programas abaixo explicarรฃo mais sobre o caso.
Execute o programa abaixo. Ele verifica se um nรบmero, x, รฉ menor que 10. Nesse caso, imprimirรก โx รฉ menor que 10โ
package main
import "fmt"
func main() {
var x = 50
if x < 10 {
//Executes if x < 10
fmt.Println("x is less than 10")
}
}
Aqui, como o valor de x รฉ maior que 10, a instruรงรฃo dentro da condiรงรฃo do bloco if nรฃo serรก executada.
Agora veja o programa abaixo. Neste tutorial da linguagem de programaรงรฃo Go, temos um bloco else que serรก executado em caso de falha na avaliaรงรฃo 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")
}
}
Este programa lhe darรก uma saรญda
x is greater than or equals 10
Agora neste tutorial Go, veremos um programa com vรกrios blocos if else (encadeados if else). Execute o exemplo Go abaixo. Ele verifica se um nรบmero รฉ menor que 10, entre 10 e 90 ou maior que 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")
}
}
Aqui, primeiro, a condiรงรฃo if verifica se x รฉ menor que 10 e nรฃo รฉ. Portanto, ele verifica a prรณxima condiรงรฃo (caso contrรกrio, se) se estรก entre 10 e 90, o que tambรฉm รฉ falso. Entรฃo ele executa o bloco na seรงรฃo else que fornece a saรญda
x is greater than 90
Interruptor
Switch รฉ outra declaraรงรฃo condicional. As instruรงรตes switch avaliam uma expressรฃo e o resultado รฉ comparado com um conjunto de valores disponรญveis (casos). Depois que uma correspondรชncia รฉ encontrada, as instruรงรตes associadas a essa correspondรชncia (caso) sรฃo executadas. Se nenhuma correspondรชncia for encontrada, nada serรก executado. Vocรช tambรฉm pode adicionar um case padrรฃo ao switch que serรก executado se nenhuma outra correspondรชncia for encontrada. A sintaxe da opรงรฃo รฉ
switch expression {
case value_1:
statements_1
case value_2:
statements_2
case value_n:
statements_n
default:
statements_default
}
Aqui o valor da expressรฃo รฉ comparado com os valores de cada caso. Assim que uma correspondรชncia for encontrada, as instruรงรตes associadas a esse caso serรฃo executadas. Se nenhuma correspondรชncia for encontrada, as instruรงรตes da seรงรฃo padrรฃo serรฃo executadas.
Execute o programa abaixo
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")
}
}
Vocรช obterรก a saรญda como
Sum is 3
Altere o valor de a e b para 3 e o resultado serรก
Printing default
Vocรช tambรฉm pode ter vรกrios valores em um caso, separando-os por vรญrgula.
Arrays
Array representa um tamanho fixo, denominado sequรชncia de elementos do mesmo tipo. Vocรช nรฃo pode ter um array que contenha nรบmeros inteiros e caracteres. Vocรช nรฃo pode alterar o tamanho de uma matriz depois de definir o tamanho.
A sintaxe para declarar um array รฉ
var arrayname [size] type
Cada elemento da matriz pode receber um valor usando a sintaxe
arrayname [index] = value
O รญndice da matriz comeรงa em 0 a tamanho-1.
Vocรช pode atribuir valores aos elementos do array durante a declaraรงรฃo usando a sintaxe
arrayname := [size] type {value_0,value_1,โฆ,value_size-1}
Vocรช tambรฉm pode ignorar o parรขmetro size ao declarar o array com valores, substituindo size por ... e o compilador encontrarรก o comprimento a partir do nรบmero de valores. Sintaxe รฉ
arrayname := [โฆ] type {value_0,value_1,โฆ,value_size-1}
Vocรช pode encontrar o comprimento do array usando a sintaxe
len(arrayname)
Execute o exemplo Go abaixo para entender o array
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])
}
saรญda
Two 3 [One Two Three] [1 2 3 4 5] 5
Funรงรฃo Golang Slice e Append
Uma fatia รฉ uma parte ou segmento de uma matriz. Ou รฉ uma visรฃo ou visรฃo parcial de uma matriz subjacente para a qual aponta. Vocรช pode acessar os elementos de uma fatia usando o nome da fatia e o nรบmero do รญndice, assim como faz em uma matriz. Vocรช nรฃo pode alterar o comprimento de uma matriz, mas pode alterar o tamanho de uma fatia.
O conteรบdo de uma fatia sรฃo, na verdade, ponteiros para os elementos de uma matriz. Isso significa se vocรช alterar qualquer elemento em uma fatia, o conteรบdo subjacente do array tambรฉm serรก afetado.
A sintaxe para criar uma fatia รฉ
var slice_name [] type = array_name[start:end]
Isso criarรก uma fatia chamada slice_name a partir de uma matriz chamada array_name com os elementos no รญndice do inรญcio ao fim-1.
Agora neste tutorial Golang, executaremos o programa abaixo. O programa criarรก uma fatia do array e a imprimirรก. Alรฉm disso, vocรช pode ver que modificar o conteรบdo da fatia modificarรก a matriz real.
package main
import "fmt"
func main() {
// declaring array
a := [5] string {"one", "two", "three", "four", "five"}
fmt.Println("Array after creation:",a)
var b [] string = a[1:4] //created a slice named b
fmt.Println("Slice after creation:",b)
b[0]="changed" // changed the slice data
fmt.Println("Slice after modifying:",b)
fmt.Println("Array after slice modification:",a)
}
Isso imprimirรก o resultado como
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]
Existem certas funรงรตes como Golang len, Golang anexar que vocรช pode aplicar em fatias
len(nome_da_fatia) โ retorna o comprimento da fatia
anexar (nome_da fatia, valor_1, valor_2) โ O acrรฉscimo Golang รฉ usado para anexar valor_1 e valor_2 a uma fatia existente.
acrescentar(fatia_nale1,slice_name2โฆ) โ anexa slice_name2 a slice_name1
Execute o seguinte programa.
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)
}
A saรญda serรก
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]
O programa primeiro cria 2 fatias e imprime seu comprimento. Em seguida, ele anexou uma fatia ร outra e anexou uma string ร fatia resultante.
Funรงรตes
Uma funรงรฃo representa um bloco de instruรงรตes que executa uma tarefa especรญfica. Uma declaraรงรฃo de funรงรฃo nos informa o nome da funรงรฃo, tipo de retorno e parรขmetros de entrada. A definiรงรฃo da funรงรฃo representa o cรณdigo contido na funรงรฃo. A sintaxe para declarar a funรงรฃo รฉ
func function_name(parameter_1 type, parameter_n type) return_type {
//statements
}
Os parรขmetros e tipos de retorno sรฃo opcionais. Alรฉm disso, vocรช pode retornar vรกrios valores de uma funรงรฃo.
Agora, neste tutorial do Golang, vamos executar o seguinte exemplo do Golang. Aqui a funรงรฃo chamada calc aceitarรก 2 nรบmeros e realizarรก a adiรงรฃo e subtraรงรฃo e retornarรก ambos os valores.
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)
}
A saรญda serรก
Sum 25 Diff 5
PACOTES
Pacotes sรฃo usados โโpara organizar o cรณdigo. Em um projeto grande, nรฃo รฉ viรกvel escrever cรณdigo em um รบnico arquivo. A linguagem de programaรงรฃo Go nos permite organizar o cรณdigo em diferentes pacotes. Isso aumenta a legibilidade e a reutilizaรงรฃo do cรณdigo. Um programa Go executรกvel deve conter um pacote denominado main e a execuรงรฃo do programa comeรงa a partir da funรงรฃo denominada main. Vocรช pode importar outros pacotes em nosso programa usando a sintaxe
import package_name
Veremos e discutiremos neste tutorial Golang como criar e usar pacotes no seguinte exemplo Golang.
Passo 1) Crie um arquivo chamado package_example.go e adicione o cรณdigo abaixo
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)
}
No programa acima, fmt รฉ um pacote que a linguagem de programaรงรฃo Go nos fornece principalmente para fins de E/S. Alรฉm disso, vocรช pode ver um pacote chamado cรกlculo. Dentro de main() vocรช pode ver uma soma de passos:=cรกlculo.Do_add(x,y). Isso significa que vocรช estรก invocando a funรงรฃo Do_add do cรกlculo do pacote.
Passo 2) Primeiro, vocรช deve criar o cรกlculo do pacote dentro de uma pasta com o mesmo nome na pasta src do go. O caminho instalado do go pode ser encontrado na variรกvel PATH.
Para mac, encontre o caminho executando echo $PATH

Entรฃo o caminho รฉ /usr/local/go
Para Windows, encontre o caminho executando echo %GOROOT%

Aqui o caminho รฉ C:\Go\
Passo 3) Navegue atรฉ a pasta src (/usr/local/go/src para mac e C:\Go\src para windows). Agora, a partir do cรณdigo, o nome do pacote รฉ cรกlculo. Go requer que o pacote seja colocado em um diretรณrio com o mesmo nome no diretรณrio src. Crie um diretรณrio chamado cรกlculo na pasta src.
Passo 4) Crie um arquivo chamado calc.go (vocรช pode dar qualquer nome, mas o nome do pacote no cรณdigo รฉ importante. Aqui deve ser cรกlculo) dentro do diretรณrio de cรกlculo e adicione o cรณdigo abaixo
package calculation
func Do_add(num1 int, num2 int)(int) {
sum := num1 + num2
return sum
}
Passo 5) Execute o comando go install do diretรณrio de cรกlculo que irรก compilar o calc.go.

Passo 6) Agora volte para package_example.go e execute package_example.go. A saรญda serรก Soma 25.
Observe que o nome da funรงรฃo Do_add comeรงa com letra maiรบscula. Isso ocorre porque em Go, se o nome da funรงรฃo comeรงar com uma letra maiรบscula, significa que outros programas podem vรช-lo (acessรก-lo), caso contrรกrio, outros programas nรฃo poderรฃo acessรก-lo. Se o nome da funรงรฃo fosse do_add , vocรช teria recebido o erro
nรฃo รฉ possรญvel referir-se ao nome nรฃo exportado calculator.calc..
Adiar e empilhar adiamentos
As instruรงรตes defer sรฃo usadas para adiar a execuรงรฃo de uma chamada de funรงรฃo atรฉ que a funรงรฃo que contรฉm a instruรงรฃo defer conclua a execuรงรฃo.
Vamos aprender isso com um exemplo:
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()")
}
A saรญda serรก
Inside the main() Inside the sample()
Aqui a execuรงรฃo de sample() รฉ adiada atรฉ que a execuรงรฃo da funรงรฃo envolvente (main()) seja concluรญda.
O empilhamento defer usa vรกrias instruรงรตes defer. Suponha que vocรช tenha vรกrias instruรงรตes defer dentro de uma funรงรฃo. Go coloca todas as chamadas de funรงรฃo adiadas em uma pilha e, quando a funรงรฃo envolvente retorna, as funรงรตes empilhadas sรฃo executadas no Ordem Last In First Out (LIFO). Vocรช pode ver isso no exemplo abaixo.
Execute o cรณdigo abaixo
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)
}
A saรญda serรก
4 3 2 1
Aqui, o cรณdigo dentro de main() รฉ executado primeiro e, em seguida, as chamadas de funรงรฃo adiadas sรฃo executadas na ordem inversa, ou seja, 4, 3,2,1.
Ponteiros
Antes de explicar as dicas, vamos primeiro discutir o operador '&'. O operador '&' รฉ usado para obter o endereรงo de uma variรกvel. Significa que '&a' imprimirรก o endereรงo de memรณria da variรกvel a.
Neste tutorial Golang, executaremos o programa abaixo para exibir o valor de uma variรกvel e o endereรงo dessa variรกvel
package main
import "fmt"
func main() {
a := 20
fmt.Println("Address:",&a)
fmt.Println("Value:",a)
}
O resultado serรก
Address: 0xc000078008 Value: 20
Uma variรกvel de ponteiro armazena o endereรงo de memรณria de outra variรกvel. Vocรช pode definir um ponteiro usando a sintaxe
var variable_name *type
O asterisco (*) representa que a variรกvel รฉ um ponteiro. Vocรช entenderรก mais executando o programa abaixo
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)}
A saรญda serรก
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
Estruturas
Uma estrutura รฉ um tipo de dados definido pelo usuรกrio que contรฉm mais um elemento do mesmo tipo ou de tipo diferente.
Usar uma estrutura รฉ um processo de duas etapas.
Primeiro, crie(declare) um tipo de estrutura
Segundo, crie variรกveis โโdesse tipo para armazenar valores.
As estruturas sรฃo usadas principalmente quando vocรช deseja armazenar dados relacionados juntos.
Considere uma informaรงรฃo do funcionรกrio que contรฉm nome, idade e endereรงo. Vocรช pode lidar com isso de duas maneiras
Crie 3 arrays โ um array armazena os nomes dos funcionรกrios, um armazena a idade e o terceiro armazena a idade.
Declare um tipo de estrutura com 3 campos: nome, endereรงo e idade. Crie uma matriz desse tipo de estrutura onde cada elemento รฉ um objeto de estrutura com nome, endereรงo e idade.
A primeira abordagem nรฃo รฉ eficiente. Nesses tipos de cenรกrios, as estruturas sรฃo mais convenientes.
A sintaxe para declarar uma estrutura รฉ
type structname struct {
variable_1 variable_1_type
variable_2 variable_2_type
variable_n variable_n_type
}
Um exemplo de declaraรงรฃo de estrutura รฉ
type emp struct {
name string
address string
age int
}
Aqui um novo tipo definido pelo usuรกrio denominado emp รฉ criado. Agora vocรช pode criar variรกveis โโdo tipo emp usando a sintaxe
var variable_name struct_name
Um exemplo รฉ
var empdata1 emp
Vocรช pode definir valores para empdata1 como
empdata1.name = "John" empdata1.address = "Street-1, Bangalore" empdata1.age = 30
Vocรช tambรฉm pode criar uma variรกvel de estrutura e atribuir valores por
empdata2 := emp{"Raj", "Building-1, Delhi", 25}
Aqui, vocรช precisa manter a ordem dos elementos. Raj serรก mapeado para o nome, o prรณximo elemento a ser endereรงado e o รบltimo a envelhecer.
Execute o cรณdigo abaixo
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)
}
saรญda
John Raj
Mรฉtodos (nรฃo funรงรตes)
Um mรฉtodo รฉ uma funรงรฃo com um argumento receptor. Archiestruturalmente, estรก entre a palavra-chave func e o nome do mรฉtodo. A sintaxe de um mรฉtodo รฉ
func (variable variabletype) methodName(parameter1 paramether1type) {
}
Vamos converter o programa de exemplo acima para usar mรฉtodos em vez de funรงรตes.
package main
import "fmt"
//declared the structure named emp
type emp struct {
name string
address string
age int
}
//Declaring a function with receiver of the type emp
func(e emp) display() {
fmt.Println(e.name)
}
func main() {
//declaring a variable of type emp
var empdata1 emp
//Assign values to members
empdata1.name = "John"
empdata1.address = "Street-1, Lodon"
empdata1.age = 30
//declaring a variable of type emp and assign values to members
empdata2 := emp {
"Raj", "Building-1, Paris", 25}
//Invoking the method using the receiver of the type emp
// syntax is variable.methodname()
empdata1.display()
empdata2.display()
}
Go nรฃo รฉ uma linguagem orientada a objetos e nรฃo possui o conceito de classe. Os mรฉtodos dรฃo uma ideia do que vocรช faz em programas orientados a objetos, onde as funรงรตes de uma classe sรฃo invocadas usando a sintaxe objectname.functionname()
Concorrรชncia
Go oferece suporte ร execuรงรฃo simultรขnea de tarefas. Isso significa que Go pode executar vรกrias tarefas simultaneamente. ร diferente do conceito de paralelismo. No paralelismo, uma tarefa รฉ dividida em pequenas subtarefas e executadas em paralelo. Mas em simultaneidade, vรกrias tarefas sรฃo executadas simultaneamente. A simultaneidade รฉ alcanรงada em Go usando Goroutines e Canais.
Goroutines
Uma goroutine รฉ uma funรงรฃo que pode ser executada simultaneamente com outras funรงรตes. Normalmente, quando uma funรงรฃo รฉ invocada, o controle รฉ transferido para a funรงรฃo chamada e, uma vez concluรญda a execuรงรฃo, o controle retorna para a funรงรฃo chamadora. A funรงรฃo de chamada continua sua execuรงรฃo. A funรงรฃo chamadora espera que a funรงรฃo invocada conclua a execuรงรฃo antes de prosseguir com o restante das instruรงรตes.
Mas no caso de goroutine, a funรงรฃo chamadora nรฃo aguardarรก a conclusรฃo da execuรงรฃo da funรงรฃo invocada. Ele continuarรก a ser executado com as prรณximas instruรงรตes. Vocรช pode ter vรกrios goroutines em um programa.
Alรฉm disso, o programa principal serรก encerrado assim que concluir a execuรงรฃo de suas instruรงรตes e nรฃo aguardarรก a conclusรฃo das goroutines invocadas.
Goroutine รฉ invocada usando a palavra-chave go seguida por uma chamada de funรงรฃo.
Exemplo
go add(x,y)
Vocรช entenderรก goroutines com os exemplos de Golang abaixo. Execute o programa abaixo
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")
}
}
A saรญda serรก
In main In main In main In main In main
Aqui, o programa principal concluiu a execuรงรฃo antes mesmo do inรญcio da goroutine. O display() รฉ uma goroutine que รฉ invocada usando a sintaxe
go function_name(parameter list)
No cรณdigo acima, main() nรฃo espera a conclusรฃo de display() e main() concluiu sua execuรงรฃo antes de display() executar seu cรณdigo. Portanto, a instruรงรฃo print dentro de display() nรฃo foi impressa.
Agora modificamos o programa para imprimir as instruรงรตes de display() tambรฉm. Adicionamos um atraso de 2 segundos no loop for de main() e um atraso de 1 segundo no loop for de display().
package main
import "fmt"
import "time"
func display() {
for i:=0; i<5; i++ {
time.Sleep(1 * time.Second)
fmt.Println("In display")
}
}
func main() {
//invoking the goroutine display()
go display()
for i:=0; i<5; i++ {
time.Sleep(2 * time.Second)
fmt.Println("In main")
}
}
A saรญda serรก um pouco semelhante a
In display In main In display In display In main In display In display In main In main In main
Aqui vocรช pode ver que ambos os loops estรฃo sendo executados de forma sobreposta devido ร execuรงรฃo simultรขnea.
Canais
Os canais sรฃo uma forma de as funรงรตes se comunicarem entre si. Pode ser pensado como um meio onde uma rotina coloca os dados e รฉ acessada por outra rotina no servidor Golang.
Um canal pode ser declarado com a sintaxe
channel_variable := make(chan datatype)
Exemplo:
ch := make(chan int)
Vocรช pode enviar dados para um canal usando a sintaxe
channel_variable <- variable_name
Exemplo
ch <- x
Vocรช pode receber dados de um canal usando a sintaxe
variable_name := <- channel_variable
Exemplo
y := <- ch
Nos exemplos de goroutine da linguagem Go acima, vocรช viu que o programa principal nรฃo espera pela goroutine. Mas esse nรฃo รฉ o caso quando hรก canais envolvidos. Suponha que se uma goroutine envia dados para o canal, o main() aguardarรก a instruรงรฃo que recebe os dados do canal atรฉ obter os dados.
Vocรช verรก isso nos exemplos de linguagem Go abaixo. Primeiro, escreva uma goroutine normal e veja o comportamento. Em seguida, modifique o programa para usar canais e veja o comportamento.
Execute o programa abaixo
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()")
}
A saรญda serรก
Inside main()
O main() finalizou a execuรงรฃo e saiu antes da execuรงรฃo da goroutine. Portanto, a impressรฃo dentro de display() nรฃo foi executada.
Agora modifique o programa acima para usar canais e veja o comportamento.
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)
}
A saรญda serรก
Inside display() Inside main() Printing x in main() after taking from channel: 1234
Aqui o que acontece รฉ que main() ao atingir x := <-ch irรก aguardar os dados no canal ch. O display() espera 5 segundos e depois envia os dados para o canal ch. O main() ao receber os dados do canal รฉ desbloqueado e continua sua execuรงรฃo.
O remetente que envia os dados para o canal pode informar aos destinatรกrios que nenhum outro dado serรก adicionado ao canal fechando o canal. Isso รฉ usado principalmente quando vocรช usa um loop para enviar dados para um canal. Um canal pode ser fechado usando
close(channel_name)
E no final do receptor, รฉ possรญvel verificar se o canal estรก fechado usando uma variรกvel adicional enquanto busca dados do canal usando
variable_name, status := <- channel_variable
Se o status for True significa que vocรช recebeu dados do canal. Se for falso, significa que vocรช estรก tentando ler de um canal fechado
Vocรช tambรฉm pode usar canais para comunicaรงรฃo entre goroutines. ร necessรกrio usar 2 goroutines โ uma envia os dados para o canal e a outra recebe os dados do canal. Veja o programa abaixo
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()")
}
Aqui existem 2 sub-rotinas, uma envia dados para o canal e a outra imprime dados para o canal. A funรงรฃo add_to_channel soma os nรบmeros de 0 a 9 e fecha o canal. Simultaneamente, a funรงรฃo fetch_from_channel espera em
x, flag := <- ch e assim que os dados estiverem disponรญveis, ele os imprime. Ele sai quando o sinalizador รฉ falso, o que significa que o canal estรก fechado.
A espera em main() รฉ dada para evitar a saรญda de main() atรฉ que as goroutines terminem a execuรงรฃo.
Execute o cรณdigo e veja a saรญda como
Read data Send data 0 1 2 3 4 5 6 7 8 9 Empty channel Inside main()
Selecionar
Select pode ser visto como uma instruรงรฃo switch que funciona em canais. Aqui as declaraรงรตes case serรฃo uma operaรงรฃo de canal. Normalmente, cada declaraรงรฃo de caso serรก uma tentativa de leitura do canal. Quando qualquer um dos casos estiver pronto (o canal for lido), a instruรงรฃo associada a esse caso serรก executada. Se vรกrios casos estiverem prontos, ele escolherรก um aleatรณrio. Vocรช pode ter um caso padrรฃo que serรก executado se nenhum dos casos estiver pronto.
Vamos ver o cรณdigo abaixo
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)
}
}
A execuรงรฃo do programa acima fornecerรก a saรญda:
from data2()
Aqui, a instruรงรฃo select aguarda que os dados estejam disponรญveis em qualquer um dos canais. O data2() adiciona dados ao canal apรณs um sono de 2 segundos, o que farรก com que o segundo caso seja executado.
Adicione um caso padrรฃo ao select no mesmo programa e veja a saรญda. Aqui, ao chegar ao bloco select, se nenhum caso estiver com dados prontos no canal, ele executarรก o bloco padrรฃo sem esperar que os dados estejam disponรญveis em algum canal.
package main
import "fmt"
import "time"
//push data to channel with a 4 second delay
func data1(ch chan string) {
time.Sleep(4 * time.Second)
ch <- "from data1()"
}
//push data to channel with a 2 second delay
func data2(ch chan string) {
time.Sleep(2 * time.Second)
ch <- "from data2()"
}
func main() {
//creating channel variables for transporting string values
chan1 := make(chan string)
chan2 := make(chan string)
//invoking the subroutines with channel variables
go data1(chan1)
go data2(chan2)
//Both case statements check for data in chan1 or chan2.
//But data is not available (both routines have a delay of 2 and 4 sec)
//So the default block will be executed without waiting for data in channels.
select {
case x := <-chan1:
fmt.Println(x)
case y := <-chan2:
fmt.Println(y)
default:
fmt.Println("Default case executed")
}
}
Este programa darรก a saรญda:
Default case executed
Isso ocorre porque quando o bloco selecionado foi alcanรงado, nenhum canal tinha dados para leitura. Portanto, o caso padrรฃo รฉ executado.
Mutex
Mutex รฉ a abreviaรงรฃo de exclusรฃo mรบtua. Mutex รฉ usado quando vocรช nรฃo deseja permitir que um recurso seja acessado por vรกrias sub-rotinas ao mesmo tempo. Mutex possui 2 mรฉtodos โ Bloquear e Desbloquear. Mutex estรก contido no pacote de sincronizaรงรฃo. Entรฃo, vocรช tem que importar o pacote de sincronizaรงรฃo. As instruรงรตes que devem ser executadas mutuamente exclusivamente podem ser colocadas dentro de mutex.Lock() e mutex.Unlock().
Vamos aprender o mutex com um exemplo que conta o nรบmero de vezes que um loop รฉ executado. Neste programa esperamos que a rotina execute o loop 10 vezes e a contagem seja armazenada em soma. Vocรช chama essa rotina 3 vezes, entรฃo a contagem total deve ser 30. A contagem รฉ armazenada em uma variรกvel global count.
Primeiro, vocรช executa o programa sem 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)
}
Veja o resultado
Count after i=1 Count: 11 Count after i=3 Count: 12 Count after i=2 Count: 13 Final Count: 13
O resultado pode ser diferente ao executรก-lo, mas o resultado final nรฃo serรก 30.
Aqui o que acontece รฉ que 3 goroutines estรฃo tentando aumentar a contagem de loops armazenada na variรกvel count. Suponha que em um momento a contagem seja 5 e goroutine1 aumente a contagem para 6. As etapas principais incluem
Contagem de cรณpias para temperatura
Aumentar temperatura
Armazene a temperatura de volta ร contagem
Suponha que logo apรณs executar a etapa 3 do goroutine1; outra goroutine pode ter um valor antigo, digamos 3 executa as etapas acima e armazena 4 de volta, o que estรก errado. Isso pode ser evitado usando mutex, que faz com que outras rotinas esperem quando uma rotina jรก estiver usando a variรกvel.
Agora vocรช executarรก o programa com mutex. Aqui as 3 etapas mencionadas acima sรฃo executadas em um 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)
}
Agora a saรญda serรก
Count after i=3 Count: 21 Count after i=2 Count: 28 Count after i=1 Count: 30 Final Count: 30
Aqui obtemos o resultado esperado como resultado final. Porque as instruรงรตes de leitura, incremento e reescrita da contagem sรฃo executadas em um mutex.
Tratamento de erros
Erros sรฃo condiรงรตes anormais como fechar um arquivo que nรฃo estรก aberto, abrir um arquivo que nรฃo existe, etc. As funรงรตes geralmente retornam erros como o รบltimo valor de retorno.
O exemplo abaixo explica mais sobre o erro.
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")
}
A saรญda serรก:
open /invalid.txt: no such file or directory
Aqui tentamos abrir um arquivo inexistente e ele retornou o erro para a variรกvel er. Se o arquivo for vรกlido, o erro serรก nulo
Erros personalizados
Usando este recurso, vocรช pode criar erros personalizados. Isso รฉ feito usando New() do pacote de erros. Reescreveremos o programa acima para usar erros personalizados.
Execute o programa abaixo
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)
}
}
A saรญda serรก:
Custom error message:File name is wrong
Aqui a area() retorna a รกrea de um quadrado. Se a entrada for menor que 1, area() retornarรก uma mensagem de erro.
Lendo arquivos
Arquivos sรฃo usados โโpara armazenar dados. Go nos permite ler dados dos arquivos
Primeiro crie um arquivo, data.txt, em seu diretรณrio atual com o conteรบdo abaixo.
Line one Line two Line three
Agora execute o programa abaixo para ver se ele imprime o conteรบdo de todo o arquivo como saรญda
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))
}
Aqui os dados, err := ioutil.ReadFile(โdata.txtโ) lรช os dados e retorna uma sequรชncia de bytes. Durante a impressรฃo, ele รฉ convertido para o formato string.
Escrevendo arquivos
Vocรช verรก isso com um programa
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
}
}
Aqui รฉ criado um arquivo, test.txt. Se o arquivo jรก existir, o conteรบdo do arquivo serรก truncado. Writeline() รฉ usado para gravar o conteรบdo do arquivo. Depois disso, vocรช fechou o arquivo usando Close().
Folha de fraude
Neste tutorial do Go, abordamos,
| Tema | Descriรงรฃo | Sintaxe |
|---|---|---|
| Tipos bรกsicos | Numรฉrico, string, bool | |
| Variรกveis | Declarar e atribuir valores a variรกveis | var tipo nome_variรกvel var nome_variรกvel tipo = valor var nome_variรกvel1, nome_variรกvel2 = valor1, valor2 nome_variรกvel := valor |
| Constante | Variรกveis โโcujo valor nรฃo pode ser alterado depois de atribuรญdo | variรกvel const = valor |
| Para Loop | Execute instruรงรตes em um loop. | para expressรฃo_de_inicializaรงรฃo; expressรฃo_avaliaรงรฃo; iteraรงรฃo_expressรฃo{ // uma ou mais instruรงรตes } |
| Se mais | ร uma declaraรงรฃo condicional | se condiรงรฃo{ // declaraรงรตes_1 Else {} // declaraรงรตes_2 } |
| interruptor | Declaraรงรฃo condicional com vรกrios casos | mudar expressรฃo { valor do caso_1: declaraรงรตes_1 valor do caso_2: declaraรงรตes_2 valor do caso_n: declaraรงรตes_n default: declaraรงรตes_default } |
| Ordem | Tamanho fixo nomeado sequรชncia de elementos do mesmo tipo | nome da matriz: = [tamanho] tipo {valor_0, valor_1,โฆ, valor_tamanho-1} |
| Fatia | Parte ou segmento de uma matriz | var slice_name [] tipo = array_name[inรญcio:fim] |
| Funรงรตes | Bloco de instruรงรตes que executa uma tarefa especรญfica | func nome_da_funรงรฃo(tipo parรขmetro_1, tipo parรขmetro_n) tipo_retorno { //declaraรงรตes } |
| PACOTES | Sรฃo usados โโpara organizar o cรณdigo. Aumenta a legibilidade e a reutilizaรงรฃo do cรณdigo | importar pacote_nome |
| Adiar | Adia a execuรงรฃo de uma funรงรฃo atรฉ que a funรงรฃo que a contรฉm termine a execuรงรฃo | adiar nome_da_funรงรฃo(lista_de_parรขmetros) |
| Ponteiros | Armazena o endereรงo de memรณria de outra variรกvel. | var nome_variรกvel *tipo |
| Estrutura | Tipo de dados definido pelo usuรกrio que contรฉm mais um elemento do mesmo tipo ou de tipo diferente | digite nome da estrutura estrutura { variรกvel_1 variรกvel_1_tipo variรกvel_2 variรกvel_2_tipo variรกvel_n variรกvel_n_tipo } |
| De Depรณsito | Um mรฉtodo รฉ uma funรงรฃo com um argumento receptor | func (variรกvel tipovariรกvel) nome_mรฉtodo(lista_parรขmetro) { } |
| Gorotina | Uma funรงรฃo que pode ser executada simultaneamente com outras funรงรตes. | vรก nome_funรงรฃo(lista_parรขmetros) |
| Canal | Maneira de as funรงรตes se comunicarem entre si. Um meio no qual uma rotina coloca dados e รฉ acessado por outra rotina. | Declarar: ch := make(chan int) Envie dados para o canal: variรกvel_canal <- nome_variรกvel Receba do canal: nome_variรกvel := <- variรกvel_canal |
| Selecionar | Instruรงรฃo switch que funciona em canais. As declaraรงรตes de caso serรฃo uma operaรงรฃo de canal. Quando qualquer canal estiver pronto com dados, a instruรงรฃo associada a esse caso serรก executada | selecione { caso x := <-chan1: fmt.Println(x) caso y := <-chan2: fmt.Println(y) } |
| Mutex | Mutex รฉ usado quando vocรช nรฃo deseja permitir que um recurso seja acessado por vรกrias sub-rotinas ao mesmo tempo. Mutex tem 2 mรฉtodos โ Bloquear e Desbloquear | mutex.Lock() //declaraรงรตes mutex.Unlock(). |
| Ler arquivos | Lรช os dados e retorna uma sequรชncia de bytes. | Dados, err := ioutil.ReadFile (nome do arquivo) |
| Gravar arquivo | Grava dados em um arquivo | l, err := f.WriteString(text_to_write) |
