Janeiro 2026 · ~16 min

Sintaxe Go: Variáveis, Tipos, Funções e Structs

Aprenda sintaxe Go com exemplos: variáveis, tipos, arrays, slices, maps, funções, structs, métodos, conversões e regras do operador :=.

Resposta rápida: a sintaxe de Go prioriza poucas regras e código explícito. Dentro de funções, nome := "Ana" declara uma variável com tipo inferido; var total int declara um int com valor zero; funções começam com func; dados compostos usam struct; coleções do dia a dia usam []T (slice) e map[K]V. Go não tem classes nem conversões numéricas implícitas.

Neste segundo artigo da série Golang para Iniciantes, você aprenderá variáveis, constantes, tipos, arrays, slices, maps, funções, structs, métodos e conversões com exemplos que podem ser copiados e executados. Para consulta rápida, use esta tabela:

ObjetivoSintaxe Go
Declarar com inferêncianome := "Ana"
Declarar com tipovar idade int
Criar constanteconst timeout = 5
Criar slicenums := []int{1, 2, 3}
Criar mapidades := map[string]int{"Ana": 30}
Criar funçãofunc somar(a, b int) int
Criar structtype Pessoa struct { Nome string }
Tratar erroif err != nil { ... }

Se ainda não instalou a linguagem ou não executou seu primeiro programa, comece por Golang para iniciantes: primeiros passos. Para acompanhar exemplos pela referência oficial, veja também o guia de documentação Go em português.

Variáveis em Go

Go oferece várias formas de declarar variáveis, desde a forma explícita até a inferência de tipos.

Declaração Explícita com var

A forma tradicional de declarar variáveis:

package main

import "fmt"

func main() {
    // Declaração explícita: var nome tipo = valor
    var nome string = "João"
    var idade int = 30
    var salario float64 = 5000.50
    var ativo bool = true

    fmt.Printf("Nome: %s, Idade: %d, Salário: %.2f, Ativo: %t\n",
        nome, idade, salario, ativo)
}

Declaração com Inferência de Tipo

Go pode inferir o tipo automaticamente:

package main

import "fmt"

func main() {
    // Inferência de tipo: var nome = valor (tipo inferido)
    var nome = "João"      // string
    var idade = 30         // int
    var preco = 99.99      // float64
    var online = true      // bool

    fmt.Printf("Tipo de nome: %T\n", nome)    // string
    fmt.Printf("Tipo de idade: %T\n", idade)  // int
}

Declaração Curta com :=

A forma mais comum no dia a dia — apenas dentro de funções:

package main

import "fmt"

func main() {
    // Forma curta: nome := valor (só funciona dentro de funções)
    nome := "João"
    idade := 30
    pi := 3.14159

    fmt.Println(nome, idade, pi)
}

⚠️ Importante: O operador := só pode ser usado dentro de funções. Fora de funções (escopo de pacote), use var.

Declaração Múltipla

Declare várias variáveis de uma vez:

package main

import "fmt"

func main() {
    // Múltiplas variáveis do mesmo tipo
    var x, y, z int = 1, 2, 3

    // Múltiplas variáveis com tipos diferentes
    var (
        nome    string = "Maria"
        idade   int    = 25
        ativo   bool   = true
    )

    // Com inferência
    a, b, c := 1, 2.5, "texto"

    fmt.Println(x, y, z, nome, idade, ativo)
    fmt.Println(a, b, c)
}

Variáveis Não Inicializadas

Em Go, variáveis sempre têm um “zero value”:

package main

import "fmt"

func main() {
    var numero int       // 0
    var texto string     // "" (string vazia)
    var booleano bool    // false
    var ponteiro *int    // nil

    fmt.Printf("int: %d, string: %q, bool: %t, ponteiro: %v\n",
        numero, texto, booleano, ponteiro)
}

Zero values padrão:

TipoZero Value
int, float0, 0.0
string"" (vazia)
boolfalse
pointer, slice, map, channel, interfacenil
structCampos com seus zero values

Constantes com const

Valores que não podem ser alterados:

package main

import "fmt"

func main() {
    // Constantes
    const pi = 3.14159
    const versao = "1.0.0"
    const maxUsuarios = 100

    // Constantes agrupadas
    const (
        Segunda = 1
        Terca   = 2
        Quarta  = 3
        Quinta  = 4
        Sexta   = 5
    )

    fmt.Println("PI:", pi)
    fmt.Println("Dias úteis:", Segunda, Terca, Quarta, Quinta, Sexta)
}

