← Voltar para o blog

Projetos em Go para Portfólio: Ideias para Conquistar Sua Vaga

Projetos em Go para portfólio que realmente impressionam recrutadores: API REST com testes e Docker, worker pool, gRPC, CLI com cobra e cache Redis. Ideias para a primeira vaga em 2026.

A pergunta mais comum de quem busca a primeira vaga em Go não é “qual framework aprender”. É “o que eu coloco no portfólio?”. E a resposta que mais ajuda não é uma lista de ideias genéricas — é entender o que um projeto precisa demonstrar para que um recrutador ou um engenheiro sênior pense: “essa pessoa sabe levar um serviço até o fim”.

O mercado brasileiro de Go aparece muito em empresas com produto em produção: fintech, pagamentos, logística, plataformas internas, microsserviços e infraestrutura. Por isso, o portfólio ideal não é uma coleção de tutoriais copiados. É um sistema pequeno, porém completo, que se parece com trabalho real. Este guia mostra cinco projetos em Go para portfólio que sustentam uma conversa técnica de verdade em 2026, com o que cada um demonstra, a stack envolvida e como estruturar o repositório. Se você está começando do zero, vale seguir antes o Roadmap Go 2026 para não pular etapas.

O que um projeto de portfólio Go precisa demonstrar

Antes de escolher a ideia, entenda os sinais que um avaliador procura. Um bom projeto mostra, ao mesmo tempo, alguns destes pontos:

  • Ciclo completo de um serviço: receber uma requisição HTTP, validar dados, persistir em banco, responder de forma padronizada e tratar erros sem esconder falhas.
  • Banco de dados real: PostgreSQL com migrations, e não só um map em memória.
  • Testes: ao menos testes de tabela cobrindo os caminhos felizes e os de erro.
  • Empacotamento: Dockerfile enxuto e um comando para rodar tudo.
  • Decisões explicadas: um README que diz o quê e por quê.
  • Concorrência consciente: quando fizer sentido, goroutines, channels e context com cancelamento.

Note que “saber o framework da moda” não está na lista. O que transfere entre empresas e entre frameworks é o domínio de net/http, context, tratamento de erro, testes e padrões de produção. O guia de Go para backend aprofunda esses fundamentos.

Projeto 1: API REST com autenticação, testes e Docker

É o projeto-base. Se você só tiver tempo para um, faça este. A proposta é construir uma API REST pequena (um gerenciador de tarefas, um controle financeiro pessoal, um agregador de vagas) com autenticação, persistência em PostgreSQL, testes e um Dockerfile.

O que ela demonstra: roteamento, validação de entrada, tratamento de erro padronizado, uso de PostgreSQL com Go, migrations e testes de tabela. Para a autenticação, JWT é um padrão de mercado; o tutorial de autenticação em APIs Go cobre o caminho.

Um esboço de handler com tratamento de erro explícito:

package main

import (
	"encoding/json"
	"errors"
	"net/http"
	"strconv"
)

type Servico struct {
	repo *Repositorio
}

func (s *Servico) CriarTarefa(w http.ResponseWriter, r *http.Request) {
	var entrada struct {
		Titulo string `json:"titulo"`
	}
	if err := json.NewDecoder(r.Body).Decode(&entrada); err != nil {
		 responderErro(w, http.StatusBadRequest, "payload inválido")
		return
	}
	if entrada.Titulo == "" {
		 responderErro(w, http.StatusBadRequest, "título é obrigatório")
		return
	}
	tarefa, err := s.repo.Criar(r.Context(), entrada.Titulo)
	if err != nil {
		 responderErro(w, http.StatusInternalServerError, "falha ao salvar")
		return
	}
	responderJSON(w, http.StatusCreated, tarefa)
}

// responderErro e responderJSON centralizam o formato de resposta.
func responderJSON(w http.ResponseWriter, status int, corpo any) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	_ = json.NewEncoder(w).Encode(corpo)
}

func responderErro(w http.ResponseWriter, status int, msg string) {
	responderJSON(w, status, map[string]string{"erro": msg})
}

var _ = errors.New
var _ = strconv.Atoi

Atenção: o trecho acima é um esqueleto para ilustrar o padrão de handler com erro centralizado. A classe Repositorio e a conexão com o banco ficam por sua conta — veja o tutorial de API REST com Go para a versão completa, e a série de API REST com Gin se preferir framework.

