---
title: "Projetos em Go para Portfólio: Ideias para Conquistar Sua Vaga"
url: "https://golang.com.br/blog/projetos-go-para-portfolio-ideias-primeira-vaga/"
markdown_url: "https://golang.com.br/blog/projetos-go-para-portfolio-ideias-primeira-vaga.MD"
description: "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."
date: "2026-07-10"
author: "Golang Brasil"
---

# 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](/aprenda/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](/aprenda/golang-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](/aprenda/golang-postgresql/), [migrations](/blog/migrations-go-banco-dados-producao/) e [testes de tabela](/blog/testes-tabela-go-guia-table-driven-tests/). Para a autenticação, JWT é um padrão de mercado; o tutorial de [autenticação em APIs Go](/blog/autenticacao-autorizacao-go-apis/) cobre o caminho.

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

```go
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](/aprenda/api-rest-go/) para a versão completa, e a série de [API REST com Gin](/aprenda/api-rest-gin-parte1/) 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](/blog/context-timeout-cancelamento-go/), graceful shutdown (não derrubar jobs no meio quando o processo morre) e noções de fila. O guia de [worker pool em Go](/blog/worker-pool-go-fila-jobs/) mostra a estrutura completa; o artigo sobre [channels em Go](/blog/channels-go-comunicacao-goroutines-producao/) aprofunda a comunicação entre goroutines.

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

```go
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](/blog/redis-streams-go-filas-consumer-groups/), [SQS na AWS](/blog/sqs-go-filas-workers-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](/blog/grpc-go-protobuf-apis-internas/), definição de contratos, [observabilidade com OpenTelemetry](/blog/go-opentelemetry-observabilidade-tracing-metricas/) (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](/vagas/), ou um utilitário que processa arquivos em lote.

O que demonstra: organização de pacotes, [módulos Go](/aprenda/go-modules-na-pratica/), 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).

```go
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.

## Projeto 5: Encurtador de links com cache Redis

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](/tutoriais/go-redis-cache/), 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](/blog/rate-limiting-go-api-producao/) e um [health check](/blog/health-checks-go-liveness-readiness-startup/) 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](/tutoriais/go-performance-profiling/) 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](/carreira/entrevista-tecnica-go-2026/) lista as perguntas mais frequentes e como se preparar. Para o currículo, o guia de [currículo de desenvolvedor Go](/carreira/curriculo-desenvolvedor-go-2026/) 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](/blog/govulncheck-go-vulnerabilidades-dependencias/). 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](/vagas/) 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](/carreira/primeira-vaga-go-brasil-2026/) 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 <a href="https://eu.dev.br/" target="_blank" rel="noopener noreferrer" onclick="umami.track('portfolio-site-click', { destination: 'eu.dev.br' })">portal de vagas eu.dev.br</a> reúne oportunidades de desenvolvimento no Brasil e ajuda a calibrar o que cada stack pede de portfólio.