Iota — gerador de constantes incrementais:

package main

import "fmt"

func main() {
    const (
        Domingo = iota  // 0
        Segunda         // 1
        Terca           // 2
        Quarta          // 3
        Quinta          // 4
        Sexta           // 5
        Sabado          // 6
    )

    fmt.Println("Segunda:", Segunda)  // 1
}

Tipos de Dados em Go

Go é uma linguagem estaticamente tipada com tipos básicos claros.

Tipos Numéricos

package main

import "fmt"

func main() {
    // Inteiros
    var inteiro int = 42           // Plataforma-dependente (32 ou 64 bits)
    var int8bit int8 = 127         // -128 a 127
    var int16bit int16 = 32767     // -32768 a 32767
    var int32bit int32 = 2147483647
    var int64bit int64 = 9223372036854775807

    // Inteiros sem sinal (unsigned)
    var uint8bit uint8 = 255       // 0 a 255
    var uint16bit uint16 = 65535
    var uint32bit uint32 = 4294967295
    var uint64bit uint64 = 18446744073709551615

    // Ponto flutuante
    var flutuante32 float32 = 3.14159
    var flutuante64 float64 = 3.141592653589793

    // Números complexos (raramente usados)
    var complexo complex64 = 1 + 2i
    var complexo128 complex128 = 1 + 2i

    fmt.Printf("int: %d (tipo: %T)\n", inteiro, inteiro)
    fmt.Printf("float64: %f (tipo: %T)\n", flutuante64, flutuante64)
}

Dica: Use int para inteiros gerais e float64 para ponto flutuante, a menos que tenha requisitos específicos de memória.

Strings

Strings em Go são sequências imutáveis de bytes:

package main

import "fmt"

func main() {
    // Declaração de strings
    saudacao := "Olá, Mundo!"
    citacao := `Esta é uma string
    com múltiplas linhas
    e "aspas" não precisam ser escapadas`

    // Concatenação
    nome := "João"
    sobrenome := "Silva"
    nomeCompleto := nome + " " + sobrenome

    // Tamanho
    tamanho := len(saudacao)

    // Acesso a caracteres (retorna byte)
    primeiro := saudacao[0]  // 'O' (byte)

    fmt.Println(nomeCompleto)
    fmt.Println("Tamanho:", tamanho)
    fmt.Printf("Primeiro caractere: %c\n", primeiro)

    // String como slice de bytes
    for i, c := range saudacao {
        fmt.Printf("Índice %d: %c\n", i, c)
    }
}

Booleanos

package main

import "fmt"

func main() {
    var ativo bool = true
    inativo := false

    // Operações lógicas
    resultado1 := ativo && inativo  // AND: false
    resultado2 := ativo || inativo  // OR: true
    resultado3 := !ativo            // NOT: false

    fmt.Println(resultado1, resultado2, resultado3)
}

Arrays, slices e maps

Estas são as coleções fundamentais da sintaxe Go. Arrays têm tamanho fixo; slices representam sequências flexíveis; maps associam chaves a valores.

Arrays: tamanho faz parte do tipo

package main

import "fmt"

func main() {
    notas := [3]float64{8.5, 9.0, 7.5}
    fmt.Println(notas[0])
    fmt.Println("quantidade:", len(notas))
}

[3]float64 e [4]float64 são tipos diferentes. Arrays são úteis quando o tamanho fixo faz parte do modelo, mas slices aparecem com mais frequência em funções e aplicações.

Slices: a coleção mais usada

package main

import "fmt"

func main() {
    linguagens := []string{"Go", "Python"}
    linguagens = append(linguagens, "Java")

    for indice, linguagem := range linguagens {
        fmt.Printf("%d: %s\n", indice, linguagem)
    }
}

O tipo []string não inclui comprimento fixo. append devolve o slice atualizado e pode alocar um array subjacente novo, portanto guarde o retorno. Para reservar capacidade quando você conhece o volume aproximado:

ids := make([]int, 0, 100)
ids = append(ids, 10, 20, 30)

