Linguagem de

Programação Go

  • Vanilton da Thálita 💍
  • Pai do Louie 👦🏻 e Lourenzo 👶🏻
  • Cientista da Computação 🤓
  • 🎓 Especialista  em Engenharia de Software e Gestão de Pessoas
  • 👨🏻‍💻Pessoas e Processos na @fpf.tech 😃
  • 👨🏻‍🏫 Professor na @fpftech.educacional

APRESENTAÇÃO

QUEM SÃO VOCÊS?

  • Nome, profissão ou ocupação e sua expertise em informática.
  • Uma expectativa para disciplina

ACORDOS DE TIME

1

Introdução aos conceitos de linguagem de programação

2

GO

Definição

Porque usar Go?
Quem usa Go?
Aplicabilidade da linguagem Go
Instalação e configuração do ambiente

 

3

Tipos Básicos, Operadores e Variáveis

4

Estrutura de controle de fluxo

5

Arrays, Slices e Maps

AGENDA

6

Ponteiros

7

Structs

AGENDA

O que é uma linguagem de programação?

Comando em Português para Go

// Mostre a mensagem "Olá, mundo!"
println("Olá, mundo!")
  • Citem um comando em português.

// Guarde o nome "Ana" em uma variável
nome := "Ana"
// Some 2 com 3 e guarde o resultado
resultado := 2 + 3
// Se a idade for maior ou igual a 18, diga "Pode votar"
if idade >= 18 {
   fmt.Println("Pode votar") 
}
    
// Repita de 0 até 4 e mostre o número
for i := 0; i < 5; i++ {
    fmt.Println(i)
}
    

TIPOS DE LINGUAGEM

Definições

write()

exit()

data()

Linguagem de máquina

Linguagem de montagem

LINGUAGEM COMPILADA

  • O código-fonte é traduzido de uma só vez para linguagem de máquina por um compilador.
  • O resultado é um arquivo executável independente (.exe, .out, etc.).
  • Exemplos: C, C++, Go, Rust

LINGUAGEM COMPILADA X INTERPRETADA

package main

import "fmt"

func main() {
    fmt.Println("Olá, mundo!")
}

go build main.go     
./main               

main.exe

print("Olá, mundo!")

python programa.py 

“Enquanto o Python precisa estar instalado em qualquer máquina que vá rodar seu script, com Go você pode compilar e enviar só o executável.”

LINGUAGEM COMPILADA X INTERPRETADA

Característica Compilada Interpretada
Tradução Todo o código de uma vez Linha por linha
Velocidade de execução Mais rápida Pode ser mais lenta
Portabilidade Menos portável Mais portável 
Detecção de erros Antes da execução (em tempo de compilação) Durante a execução (em tempo real)
Gera arquivo executável? Sim Não
Exemplo de linguagem C, C++, Rust, GO Python, JavaScript

LINGUAGEM INTERPRETADA X COMPILADA - PARA FIXAR

"Linguagens compiladas são como traduzir um livro inteiro antes de ler. Já as interpretadas são como ter um tradutor lendo e traduzindo cada frase em tempo real."

RANKING DE LINGUAGENS DE PROGRAMAÇÃO

RANKING DE LINGUAGENS DE PROGRAMAÇÃO

Python

  • Domínio em IA e Ciência de Dados: Bibliotecas como TensorFlow e Pandas consolidam sua posição.

  • Sintaxe Amigável: Atraente para iniciantes e poderosa para tarefas complexas.

  • Apoio Corporativo: Empresas como Google e Amazon investem fortemente.

RANKING DE LINGUAGENS DE PROGRAMAÇÃO

TypeScript

  • Superset do JavaScript: Oferece tipagem estática, melhorando a qualidade e manutenção do código.
  • Adoção Empresarial: Utilizado por empresas como Microsoft e Slack.

RANKING DE LINGUAGENS DE PROGRAMAÇÃO

C++

  • Desempenho em Aplicações Críticas: Preferido para motores de jogos, sistemas operacionais e sistemas embarcados devido ao controle preciso dos recursos do sistema.

RANKING DE LINGUAGENS DE PROGRAMAÇÃO

Go

  • Em crescimento, especialmente em infraestrutura, back-end e cloud computing.
    Adotado por empresas como Google, Uber, Dropbox, Kubernetes e Docker.
  • Go tem como objetivo substituir linguagens como C/C++ em sistemas distribuídos e escaláveis com foco em simplicidade, desempenho e concorrência.

Dito isso iremos trabalhar com...

DEFINIÇÃO

  • Go, também conhecido como Golang, é uma linguagem de programação de código aberto.
    Criada pelo Google em 2007 por Robert Griesemer, Rob Pike, e Ken Thompson.

DEFINIÇÃO

Objetivos principais:

  • Simplicidade e eficiência
  • Concorrência nativa
  • Compilação rápida

 

PORQUE USAR GO?

  • Sintaxe simples e clara
  • Alto desempenho
  • Facilita o desenvolvimento de sistemas concorrentes e distribuídos
  • Excelente suporte para programação em rede e serviços web
  • Usada por empresas como Google, Uber, Dropbox, Docker

PORQUE USAR GO?

  • De acordo com site TIOBE Index for October 2025 para a linguagem GO mostra uma crescente no uso do linguagem em relação ao ano anterior.

QUEM USA GO?

APLICABILIDADE DA LINGUAGEM GO

  • 💾  Backend Web e APIs

    • Go possui frameworks leves (como Gin, Echo) para criação de APIs RESTful com alta performance.

    • Excelente desempenho em resposta e uso de memória.

  • ⚙️  Ferramentas de Linha de Comando (CLI)

    • Go produz binários leves e multiplataforma, perfeitos para utilitários CLI.

    • Simples de empacotar e distribuir.

    • Exemplos:

    • kubectl, helm, hugo (gerador de site estático)

  • ​☁️ Cloud Computing e Microserviços

    • Estrutura leve e compilação em binários únicos facilitam a distribuição em contêineres.
    • Excelente para desenvolver microserviços em arquiteturas distribuídas.

    • Ferramentas famosas escritas em Go:

      • Docker

      • Kubernetes

      • Prometheus

      • Terraform

  • 🧩 Desenvolvimento de Sistemas Concorrentes

    • Go é projetada com suporte nativo à concorrência via goroutines e channels.

    • Ideal para sistemas que exigem alta escalabilidade, como servidores web, proxies e serviços em tempo real.

    • Exemplos:

      • Servidores HTTP de alto desempenho

      • Chat em tempo real

      • Processamento paralelo de dados