Dica de ouro: padronize as respostas de erro. Misturar {"erro": "..."} em uma rota com {"message": "..."} em outra passa o sinal de que o código não tem convenção — e isso aparece em code review.

Projeto 2: Worker pool com fila de processamento assíncrono

Esse projeto separa o seu portfólio de quem só fez CRUD. A ideia: um serviço que recebe jobs (processar uma imagem, enviar um e-mail, gerar um relatório) e executa em background com um número controlado de workers, usando concorrência de verdade.

O que demonstra: goroutines, channels, context com cancelamento e timeout, graceful shutdown (não derrubar jobs no meio quando o processo morre) e noções de fila. O guia de worker pool em Go mostra a estrutura completa; o artigo sobre channels em Go aprofunda a comunicação entre goroutines.

Um padrão compacto de worker pool com cancelamento via contexto:

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

type Job struct {
	ID int
}

func worker(ctx context.Context, jobs <-chan Job, wg *sync.WaitGroup) {
	defer wg.Done()
	for j := range jobs {
		select {
		case <-ctx.Done():
			return // contexto cancelado: pare de forma limpa
		default:
			processar(ctx, j)
		}
	}
}

func processar(ctx context.Context, j Job) {
	// simula trabalho respeitando o contexto
	select {
	case <-time.After(200 * time.Millisecond):
		fmt.Printf("job %d concluído\n", j.ID)
	case <-ctx.Done():
		fmt.Printf("job %d interrompido\n", j.ID)
	}
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	jobs := make(chan Job, 10)
	var wg sync.WaitGroup

	for w := 0; w < 3; w++ {
		wg.Add(1)
		go worker(ctx, jobs, &wg)
	}

	for i := 0; i < 5; i++ {
		jobs <- Job{ID: i}
	}
	close(jobs)
	wg.Wait()
}

Para subir o nível, troque o channel em memória por uma fila real: Redis Streams, SQS na AWS ou RabbitMQ. Isso mostra que você entende filas distribuídas, e não só concorrência dentro de um processo.

Projeto 3: Serviço gRPC ou gateway com observabilidade

Go brilha em comunicação entre serviços internos, e gRPC é o padrão para isso. Um projeto forte é um serviço gRPC (definido em Protobuf) que expõe algumas operações, instrumentado com tracing e métricas. Alternativamente, um gateway HTTP que chama um serviço gRPC interno.

O que demonstra: gRPC com Protobuf, definição de contratos, observabilidade com OpenTelemetry (traces distribuídos) e a diferença entre APIs internas (gRPC) e externas (HTTP/JSON). É um diferencial que aparece muito em vagas de microsserviços e plataformas.

Mesmo sem gRPC, você pode adicionar observabilidade ao Projeto 1: instrumentar a API REST com OpenTelemetry e expor métricas no formato Prometheus. Um serviço com /metrics e tracing já fica visivelmente mais “produção” do que 90% dos portfólios.

Projeto 4: CLI com cobra

Nem todo projeto precisa ser servidor. Uma ferramenta de linha de comando é um portfólio excelente e menos óbvio: mostra que você entende a linguagem para além de HTTP. Ideias: um gerador de senhas, um CLI que consome uma API pública, uma ferramenta de linha de comando para buscar e filtrar as próprias vagas de Go, ou um utilitário que processa arquivos em lote.

O que demonstra: organização de pacotes, módulos Go, flags e subcomandos, leitura/escrita de arquivos e testes de funções puras. Use a biblioteca cobra — é o padrão de mercado para CLIs em Go (é o que o próprio go e ferramentas como hugo, docker e kubectl usam por baixo).

package main

import (
	"fmt"
	"strconv"

	"github.com/spf13/cobra"
)

func main() {
	root := &cobra.Command{
		Use:   "meucli",
		Short: "Exemplo de CLI em Go para portfólio",
	}

	dobro := &cobra.Command{
		Use:   "dobro [número]",
		Short: "Calcula o dobro de um número",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			n, err := strconv.Atoi(args[0])
			if err != nil {
				return fmt.Errorf("argumento inválido: %w", err)
			}
			fmt.Println(n * 2)
			return nil
		},
	}

	root.AddCommand(dobro)
	_ = root.Execute()
}

Uma CLI pequena, com --help organizado e testes, é um projeto rápido que se sustenta sozinho — e rende assunto em entrevista porque força você a pensar em ergonomia e tratamento de erro.