Um slice nil tem comprimento zero e normalmente pode receber append. Porém, um slice vazio e um slice nil podem ser serializados de formas diferentes por algumas APIs, então defina o contrato JSON conscientemente. A cheatsheet de slices, maps e structs aprofunda cópia, capacidade e operações comuns.

Maps: chaves e valores

package main

import "fmt"

func main() {
    idades := map[string]int{
        "Ana":  30,
        "Bruno": 27,
    }

    idades["Carla"] = 25

    idade, existe := idades["Ana"]
    if existe {
        fmt.Println("Ana:", idade)
    }

    delete(idades, "Bruno")
}

A leitura de uma chave ausente retorna o zero value do tipo. Use a forma valor, existe := mapa[chave] quando precisar distinguir “ausente” de um valor zero legítimo. Um map nil pode ser lido, mas escrever nele causa panic; inicialize com literal ou make(map[K]V) antes de inserir.

Slices e maps carregam referências para estruturas internas. Ao passá-los para uma função, ela pode observar ou alterar elementos compartilhados. Isso é diferente de copiar um array ou uma struct por valor e é importante ao projetar APIs.

Operadores

Operadores Aritméticos

package main

import "fmt"

func main() {
    a, b := 10, 3

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

    // Incremento e decremento (somente como statements)
    a++  // a = a + 1
    b--  // b = b - 1
}

Nota: Go não tem operadores de pré/pós-incremento como expressões (++a ou --b não retornam valores).

Operadores de Comparação

package main

import "fmt"

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

    fmt.Println("Igual:", x == y)      // false
    fmt.Println("Diferente:", x != y)  // true
    fmt.Println("Maior:", x > y)       // false
    fmt.Println("Menor:", x < y)       // true
    fmt.Println("Maior ou igual:", x >= y) // false
    fmt.Println("Menor ou igual:", x <= y) // true
}

Funções

Funções são cidadãs de primeira classe em Go.

Declaração Básica

package main

import "fmt"

// Função simples
func saudar(nome string) {
    fmt.Printf("Olá, %s!\n", nome)
}

// Função com retorno
func somar(a, b int) int {
    return a + b
}

// Função com múltiplos parâmetros do mesmo tipo
func calcularArea(largura, altura float64) float64 {
    return largura * altura
}

func main() {
    saudar("Maria")
    resultado := somar(10, 20)
    area := calcularArea(5.0, 3.0)

    fmt.Println("Soma:", resultado)
    fmt.Println("Área:", area)
}

Múltiplos Retornos

Uma característica poderosa de Go:

package main

import "fmt"

// Retorna quociente e resto
func dividir(dividendo, divisor int) (int, int) {
    quociente := dividendo / divisor
    resto := dividendo % divisor
    return quociente, resto
}

// Retorna resultado e erro (padrão idiomático)
func dividirSeguro(dividendo, divisor float64) (float64, error) {
    if divisor == 0 {
        return 0, fmt.Errorf("divisão por zero")
    }
    return dividendo / divisor, nil
}

func main() {
    // Ignorando um retorno com _
    q, _ := dividir(17, 5)
    fmt.Println("Quociente:", q)

    q2, r := dividir(17, 5)
    fmt.Printf("%d dividido por %d = %d, resto %d\n", 17, 5, q2, r)

    // Tratando erro
    resultado, err := dividirSeguro(10.0, 0.0)
    if err != nil {
        fmt.Println("Erro:", err)
    } else {
        fmt.Println("Resultado:", resultado)
    }
}

Named Return Values

Retornos nomeados tornam o código mais claro:

package main

import "fmt"

// Retornos nomeados
func calcularStats(numeros []int) (min, max, media int) {
    if len(numeros) == 0 {
        return 0, 0, 0  // Retorna zero values
    }

    min = numeros[0]
    max = numeros[0]
    soma := 0

    for _, n := range numeros {
        if n < min {
            min = n
        }
        if n > max {
            max = n
        }
        soma += n
    }

    media = soma / len(numeros)
    return  // Retorna min, max, media automaticamente
}

func main() {
    nums := []int{5, 2, 8, 1, 9}
    minimo, maximo, media := calcularStats(nums)
    fmt.Printf("Min: %d, Max: %d, Média: %d\n", minimo, maximo, media)
}

Funções Variádicas

Aceitam número variável de argumentos:

package main

import "fmt"