INSTALAÇÃO E CONFIGURAÇÃO DO AMBIENTE

INSTALAÇÃO E CONFIGURAÇÃO DO AMBIENTE

  • Instalação Go
    • Baixe o instalador e execute-o.
    • Siga as instruções de instalação.
    • Verifique se o Go foi instalado corretamente, abra o terminal (CMD/PowerShell) e digite:

INSTALAÇÃO E CONFIGURAÇÃO DO AMBIENTE

INSTALAÇÃO E CONFIGURAÇÃO DO AMBIENTE

  • Marque todas as opções quando chegar na tela abaixo.

     

INSTALAÇÃO E CONFIGURAÇÃO DO AMBIENTE

  • Criando primeiro projeto no GoLand.

  • Clique em New Project/Novo Projeto.

     

INSTALAÇÃO E CONFIGURAÇÃO DO AMBIENTE

  • Defina o nome do projeto ProjetoGo.

  • Clique no botão create.

ESTRUTURA DO PROJETO GO

  • Primeiro projeto criado entenda a estrutura de um projeto GO:

    • go.mod: Usado para rastrear as dependências do projeto e definir o módulo. Esse arquivo é gerado ao rodar go mod init.

    • main.go: Ponto de entrada da aplicação.

    • README.md: Contém a descrição e as instruções do projeto.

ESTRUTURA DE UM PROGRAMA GO

  • Explicando o Programa “Hello and welcome”:

    • package main: Declara que este é o pacote principal e o código será compilado como um executável.

    • import "fmt": Importa o pacote fmt, que contém funções para entrada e saída de dados (ex.: Println).

    • func main(): A função principal. É onde o código começa a ser executado.

    • fmt.Println("Hello and welcome!"): Usa a função Println do pacote fmt para imprimir "Hello and welcome!" no console.

       

COMPILAÇÃO E EXECUÇÃO NO GO

  • O Go compila diretamente para um binário executável, que pode ser executado nativamente no sistema.

  • Para compilar e executar um programa GO, use os comandos abaixo no terminal da IDE GoLand:

Execução

Compilação

SINTAXE BÁSICA E TIPOS DE DADOS EM GO

package main

import "fmt"

func main() {
    // declaração explícita com var
    var nome string
    var idade int

    // declaração com atribuição
    var sobrenome string = "Vasconcelos"
    var peso float64 = 85.6

    // atribuição curta (somente dentro de funções)
    cor := "pardo"
    temFilhos := true

    nome = "Raimundo José"
    idade = 37

    println("Nome: ", nome)
    println("Idade: ", idade)
    println("Sobrenome: ", sobrenome)
    fmt.Printf("Peso: %.2f\n", peso)
    println("Cor: ", cor)
    println("TemFilhos: ", temFilhos)
}
  • Em Go, as variáveis podem ser declaradas de várias maneiras:

    • Usando a palavra-chave var.

    • Usando a atribuição curta := (somente dentro de funções).

       

TIPOS DE DADOS

func tiposDeDados() {
    idade := 21       // Inteiro
    altura := 1.75    // Ponto flutuante
    nome := "Ana"     // String
    vivo := true      // Booleano

    println("Idade: ", idade)
    println("Altura: ", altura)
    println("Nome: ", nome)
    println("Vivo: ", vivo)
}
  • Inteiros: int, int8, int16, int32, int64 (e suas versões sem sinal uint).

  • Pontos flutuantes:  float32, float64.

  • Strings: Cadeias de caracteres (imutáveis).

  • Booleanos: bool (verdadeiro ou falso).

     

TIPOS DE DADOS - CONSTANTES

func constante() {
    const pi = 3.14
    const nome = "GoLang"

    println("PI: ", pi)
    println("Nome: ", nome)
}
  • Constantes em Go são declaradas com a palavra-chave const.

  • Diferente das variáveis, seu valor não pode ser alterado após a atribuição.

     

TIPOS DE DADOS - CONVERSÃO DE TIPOS

func conversaoDeTipos() {
    var nota int = 85
    var notaMedia float64 = float64(nota) / 10
    fmt.Println(notaMedia)
}
  • Em Go, a conversão de tipos deve ser feita de forma explícita.

  • Sintaxe para conversão:

    • var inteiro int = 10

    • var flutuante float64 = float64(inteiro)

    • var novoInteiro int = int(flutuante)

       

ENTRADA E SAÍDA

  • O pacote fmt em Go é utilizado para formatar e imprimir dados no console, assim como para ler entradas do usuário. Aqui está um resumo dos principais comandos de entrada e saída:

    • Entrada (Input):

      • fmt.Scan(): Lê entradas de uma ou mais variáveis, separadas por espaços.
        fmt.Scanln(): Similar ao Scan(), mas lê até o fim da linha (após o "Enter").

      • fmt.Scanf():Lê a entrada com base em um formato especificado (similar ao Printf, mas para entrada).

    • Saída (Output):

      • fmt.Println(): Imprime uma ou mais variáveis no console com uma nova linha no final.

      • fmt.Printf(): Imprime com formatação especificada, sem adicionar automaticamente uma nova linha.

// Entrada e Saída de Dados
var input1 string
var input2 string

fmt.Printf("Entre com 2 palavras - (Scan): ")
fmt.Scan(&input1, &input2)
fmt.Printf("Texto Lido - (Scan): %s - %s\n", input1, input2)