Clássico, mas eficaz quando bem feito. A ideia: uma API que encurta URLs e, no redirecionamento, usa cache (Redis) para responder rápido sem bater no banco a cada acesso.

O que demonstra: cache com Redis, separação entre camada de cache e persistência, métricas de latência e trade-offs (invalidação de cache, expiração). É um projeto curto, com um problema de performance real para discutir: como o sistema se comporta com milhares de acessos ao mesmo link?

Para fechar o ciclo de produção, adicione rate limiting e um health check no estilo liveness/readiness. São dois detalhes pequenos que mostram maturidade operacional.

Como estruturar o repositório e o README

Um projeto de portfólio bem estruturado vence um projeto melhor escrito, mas bagunçado. Use uma organização de pastas que se pareça com código real:

meu-projeto/
├── cmd/
│   └── server/
│       └── main.go          # ponto de entrada
├── internal/
│   ├── handler/             # handlers HTTP
│   ├── service/             # regras de negócio
│   ├── repository/          # acesso a dados
│   └── model/               # entidades
├── migrations/              # SQL de migração
├── Dockerfile
├── docker-compose.yml       # sobe app + postgres + redis
├── go.mod
└── README.md

O README é a parte mais importante. Um recrutador ou sênior decide em dois minutos se vai ler o código. Um bom README responde:

  1. O que o sistema faz em três linhas.
  2. Decisões técnicas e por quê. Por que PostgreSQL e não SQLite? Por que net/http e não Gin? Justificar escolhas mostra maturidade.
  3. Como rodar localmente com um comando só (docker compose up).
  4. Estrutura de pastas e o que cada pacote faz.
  5. Endpoints ou comandos disponíveis, com exemplos de requisição.
  6. Como rodar os testes (go test ./...).

Não invente números de performance (“suporta 10 mil requisições por segundo”) sem medir. Se for medir de verdade, use o guia de profiling e performance com pprof e coloque o método no README.

Como apresentar o projeto na entrevista

Ter o projeto é metade; saber falar dele é a outra. Em entrevista técnica, prepare-se para explicar:

  • O fluxo de uma requisição do início ao fim: o que acontece entre o cliente bater no endpoint e a resposta sair.
  • As decisões de design e suas alternativas. “Usei um worker pool com buffer 10 porque…” é uma frase que impressiona; “usei goroutines” não.
  • Os trade-offs. Cache acelera leitura, mas adiciona invalidação. Fila desacopla, mas adiciona complexidade.
  • O que você faria diferente com mais tempo. Honestidade sobre o que falta vale pontos.

O guia de entrevista técnica em Go lista as perguntas mais frequentes e como se preparar. Para o currículo, o guia de currículo de desenvolvedor Go mostra como destacar o portfólio sem inflar.

Erros comuns no portfólio Go

  • Repositório sem README, ou com um README de uma linha. É a primeira coisa que eliminam.
  • Código sem teste algum. Mesmo poucos testes de tabela já mudam a percepção.
  • Tratamento de erro que esconde falhas (_ = err ou if err != nil { return } sem contexto). Em Go, o jeito como você trata erro é uma assinatura de senioridade.
  • Dependências sem gerenciamento. Sem go.sum organizado ou com vulnerabilidades conhecidas. Rode govulncheck antes de publicar.
  • Muitos repositórios rasos. Dez “hello world” valem menos que um projeto sólido. Concentre esforço.
  • Segredos no repositório. Nenhuma chave de API no código. Use variáveis de ambiente e .env.example.

Próximos passos: do portfólio à vaga

Escolha um projeto principal entre os cinco acima e leve até o fim: testes, Docker, README honesto e, se possível, deploy. Depois, coloque o link do repositório em destaque no currículo e comece a aplicar. As vagas de Go no Brasil mostram o que o mercado pede em termos de senioridade, regime (CLT ou PJ) e localização — e o guia de como conseguir a primeira vaga em Go fecha o funil, do perfil exigido ao plano de 90 dias.

O portfólio não precisa ser perfeito nem cobrir tudo. Precisa mostrar que você entende o ciclo de um serviço e consegue explicar o que construiu. Esse conjunto — um projeto sólido e a capacidade de falar sobre ele — vale mais do que conhecer a API de cada framework. Para quem quer comparar como o mesmo desafio de “portfólio de entrada” aparece em outra linguagem, o portal de vagas eu.dev.br reúne oportunidades de desenvolvimento no Brasil e ajuda a calibrar o que cada stack pede de portfólio.