// Função variádica
func somarTudo(numeros ...int) int {
    total := 0
    for _, n := range numeros {
        total += n
    }
    return total
}

func main() {
    fmt.Println(somarTudo(1, 2, 3))       // 6
    fmt.Println(somarTudo(10, 20))        // 30
    fmt.Println(somarTudo())              // 0

    // Passando slice com ...
    nums := []int{1, 2, 3, 4, 5}
    fmt.Println(somarTudo(nums...))       // 15
}

Funções Anônimas e Closures

package main

import "fmt"

func main() {
    // Função anônima atribuída a variável
    dobro := func(x int) int {
        return x * 2
    }

    fmt.Println(dobro(5))  // 10

    // Closure (função que captura variáveis do escopo)
    contador := func() func() int {
        count := 0
        return func() int {
            count++
            return count
        }
    }()

    fmt.Println(contador())  // 1
    fmt.Println(contador())  // 2
    fmt.Println(contador())  // 3
}

Structs (Estruturas)

Structs agrupam campos relacionados:

Declaração e Uso

package main

import "fmt"

type Pessoa struct {
    Nome    string
    Idade   int
    Email   string
    Ativo   bool
}

func main() {
    // Criação de instância
    p1 := Pessoa{
        Nome:  "João Silva",
        Idade: 30,
        Email: "[email protected]",
        Ativo: true,
    }

    // Forma curta (ordem dos campos)
    p2 := Pessoa{"Maria Santos", 25, "[email protected]", true}

    // Struct parcial (campos omitidos ficam com zero value)
    p3 := Pessoa{
        Nome: "Pedro",
    }

    // Acesso aos campos
    fmt.Println("Nome:", p1.Nome)
    fmt.Println("Idade:", p1.Idade)

    // Modificação
    p1.Idade = 31
    fmt.Println("Nova idade:", p1.Idade)

    fmt.Printf("Pessoa 2: %+v\n", p2)
    fmt.Printf("Pessoa 3: %+v\n", p3)
}

Structs Aninhados

package main

import "fmt"

type Endereco struct {
    Rua     string
    Cidade  string
    Estado  string
    CEP     string
}

type Pessoa struct {
    Nome     string
    Idade    int
    Endereco Endereco  // Struct aninhado
}

func main() {
    pessoa := Pessoa{
        Nome:  "Ana Paula",
        Idade: 28,
        Endereco: Endereco{
            Rua:    "Av. Brasil, 123",
            Cidade: "São Paulo",
            Estado: "SP",
            CEP:    "01000-000",
        },
    }

    fmt.Printf("%s mora em %s, %s\n",
        pessoa.Nome,
        pessoa.Endereco.Cidade,
        pessoa.Endereco.Estado)
}

Ponteiros para Structs

package main

import "fmt"

type Pessoa struct {
    Nome  string
    Idade int
}

// Recebe ponteiro para modificar o original
func fazerAniversario(p *Pessoa) {
    p.Idade++  // Não precisa de (*p).Idade, Go faz automaticamente
}

func main() {
    p := Pessoa{"João", 30}

    fmt.Println("Antes:", p.Idade)  // 30

    fazerAniversario(&p)

    fmt.Println("Depois:", p.Idade)  // 31
}

Métodos

Métodos são funções associadas a tipos (especialmente structs):

package main

import "fmt"

type Retangulo struct {
    Largura  float64
    Altura   float64
}

// Método com receiver por valor (não modifica o original)
func (r Retangulo) Area() float64 {
    return r.Largura * r.Altura
}

// Método com receiver por ponteiro (pode modificar o original)
func (r *Retangulo) Escalar(fator float64) {
    r.Largura *= fator
    r.Altura *= fator
}

// Método com retorno formatado
func (r Retangulo) String() string {
    return fmt.Sprintf("Retângulo %.1f x %.1f", r.Largura, r.Altura)
}

func main() {
    ret := Retangulo{Largura: 10, Altura: 5}

    fmt.Println(ret.String())        // Retângulo 10.0 x 5.0
    fmt.Println("Área:", ret.Area()) // 50

    ret.Escalar(2)
    fmt.Println("Após escalar:", ret.String()) // Retângulo 20.0 x 10.0
}

Quando Usar Ponteiro vs Valor?