var input3 string
fmt.Printf("Digite um texto - (Scanln): ")
fmt.Scanln(&input3)
fmt.Printf("Texto digitado - (Scanln): %s\n", input3)

var input4 string
var input5 int

fmt.Printf("Digite um texto - (Scanf): ")
fmt.Scanf("%s", &input4)
fmt.Printf("Texto digitado: %s\n", input4)

fmt.Printf("Digite um numero - (Scanf): ")
fmt.Scanf("%d", &input5)
fmt.Printf("numero digitado - (Scanf): %d\n", input5)

ENTRADA E SAÍDA

Em Go, para ler uma entrada de texto que contém espaços, você pode usar o método fmt.Scanln() ou bufio.Reader junto com os.Stdin para capturar a linha inteira.

  • bufio.NewReader(os.Stdin): Cria um leitor a partir da entrada padrão (o console).
  • reader.ReadString('\n'): Lê até o usuário pressionar "Enter" (fim de linha), capturando todo o texto com espaços.
  • Com o bufio.Reader, você pode capturar toda a linha, mesmo que contenha espaços. Essa é a abordagem mais adequada para entradas com frases ou sentenças.

 

 

// Entrada de Dados - bufio
reader := bufio.NewReader(os.Stdin)
fmt.Printf("Digite um texto com espaços:")
texto, _ := reader.ReadString('\n')
fmt.Printf("Você digitou: %s", texto)

OPERADORES ARITMÉTICOS

Go suporta os operadores aritméticos básicos:

  • Soma: +
  • Subtração: -
  • Multiplicação: *
  • Divisão: /
  • Módulo (resto da divisão): %
// Operadores aritméticos
a := 10
b := 3

fmt.Println(a + b) // Soma: 13
fmt.Println(a - b) // Subtração: 7
fmt.Println(a * b) // Multiplicação: 30
fmt.Println(a / b) // Divisão: 3
fmt.Println(a % b) // Módulo: 1

OPERADORES RELACIONAIS

Operadores relacionais em Go:

  • Igual a: ==
  • Diferente de: !=
  • Maior que: >
  • Menor que: <
  • Maior ou igual a: >=
  • Menor ou igual a: <=

 

// Operadores Relacionais
x := 10
y := 5

fmt.Println(x > y)   // true
fmt.Println(x <= y)  // false
fmt.Println(x == 10) // true
fmt.Println(x != y)  // true

OPERADORES LÓGICOS

# Definindo variáveis
a = 10
b = 5
c = 7

# Exemplo sem parênteses usando 'and' e operadores relacionais 
resultado = a > b and  b < c
print("Resultado de a > b and b < c: ", resultado) # Output: True

# Exemplo sem parênteses usando 'or' e operadores relacionais 
resultado = a < b or c >= b
print("Resultado de a < b or c >= b: ", resultado) # Output: True

# Exemplo sem parênteses usando 'not' para inverter o resultado 
resultado = not a == b
print("Resultado de not a == b: ", resultado) # Output: True

Operadores relacionais em Go:

  • &&: E lógico (ambas as condições precisam ser verdadeiras)
  • ||: OU lógico (pelo menos uma condição verdadeira) 
  • !: Negação (inverte o valor lógico)

 

EXERCÍCIO DE FIXAÇÃO

Crie um programa que peça ao usuário para inserir três números inteiros. O programa deve calcular e exibir a média aritmética desses três números.

  • Instruções: 
    • Solicitar três números inteiros do usuário.
    • Calcular a média dos números.
    • Exibir o resultado da média.

 

package main

import "fmt"

func main() {
    var num1, num2, num3 int

    fmt.Println("Digite o primeiro número:")
    fmt.Scanln(&num1)

    fmt.Println("Digite o segundo número:")
    fmt.Scanln(&num2)

    fmt.Println("Digite o terceiro número:")
    fmt.Scanln(&num3)

    media := (num1 + num2 + num3) / 3
    fmt.Printf("A média dos números é: %d\n", media)
}

EXERCÍCIO DE FIXAÇÃO

Calculadora Simples

Criar uma calculadora que pede dois números e realiza as quatro operações básicas.

  • Instruções:
    • Solicitar que o usuário insira dois números.
    • Realizar as operações de soma, subtração, multiplicação e divisão.
    • Exibir o resultado de cada operação.

 

func calculadoraSimples() {
    var num1, num2 float64

    // Entrada de dados
    fmt.Println("Digite o primeiro número:")
    fmt.Scanln(&num1)
    fmt.Println("Digite o segundo número:")
    fmt.Scanln(&num2)

    // Operações
    soma := num1 + num2
    subtracao := num1 - num2
    multiplicacao := num1 * num2
    divisao := num1 / num2

    // Saída
    fmt.Printf("Soma: %.2f\n", soma)
    fmt.Printf("Subtração: %.2f\n", subtracao)
    fmt.Printf("Multiplicação: %.2f\n", multiplicacao)
    fmt.Printf("Divisão: %.2f\n", divisao)
}

EXERCÍCIO DE FIXAÇÃO

Login

Criar uma algoritmo que simule o login de um usuário.

  • Instruções:
    • Definir variáveis para usuário, senha e "status" ativo simulando um usuário previamente criado.
    • Solicitar que o usuário insira usuario e senha.
    • Realize a verificação ao simular o login se ambas estão de acordo com o usuário simulado.
    • Exibir o resultado de cada operação tratando com uma mensagem de saída.

 

package main

import "fmt"