Use valor (r Retangulo) quando…Use ponteiro (r *Retangulo) quando…
O método não precisa modificar o receiverO método precisa modificar o receiver
O tipo é pequeno e sua cópia é intencionalCopiar o tipo seria caro ou incorreto
O valor se comporta naturalmente como imutávelOutros métodos do mesmo tipo já usam ponteiro

Usar receiver por valor não torna o código automaticamente seguro para concorrência. Se a struct contém maps, slices, ponteiros ou outro estado compartilhado, as estruturas internas ainda podem ser compartilhadas. Mantenha consistência entre os métodos do tipo e use sincronização explícita quando várias goroutines acessarem estado mutável.

Type Conversion (Conversão de Tipos)

Go não faz conversão implícita — você deve converter explicitamente:

package main

import "fmt"
import "strconv"

func main() {
    // Entre tipos numéricos
    var i int = 42
    var f float64 = float64(i)  // Conversão explícita obrigatória
    var u uint = uint(i)

    // String para número
    numStr := "123"
    num, _ := strconv.Atoi(numStr)  // string → int
    num64, _ := strconv.ParseInt(numStr, 10, 64)

    // Número para string
    str := strconv.Itoa(num)        // int → string
    strf := strconv.FormatFloat(3.14, 'f', 2, 64)

    // String para bytes e vice-versa
    texto := "Olá"
    bytes := []byte(texto)
    texto2 := string(bytes)

    fmt.Printf("int: %d, float64: %f, uint: %d\n", i, f, u)
    fmt.Printf("Número: %d, String: %s\n", num, str)
    fmt.Println(texto2)
}

Exercícios Práticos

Exercício 1: Calculadora de IMC

Crie uma função que calcula o IMC (Índice de Massa Corporal) dados peso e altura.

Ver solução
package main

import "fmt"

func calcularIMC(peso, altura float64) float64 {
    return peso / (altura * altura)
}

func classificarIMC(imc float64) string {
    switch {
    case imc < 18.5:
        return "Abaixo do peso"
    case imc < 25:
        return "Peso normal"
    case imc < 30:
        return "Sobrepeso"
    default:
        return "Obesidade"
    }
}

func main() {
    peso := 70.0
    altura := 1.75

    imc := calcularIMC(peso, altura)
    classificacao := classificarIMC(imc)

    fmt.Printf("IMC: %.2f - %s\n", imc, classificacao)
}

Exercício 2: Sistema de Biblioteca

Crie um sistema simples de biblioteca com struct Livro e métodos para emprestar e devolver.

Ver solução
package main

import "fmt"

type Livro struct {
    Titulo    string
    Autor     string
    Emprestado bool
}

func (l *Livro) Emprestar() error {
    if l.Emprestado {
        return fmt.Errorf("livro já está emprestado")
    }
    l.Emprestado = true
    return nil
}

func (l *Livro) Devolver() error {
    if !l.Emprestado {
        return fmt.Errorf("livro não estava emprestado")
    }
    l.Emprestado = false
    return nil
}

func (l Livro) String() string {
    status := "Disponível"
    if l.Emprestado {
        status = "Emprestado"
    }
    return fmt.Sprintf("%s (por %s) - %s", l.Titulo, l.Autor, status)
}

func main() {
    livro := Livro{Titulo: "O Senhor dos Anéis", Autor: "J.R.R. Tolkien"}

    fmt.Println(livro)

    if err := livro.Emprestar(); err != nil {
        fmt.Println("Erro:", err)
    } else {
        fmt.Println("Livro emprestado com sucesso!")
    }

    fmt.Println(livro)
}

Exercício 3: Gerenciador de Tarefas

Implemente um gerenciador de tarefas com structs e funções para adicionar, listar e completar tarefas.

Ver solução
package main

import "fmt"
import "time"

type Tarefa struct {
    ID        int
    Titulo    string
    Completa  bool
    CriadaEm  time.Time
}

type GerenciadorTarefas struct {
    tarefas []Tarefa
    proxID  int
}

func (gt *GerenciadorTarefas) Adicionar(titulo string) Tarefa {
    tarefa := Tarefa{
        ID:       gt.proxID,
        Titulo:   titulo,
        Completa: false,
        CriadaEm: time.Now(),
    }
    gt.tarefas = append(gt.tarefas, tarefa)
    gt.proxID++
    return tarefa
}