func main() {
    var usuario, senha string
    var ativo bool = true

    // Dados simulados
    usuarioCorreto := "admin"
    senhaCorreta := "1234"

    fmt.Println("Digite o nome de usuário:")
    fmt.Scanln(&usuario)

    fmt.Println("Digite a senha:")
    fmt.Scanln(&senha)

    // Verificação de login com operadores lógicos
    if usuario == usuarioCorreto && senha == senhaCorreta && ativo {
        fmt.Println("Login realizado com sucesso!")
    } else if usuario == usuarioCorreto && senha == senhaCorreta && !ativo {
        fmt.Println("Usuário correto, mas conta inativa.")
    } else if usuario == usuarioCorreto || senha == senhaCorreta {
        fmt.Println("Usuário ou senha corretos, mas combinação inválida.")
    } else {
        fmt.Println("Usuário e senha incorretos.")
    }

    // Exemplo de negação
    if !(usuario == usuarioCorreto && senha == senhaCorreta) {
        fmt.Println("Tentativa de login inválida.")
    }
}

IMPORTAÇÕES

  • Seguindo a seguinte estrutura de projeto, vejamos como podemos realizar a importação de módulos.

meu_projeto/
├── main.go
└── util/
    └── mensagens.go
//mensagens.go
package util

import "fmt"

func Ola(nome string) {
	fmt.Printf("Olá, %s!\n", nome)
}
//main.go
package main

import (
	"meu_projeto/util" // importa o pacote local
)

func main() {
	util.Ola("Mundo")
}

IMPORTAÇÕES

  • Também é possível criar "alias" ou apelidos para as importações:

meu_projeto/
├── main.go
└── util/
    └── mensagens.go
import alias "caminho/do/pacote"
//main.go
package main

import (
	msg "meu_projeto/util" // importa o pacote local
)

func main() {
	msg.Ola("Mundo")
}

ESTRUTURA DE DECISÃO

  • Estruturas de decisão (ou estruturas condicionais) são usadas para controlar o fluxo de execução de um programa com base em condições. Em Go, a principal estrutura de decisão é o bloco if, que pode ser complementado pelos blocos else if e else para verificar múltiplas condições e tomar diferentes decisões.

     

ESTRUTURA DE DECISÃO

  • if: Avalia uma condição e, se for verdadeira, executa o bloco de código associado.

  • else if:  Permite verificar outras condições se a condição if anterior for falsa.

  • else: Executa um bloco de código quando todas as condições anteriores são falsas.

     

if condicao {
    // Código se condição for verdadeira
} else if outraCondicao {
    // Código se a outra condição for verdadeira
} else {
    // Código se nenhuma condição for verdadeira
}

ESTRUTURA DE DECISÃO

package main

import "fmt"

func main(){
  idade := 20

  if idade >= 18 {
      fmt.Println("Maior de idade")
  } else {
      fmt.Println("Menor de idade")
  }  
}
  • Condicionais if, else permite executar blocos de código com base em condições.

ESTRUTURA DE DECISÃO

package main

import (
    "fmt"
)

func main() {
    var numero int

    fmt.Print("Digite um número inteiro: ")
    fmt.Scanln(&numero)

    if numero > 0 && numero%2 == 0 {
        fmt.Println("O número digitado é par.")
    } else if numero > 0 && numero%2 != 0 {
        fmt.Println("O número digitado é ímpar.")
    } else {
        fmt.Println("O número digitado é zero ou negativo.")
    }
}
  • Condicional else if verifica múltiplas condições.

ESTRUTURA DE DECISÃO

# Exemplo de estrutura aninhada
func podeDirigir() {

	var idade, possuiCarteira int
	fmt.Println("Digite sua idade: ")
	fmt.Scan(&idade)
	fmt.Println("Digite 1 se possui carteira ou 0 senão possui: ")
	fmt.Scan(&possuiCarteira)

	temCarteira := 1 == possuiCarteira

	if idade >= 18 {
		if temCarteira {
			println("Você pode dirigir")
		} else {
			println("Você não pode dirigir sem carteira.")
		}

	} else {
		println("Você é menor de idade e não pode dirigir.")
	}
}

ESTRUTURA DE DECISÃO

  • O switch é uma alternativa mais organizada para múltiplos if-else, especialmente quando há várias condições a serem avaliadas.

switch valor {
    case padrão1:
        // bloco de código
    case padrão2:
        // outro bloco
    default:
        // caso padrão (equivalente ao 'else')
}

ESTRUTURA DE DECISÃO

dia := 2

switch dia {
case 1:
    fmt.Println("Domingo")
case 2:
    fmt.Println("Segunda")
default:
    fmt.Println("Outro dia")
}

ESTRUTURA DE DECISÃO

switch {
case idade < 18:
    fmt.Println("Menor de idade")
case idade >= 18:
    fmt.Println("Maior de idade")
}
  • Também funciona sem variável.

ESTRUTURA DE REPETIÇÃO

  • O for é o único loop disponível no Go, e pode ser utilizado de diversas formas. Ele pode ser semelhante ao while em outras linguagens, ou usado de forma tradicional com contadores.

for inicialização; condição; incremento {
	// Código a ser executado
}
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

Em Go, a única estrutura de repetição é o for, mas ela é bem flexível e cobre os usos de while, do-while e for tradicional de outras linguagens.

  • Um for pode se comportar como um loop while.

i := 0
for i < 5 {
    fmt.Println(i)
    i++
}

ESTRUTURA DE REPETIÇÃO

for {
    fmt.Println("Executando para sempre...")
    break // ou use return para sair
}
  • Um Loop Infinito (como while true)

  • Controle de Loop usando continue

     

for i := 1; i <= 10; i++ {
	if i%2 == 0 {
		continue // Pula para a próxima iteração se for par
	}
	fmt.Println(i) // Só imprime números ímpares
}

ESTRUTURA DE REPETIÇÃO

for i := 0; i < 10; i++ {
    if i == 5 {
        break // Sai do loop quando i for igual a 5
    }
    fmt.Println(i)
}
  • Controle de Loop com break interrompe imediatamente.

     

  • Usando range para itera sobre arrays, slices, strings, mapas ou canais.

     

numeros := []int{10, 20, 30}

for indice, valor := range numeros {
    fmt.Printf("Índice %d: valor %d\n", indice, valor)
}

ESTRUTURA DE REPETIÇÃO

texto := "GoLang"
for i, c := range texto {
    fmt.Printf("Posição %d: Letra %c\n", i, c)
}
  • Percorrendo uma string (For com range)

Jogo de Adivinhação de Números

O programa gera um número aleatório entre 1 e 10. O usuário deve adivinhar o número. O programa informa se o palpite é alto ou baixo.
Use for e break para repetir até acertar.

 

EXERCÍCIOS DE FIXAÇÃO

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())           // Garante números aleatórios diferentes a cada execução
    numeroSecreto := rand.Intn(10) + 1         // Gera número de 1 a 10
    var palpite int

    fmt.Println("Adivinhe o número (entre 1 e 10):")

    for {
        fmt.Print("Digite seu palpite: ")
        fmt.Scanln(&palpite)

        if palpite < numeroSecreto {
            fmt.Println("Muito baixo!")
        } else if palpite > numeroSecreto {
            fmt.Println("Muito alto!")
        } else {
            fmt.Println("Parabéns! Você acertou!")
            break
        }
    }
}
  • Em Go Arrays, slices e mapas são as principais estruturas de dados para armazenar coleções em Go. Cada uma dessas estruturas tem características específicas e é usada em diferentes cenários.

ARRAYS, SLICES E MAPS

  • O que é um Array?
    Um array é uma sequência de elementos de tamanho fixo e de mesmo tipo. O tamanho do array deve ser especificado na sua criação e não pode ser alterado depois.

     

     

// Declaração de um array de 5 inteiros
var numeros [5]int

fmt.Println(numeros)

ARRAYS, SLICES E MAPS

  • Inicializando array acessando os índices manualmente.
// Inicializando Array
arrayNumeros[0] = 1
arrayNumeros[1] = 2
arrayNumeros[2] = 3
arrayNumeros[3] = 4
arrayNumeros[4] = 5

// Mostrando os valores do array
fmt.Println(arrayNumeros)

ARRAYS, SLICES E MAPS

  • Declarando Array Inicializados.
arrayNomes := [4]string{"Pedro", "Louie", "Maria", "Lourenzo"}

fmt.Println(arrayNomes) // Output: [Pedro Louie Maria Lourenzo]
  • Obtendo tamanho do array utilizando a função len().

ARRAYS, SLICES E MAPS

// Tamanho do Array utilizando len
arrayNumeros := [5]int{1, 2, 3, 4, 5}
fmt.Printf("Tamanho do Array é [%d]", len(arrayNumeros)) //Output: Tamanho do Array é [5]
  • Iterando sobre array utilizando o loop for.
for i := 0; i < 5; i++ {
	arrayNumeros[i] = i + 10
}
fmt.Println(arrayNumeros) //Output: [10 11 12 13 14]
  • Iterando sobre array utilizando for e range.

ARRAYS, SLICES E MAPS

for index, value := range arrayNumeros {
	fmt.Println("Índice:", index, "Valor: ", value)
}
/*Output: 
Índice: 0 Valor:  10
Índice: 1 Valor:  11
Índice: 2 Valor:  12
Índice: 3 Valor:  13
Índice: 4 Valor:  14*/
  • Go suporta arrays multidimensionais, permitindo trabalhar com matrizes.

ARRAYS, SLICES E MAPS

// Declarando array 2D de 3 linhas e 3 colunas
array2D := [3][3]int{
    {11, 12, 13},
    {15, 16, 17},
    {19, 20, 21},
}

// Iterando sobre o array 2D
for i := 0; i < len(array2D); i++ {
    for j := 0; j < len(array2D[i]); j++ {
        fmt.Printf(" %d ", array2D[i][j])
    }
    fmt.Print("\n")
}
/*Output: 
 11  12  13 
 15  16  17 
 19  20  21 
 */

EXERCÍCIOS DE FIXAÇÃO

Desenvolva um programa em Go que permita ao usuário visualizar os números que ele escolheu para um sorteio da Loteria Federal.
Instruções:

  • Solicite que o usuário informe 6 números distintos entre 1 e 60.
  • Crie uma matriz 2D (array bidimensional) com 6 linhas e 10 colunas, preenchida com números de 1 a 60.
  • Exiba a matriz substituindo cada número escolhido pelo usuário por ele mesmo envolto em colchetes [ ], para destacar suas escolhas.

 

Exemplo:
Informe os seus números: 06 12 23 34 42 50

 

O que é um Slice?

  • Um slice é semelhante a um array, mas com tamanho dinâmico.
  • Slices são mais flexíveis e mais usados do que arrays em Go.
  • Podemos criar um slice a partir de um array ou usando a função make().

ARRAYS, SLICES E MAPS

// Slice criado diretamente do array
sliceNumeros := []int{1, 2, 3, 4, 5}
fmt.Println("Slices numeros: ", sliceNumeros)

// Slice criado vazio
slicesLetras := make([]string, 2)
fmt.Println("Slices letras: ", slicesLetras)

A função append() é usada para adicionar elementos a um slice, aumentando seu tamanho dinamicamente.

ARRAYS, SLICES E MAPS

// Add elemento ao sliceNumeros
sliceNumeros := []int{1, 2, 3, 4, 5}
sliceNumeros = append(sliceNumeros, 6)
fmt.Println("Slices numeros: ", sliceNumeros)

// Add elemento ao sliceLetras
slicesLetras = append(slicesLetras, "A")
slicesLetras = append(slicesLetras, "B")
slicesLetras = append(slicesLetras, "C")
slicesLetras = append(slicesLetras, "D")
slicesLetras = append(slicesLetras, "E")
fmt.Println("Slices letras: ", slicesLetras)

Detalhando: Um slice em Go é uma estrutura que contém:

  • Um ponteiro para o array subjacente;
  • Um tamanho (length);
  • Uma capacidade (capacity).
// Exemplo
s := make([]int, 0, 5) // make: defini uma capacidade

// Neste exemplo:

// O length é 0;

// A capacity é 5;

// Um array interno de tamanho 5 é alocado para armazenar os dados.