func (gt *GerenciadorTarefas) Completar(id int) bool {
    for i := range gt.tarefas {
        if gt.tarefas[i].ID == id {
            gt.tarefas[i].Completa = true
            return true
        }
    }
    return false
}

func (gt GerenciadorTarefas) ListarPendentes() []Tarefa {
    var pendentes []Tarefa
    for _, t := range gt.tarefas {
        if !t.Completa {
            pendentes = append(pendentes, t)
        }
    }
    return pendentes
}

func main() {
    gt := GerenciadorTarefas{}

    gt.Adicionar("Estudar Go")
    gt.Adicionar("Fazer exercícios")
    gt.Adicionar("Ler documentação")

    gt.Completar(0)

    fmt.Println("Tarefas pendentes:")
    for _, t := range gt.ListarPendentes() {
        fmt.Printf("- %s\n", t.Titulo)
    }
}

Dicas e Melhores Práticas

1. Nomenclatura

  • Use nomes curtos e claros no menor escopo possível: i, err, cliente.
  • Nomes que começam com maiúscula são exportados pelo pacote: Cliente, Calcular.
  • Nomes que começam com minúscula ficam internos ao pacote: cliente, calcular.
  • Prefira MaxSize ou maxSize; Go normalmente não usa SCREAMING_SNAKE_CASE.
  • Siglas mantêm capitalização consistente: HTTPClient, userID, ServeHTTP.
const maxSize = 100   // Constante interna ao pacote
const MaxRetries = 3  // Constante exportada
var contador = 0      // Variável interna
func calcular() {}    // Função interna
func Calcular() {}    // Função exportada

Rode go fmt ./... para formatação e use nomes que façam sentido no pacote. O guia Effective Go e o Code Review Comments são boas referências de estilo.

2. Zero Values são Seus Amigos

Aproveite que Go inicializa variáveis automaticamente:

// Bom: aproveita zero values
var contador int  // Começa em 0
var encontrado bool // Começa em false

// Ruim: inicialização desnecessária
contador := 0
encontrado := false

3. Evite Variáveis Globais

Prefira passar dependências como parâmetros:

// Ruim: variável global
var db *sql.DB

func main() {
    db = conectarDB()
}

// Bom: injeção de dependência
func main() {
    db := conectarDB()
    handler := NewHandler(db)
}

4. Trate Erros Explicitamente

Go não tem exceções — verifique erros:

// Ruim: ignorando erro
file, _ := os.Open("dados.txt")

// Bom: tratando erro
file, err := os.Open("dados.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

Próximos Passos

Parabéns! Você domina agora os fundamentos da sintaxe de Go. Continue sua jornada:

Próximo Artigo da Série

📖 Controle de fluxo em Go: if, switch e loops → — aprenda a controlar a execução com condicionais e repetição.

Recursos Recomendados

Carreira Go

Desafios

  1. Crie uma calculadora completa com operações básicas
  2. Implemente um jogo da forca em linha de comando
  3. Crie um sistema de cadastro de produtos

Artigo anterior: Golang para iniciantes: primeiros passos ←

Próximo artigo: Controle de fluxo em Go: if, switch e loops →


Última atualização: agosto de 2026

Exemplos compatíveis com Go moderno; versão de referência do site: Go 1.26.

Perguntas frequentes

Como declarar uma variável em Go?

Dentro de uma função, use nome := valor quando o tipo puder ser inferido. Use var nome tipo quando precisar declarar sem valor inicial, controlar o tipo ou declarar no escopo do pacote. O operador := não funciona fora de funções.

Qual é a diferença entre array e slice em Go?

Um array tem tamanho fixo e o comprimento faz parte do tipo, como [3]int. Um slice, como []int, é uma visão flexível sobre um array e pode crescer com append; por isso slices são mais comuns em aplicações Go.

Go tem classes?

Não. Go combina structs para armazenar dados, métodos para definir comportamento e interfaces para representar contratos. Composição é preferida a herança.

Go faz conversão automática entre tipos numéricos?

Não. Conversões entre tipos numéricos precisam ser explícitas, como float64(valor). Ao converter para um tipo menor, confira limites porque o valor pode ser truncado.

O que significa := em Go?

O operador := faz uma declaração curta: cria pelo menos uma variável nova e infere seu tipo a partir do valor. Ele só pode ser usado dentro de funções; para atribuir depois, use =.