ARRAYS, SLICES E MAPS

Quando usamos:

s = append(s, 1)

/*
o Go:

1. Verifica se ainda há capacidade disponível no array subjacente.

Se houver, ele apenas adiciona o valor no próximo espaço e incrementa o length.

Se não houver capacidade suficiente, o Go:

2. Cria um novo array maior (geralmente o dobro da capacidade anterior),

3. Copia todos os elementos antigos para esse novo array,

4. Adiciona o novo elemento,

E o slice agora aponta para esse novo array.
*/

ARRAYS, SLICES E MAPS

Exemplo de comportamento interno:

s := []int{1, 2, 3}
fmt.Println(len(s), cap(s)) // 3 3

s = append(s, 4) // Capacidade estourou!
fmt.Println(len(s), cap(s)) // 4 6 (por exemplo)

//O Go internamente realoca a memória e cria um novo array com uma capacidade maior.

ARRAYS, SLICES E MAPS

💡 Exemplo visual do append com realocação de memória

s := make([]int, 0, 3) // slice com capacidade 3
s = append(s, 1)
s = append(s, 2)
s = append(s, 3)
s = append(s, 4) // aqui a capacidade estoura!

ARRAYS, SLICES E MAPS

Antes do append(4):
┌─────┬─────┬─────┐
│  1  │  2  │  3  │ ← slice s (capacidade cheia)
└─────┴─────┴─────┘

Depois do append(4):
┌─────┬─────┬─────┬─────┬─────┬─────┐
│  1  │  2  │  3  │  4  │     │     │ ← novo array criado
└─────┴─────┴─────┴─────┴─────┴─────┘
             ↑
         slice s agora aponta para este novo array

Como saber se dois slices apontam para o mesmo array?

s1 := []int{1, 2, 3}
s2 := s1
s3 := append(s1, 4, 5, 6, 7) // provavelmente vai realocar

fmt.Printf("s1 pointer: %p\n", &s1[0])
fmt.Printf("s2 pointer: %p\n", &s2[0])
fmt.Printf("s3 pointer: %p\n", &s3[0])

// Output:
// s1 pointer: 0x14000120000
// s2 pointer: 0x14000120000 (mesmo que s1)
// s3 pointer: 0x14000124000 (diferente! novo array criado)

ARRAYS, SLICES E MAPS

Iterando sobre Slices: Assim como arrays, slices também podem ser percorridos com um for ou range para iterar sobre os seus elementos

 

// Iterando slice com for
for i := 0; i < len(sliceNumeros); i++ {
    fmt.Println("Slices letras: ", sliceNumeros[i])
}

// Iterando slice com for e range
for i, v := range slicesLetras {
    fmt.Printf("Índice: %d, Valor: %s\n", i, v)
}

ARRAYS, SLICES E MAPS

Removendo elementos do slice: Remover um elemento de um slice envolve criar um novo slice, excluindo o elemento desejado.

 

sliceNumeros := []int{1, 2, 3, 4, 5}
sliceNumeros = append(sliceNumeros, 6)
fmt.Println("Slices numeros: ", sliceNumeros) 
// Output: Slices numeros:  [1 2 3 4 5 6]

sliceNumeros = append(sliceNumeros[:2])
fmt.Println("Slices numeros: ", sliceNumeros) 
// Output: Slices numeros:  [1 2]


sliceNumeros = append(sliceNumeros[0:2], 
                    sliceNumeros[3:]...)
fmt.Println("Slices numeros: ", sliceNumeros) 
// Output: Slices numeros:  [1 2 4 5 6]

ARRAYS, SLICES E MAPS

  • sliceNumeros[:2] equivale a sliceNumeros[0:2]

  • Inclui o índice 0 e 1 (mas não o 2)

  • A operação não remove os elementos do slice original — ela apenas cria uma nova fatia que aponta para os mesmos elementos até o índice 2.

O que é um Map?

  • Em Go, maps são coleções de pares chave-valor, onde cada chave é única e associada a um valor.
  • Eles são extremamente úteis quando você precisa de associações rápidas, como dicionários. Vamos explorar como trabalhar com maps em Go.

 

// Cria um map com chave do tipo
// string e valor do tipo int e vazio
mapNomes := make(map[string]int)
fmt.Println("Map Nomes: ", mapNomes) 
// Output: Map Nomes:  map[]


// Inserindo valores no mapNomes
mapNomes["Raimundo"] = 37
mapNomes["Maria"] = 18
mapNomes["Ana"] = 20
mapNomes["Paula"] = 22

fmt.Println("Map Nomes: ", mapNomes) 
//Output: Map Nomes:  map[Louie:6 Lourenzo:1 Thálita:36 Vanilton:34]

ARRAYS, SLICES E MAPS

Criando map diretamente com uma literal sem o uso do make.

// Criando um map literal sem make
mapProduto := map[int]string{
    1: "Resistor 1k Ohm 5%",
    2: "Diodo 1N4007",
    3: "LED Difuso 5mm Azul",
}

fmt.Println("Map Produto: ", mapProduto)
//Output: Map Produto:  map[1:Resistor 1k Ohm 5% 2:Diodo 1N4007 3:LED Difuso 5mm Azul]

ARRAYS, SLICES E MAPS

Adicionando itens no Map que já está inicializado.

// Adicionando itens no mapProduto
mapProduto[4] = "Capacitor"
mapProduto[5] = "Placa montada"

fmt.Println("Map Produto: ", mapProduto)
// Output: Map Produto:  map[1:Resistor 1k Ohm 5% 2:Diodo 1N4007 3:LED Difuso 5mm Azul 4:Capacitor 5:Placa montada]


Verificando se uma chave existe: Ao acessar um valor, você pode verificar se a chave realmente existe no map usando o segundo valor de retorno da expressão map[chave].

 

// Verificando se a chave existe em um map
valor, existe := mapProduto[6]

fmt.Println("Map Produto: ", valor, " - ", existe)
// Output: Map Produto:  -  false

ARRAYS, SLICES E MAPS

Removendo elementos com delete(): Você pode remover uma chave e seu valor associado do map usando a função delete().

// Removendo elementos do map com a função delete()
delete(mapProduto, 4)

fmt.Println("Map Produto: ", mapProduto)
// Output: Map Produto:  map[1:Resistor 1k Ohm 5% 2:Diodo 1N4007 3:LED Difuso 5mm Azul 5:Placa montada]

Iterando sobre um map com range: Você pode usar um loop range para iterar sobre os pares chave-valor do map.

// Iterando sobre o map usando range
for chave, valor := range mapProduto {
    fmt.Printf("Chave: %d, Valor: %s\n", chave, valor)
}

ARRAYS, SLICES E MAPS

Tamanho de um map: Você pode usar a função len() para obter o número de pares chave-valor presentes no map.

// Tamanho de um map usando a função len()
fmt.Println("Map Produto: ", len(mapProduto))

Map de Maps: Você pode criar mapas cujos valores também são mapas. Isso é útil para representar estruturas mais complexas, como uma tabela de dados ou um dicionário aninhado.

// Criando um map de maps
estoque := map[int]map[string]string{
	1: {
		"nome":     "Resistor 1k",
        "categoria": "Eletrônico",
    },
    2: {
        "nome":     "LED Azul",
        "categoria": "Eletrônico",
       },
    }

// Acessando um valor
fmt.Println("Produto 1:", estoque[1]["nome"])

ARRAYS, SLICES E MAPS

Map de Maps: Percorrendo o mapa de mapas.

// Iterando sobre o map de maps
for id, produto := range estoque {
	
    fmt.Println("ID:", id)
	
    for chave, valor := range produto {
		fmt.Printf("  %s: %s\n", chave, valor)
	}
}

ARRAYS, SLICES E MAPS

EXERCÍCIOS DE FIXAÇÃO

Verificador de Palíndromo:
Escreva um programa que verifique se uma palavra inserida pelo usuário é um palíndromo. Uma palavra é considerada palíndromo se ela pode ser lida da mesma forma de trás para frente, como "arara" ou "radar".
Requisitos:

  •  Solicite uma string do usuário.
  • Verifique se a string é igual ao seu reverso.

 

EXERCÍCIOS DE FIXAÇÃO

Ordenação de Números:
Crie um programa que leia uma lista de números inteiros e os ordene em ordem crescente. Não utilize funções prontas de ordenação, como sort.Sort(). Implemente o algoritmo Bubble Sort manualmente.


Requisitos:

  • Solicite ao usuário para inserir a quantidade de números e, em seguida, os números. 
  • Implemente a função bubbleSort(arr []int) que realiza a ordenação.

 

EXERCÍCIOS DE FIXAÇÃO

Soma de Números Pares: 
Escreva um programa que solicite uma lista de números inteiros e calcule a soma de todos os números pares presentes na lista.
 

Requisitos:

  • Solicite ao usuário a quantidade de números e os números.
  • Calcule e exiba a soma dos números pares.

 

PONTEIROS EM GO

O que é um Ponteiro?

  • Um ponteiro é uma variável que armazena o endereço de memória de outra variável.
  • Em vez de guardar um valor diretamente, ele guarda a referência a esse valor.

 

Declaração e Uso de Ponteiros:

  • Para criar um ponteiro para uma variável, usamos o símbolo & para obter o endereço dessa variável.
  • Para acessar o valor de um ponteiro, usamos o símbolo * (chamado de desreferenciação).

 

package main

import "fmt"

func declaracaoPonteiro() {
    a := 42              // variável normal
    p := &a              // p é um ponteiro para a variável a
    fmt.Println(p)       // Imprime o endereço de memória de a
    fmt.Println(*p)      // Acessa o valor de a através do ponteiro p
}

PONTEIROS EM GO

Quando Usar Ponteiros?

  • Para alterar o valor da variável original em funções: Se uma função recebe uma cópia de uma variável, qualquer alteração feita dentro da função não afeta a variável original. Passando um ponteiro, a função pode modificar a variável original.

 

func alterarValor(num *int) {
    *num = *num + 10 // Modifica o valor da variável apontada
}

func executarAlteraValor() {
    x := 20
    alterarValor(&x)       // Passamos o endereço de x
    fmt.Println(x)         // Resultado: 30 (x foi alterado)
}

PONTEIROS EM GO

STRUCT EM GO

O que é uma Struct?
Em Go, uma struct (estrutura) é um tipo de dado composto que permite agrupar variáveis de diferentes tipos em uma única unidade lógica. Essas variáveis são chamadas de campos da struct. As structs são muito úteis para organizar dados relacionados em uma única estrutura, como dados de uma pessoa, um produto, um carro, etc. São semelhantes a "objetos" em outras linguagens, mas sem herança.

STRUCT EM GO

Declaração de Structs: Para definir uma struct, usamos a palavra-chave type para nomeá-la, seguida de struct, e depois definimos seus campos. 

  • Pessoa é o nome da struct.
  • Nome, Idade, e Cidade são campos da struct com tipos string e int.

 

package main

type Pessoa struct {
    Nome   string
    Idade  int
    Cidade string
}

STRUCT EM GO

Criando e Usando Instâncias de Struct: Podemos criar uma instância da struct e atribuir valores aos seus campos.

func mainStruct() {

	// Criando uma instância de Pessoa e definindo valores.
	pessoa := Pessoa{
		Nome:   "Vanilton",
		Idade:  34,
		Cidade: "Manaus",
	}

	fmt.Println(pessoa)                // Output: {Vanilton 34 Manaus}
	fmt.Println("Nome: ", pessoa.Nome) // Output: Nome:  Vanilton
}


STRUCT EM GO

Acessando e Modificando Campos: Para acessar ou modificar um campo, usamos a notação ponto (.) seguido pelo nome do campo.

pessoa.Idade = 31
pessoa.Cidade = "Manaus"
fmt.Println("Nova idade:", pessoa.Idade)
fmt.Println("Nova cidade:", pessoa.Cidade)

Funções com Structs: Podemos passar structs para funções e manipular seus campos. Para evitar a cópia dos dados, é comum passar o ponteiro da struct para a função.

 

func atualizarIdade(p *Pessoa, novaIdade int) { 
	p.Idade = novaIdade // Modifica o campo Idade da struct
}	

STRUCT EM GO

Structs Aninhadas: Uma struct pode conter outras structs como campos, permitindo construir estruturas de dados mais complexas.

type Endereco struct {
    Rua    string
    Numero int
    Cidade string
}

type Pessoa struct {
    Nome     string
    Idade    int
    Endereco Endereco
}
// Criando uma instância de Pessoa e definindo valores
pessoa := Pessoa{
    Nome: "Ana",
    Idade: 28,
    Endereco: Endereco{
        Rua: "Rua das Flores",
        Numero: 123,
        Cidade: "Rio de Janeiro",
    },
}

fmt.Println(pessoa)
fmt.Println("Nome:", pessoa.Nome)
fmt.Println("Cidade:", pessoa.Endereco.Cidade)

STRUCT EM GO

Modificando um campo do tipo struct aninhado.

// Modificando cidade na struct endereco
pessoa.Endereco.Cidade = "Salvador"
fmt.Println("Nova cidade:", pessoa.Endereco.Cidade)

EXERCÍCIO DE FIXAÇÃO

Criar uma aplicação que armazena dados de livros usando structs e manipula essas informações.


Instruções:

  • Crie uma struct Livro com os seguintes campos: Titulo (string), Autor (string), AnoPublicacao (int), Disponivel (bool);
  • Implemente funções para:
    • Adicionar Livro: Receber as informações de um livro e adicioná-lo a uma lista de livros.
    • Listar Livros: Exibir todos os livros cadastrados com seus detalhes.
    • Editar Disponibilidade: Alterar a disponibilidade de um livro específico (marcá-lo como disponível ou não disponível).
  • Menu: disponibilizar as opções do sistema até o usuário sair do sistema (utilizar um loop)

EXCEÇÕES

Em Go, não existem exceções no estilo tradicional como em linguagens como Java, Python ou C#. Em vez disso, Go utiliza um sistema explícito de tratamento de erros baseado em valores de retorno e, em situações mais críticas, a função panic.

O que são exceções?

Exceções são eventos que ocorrem durante a execução de um programa que interrompem o fluxo normal do código. Elas podem ser causadas por uma variedade de problemas, como tentar acessar um índice inexistente em uma lista, dividir por zero, abrir um arquivo que não existe, entre outros.​

EXCEÇÕES

Retorno explícito de erro

Funções em Go normalmente retornam dois valores: o resultado esperado e um valor do tipo error. O código do consumidor verifica se o erro é nil.

EXCEÇÕES

package main

import (
    "errors"
    "fmt"
)

func dividir(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("divisão por zero não permitida")
    }
    return a / b, nil
}

func main() {
    resultado, err := dividir(10, 0)
    if err != nil {
        fmt.Println("Erro:", err)
        return
    }
    fmt.Println("Resultado:", resultado)
}

Panic e Recover

Use panic para situações inesperadas ou irreversíveis, e recover para capturar um panic e evitar que o programa encerre abruptamente.

EXCEÇÕES

package main

import "fmt"

func podeEntrarEmPanico() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recuperado do panic:", r)
        }
    }()

    panic("algo deu muito errado")
}

func main() {
    podeEntrarEmPanico()
    fmt.Println("Continuando execução após recover")
}

EXCEÇÕES

package main

import (
    "errors"
    "fmt"
)

// Struct Endereco
type Endereco struct {
    Rua    string
    Numero int
    Cidade string
}

// Struct Pessoa
type Pessoa struct {
    Nome     string
    Idade    int
    Endereco Endereco
}
func main() {
    // Criando pessoa com erro de idade
    pessoa := Pessoa{
        Nome:  "Ana",
        Idade: -5,
        Endereco: Endereco{
            Rua:    "Rua das Flores",
            Numero: 123,
            Cidade: "Salvador",
        },
    }

    // Tratamento de erro com if
    if err := verificarIdade(pessoa); err != nil {
        fmt.Println("Erro ao verificar idade:", err)
    } else {
        fmt.Println("Idade válida:", pessoa.Idade)
    }

    // Teste com panic/recover
    pessoa.Endereco.Cidade = "" // Vai causar panic
    operacaoCritica(pessoa)

    fmt.Println("Programa continua após recover.")
}
// Função que verifica idade válida
func verificarIdade(p Pessoa) error {
    if p.Idade < 0 {
        return errors.New("idade inválida: não pode ser negativa")
    }
    return nil
}

// Função que simula algo crítico
func operacaoCritica(p Pessoa) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recuperado de um panic:", r)
        }
    }()

    if p.Endereco.Cidade == "" {
        panic("cidade não pode estar vazia")
    }

    fmt.Println("Operação crítica realizada com sucesso")
}

EXCEÇÕES

Resumindo:

  • Use error para erros esperados (ex: erro de validação, falha de rede).
  • Use panic apenas para erros inesperados ou falhas de programação (ex: violação de invariantes).
  • Sempre trate o erro retornado. Ignorar erros em Go é possível com _, mas não recomendado.
valor, _ := dividir(10, 2)
fmt.Println("Resultado:", valor)

REFERÊNCIAS

FPFtech Escola Tecnológica - Linguage de Programação - GO

By Vanilton Pinheiro

FPFtech Escola Tecnológica - Linguage de Programação - GO

Apresentar aos alunos os conceitos de linguagens de programação e seus ecossistemas, a aplicação de conceitos de lógica de programação em linguagens de programação, bem como mostrar no mínimo o funcionamento de 2 linguagens de programação para os discentes.

  • 297