5 projectes reals per aprendre Go si ja saps programar
Projectes pràctics per aprendre Go: CLI, API REST, worker, consumidor Kafka i conversor de fitxers. Amb enllaços a tutorials pas a pas.

Els exercicis de sintaxi no serveixen. Fas vint problemes de bucles, tres de slices, un d’interfícies, i l’endemà no recordes res. No perquè siguis mal estudiant, sinó perquè el cervell no reté el que no té context. I la sintaxi de Go fora d’un problema real no té context.
La forma d’aprendre Go de debò és construir coses petites que resolguin problemes reals. No una app de TODO. No un “Hello World amb goroutines”. Projectes que s’assemblin al que faries en la teva feina o en un servei que desplegaries en producció.
Porto mesos escrivint tutorials pas a pas sobre Go, cada un centrat en un projecte concret. Aquest article és el mapa. Aquí t’explico quins cinc projectes construir, en quin ordre, què aprendràs amb cada un, i per què aquell ordre importa.
Per què projectes > tutorials per aprendre Go
Hi ha una diferència enorme entre llegir documentació i resoldre un problema. Quan llegeixes sobre goroutines, entens el concepte. Quan has de paral·lelitzar deu peticions HTTP i agregar resultats amb un timeout, aprens goroutines.
Això s’aplica a qualsevol llenguatge, però en Go és especialment cert per dues raons:
- Go és minimalista per disseny. No té cent formes de fer el mateix. Això significa que els patrons correctes els interioritzeu ràpid, però només si els useu en context. Llegir-los no n’hi ha prou.
- El tooling de Go és part del llenguatge.
go test,go build,go mod,go vet… No són extres. Són fonamentals. I només els aprens usant-los en un projecte amb estructura real.
La trampa clàssica és intentar aprendre Go llegint Effective Go de principi a fi, o completant un curs de sintaxi de quatre hores. Acabes sabent que existeixen els channels però sense haver-ne escrit un que resolgui alguna cosa. Saps que defer existeix però no has sentit per què importa en un handler HTTP que obre i tanca connexions.
Els cinc projectes que proposo aquí estan dissenyats per cobrir l’espectre del que necessita un desenvolupador backend. Cada un ataca un domini diferent i t’obliga a usar una combinació diferent d’eines del llenguatge.
Projecte 1: CLI per a automatització local
Què construeixes: Una eina de línia de comandos que automatitza una tasca repetitiva. Pot ser reanomenar fitxers, netejar logs, generar reportes, el que vulguis. L’important és que rebi arguments, processi alguna cosa i retorni un resultat.
Per què aquest primer: Perquè elimina totes les distraccions. No hi ha HTTP, no hi ha base de dades, no hi ha Docker. Només tu, el llenguatge i el sistema operatiu. És el terreny perfecte per assentar els fonaments.
Què aprendràs
- Estructura bàsica d’un projecte Go amb
go mod init - Com parsear arguments amb
os.Argso llibreries comcobra - Gestió de fitxers: llegir, escriure, recórrer directoris
- El patró d’error handling de Go (
if err != nil) - Compilar un binari i distribuir-lo
Exemple mínim
package main
import (
\"fmt\"
\"os\"
\"path/filepath\"
\"strings\"
)
func main() {
if len(os.Args) < 3 {
fmt.Println(\"ús: reanomenar <directori> <prefix>\")
os.Exit(1)
}
dir := os.Args[1]
prefix := os.Args[2]
entries, err := os.ReadDir(dir)
if err != nil {
fmt.Fprintf(os.Stderr, \"error llegint directori: %v\n\", err)
os.Exit(1)
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
oldPath := filepath.Join(dir, entry.Name())
newPath := filepath.Join(dir, prefix+\"_\"+entry.Name())
if err := os.Rename(oldPath, newPath); err != nil {
fmt.Fprintf(os.Stderr, \"error reanomenant %s: %v\n\", oldPath, err)
continue
}
fmt.Printf(\"%s -> %s\n\", oldPath, strings.TrimPrefix(newPath, dir+\"/\"))
}
}Això és una CLI real. No és sofisticada, però ja tens arguments, gestió d’errors, operacions amb el filesystem i un binari que funciona. Des d’aquí pots afegir flags, validacions, output formatat, tests.
Tutorial complet: CLI en Go
Projecte 2: API REST amb estructura professional
Què construeixes: Una API REST amb endpoints CRUD, connexió a base de dades, validació de dades i una estructura de carpetes que escali. No una API de joguina amb un map en memòria: una API amb PostgreSQL, migracions i tests.
Per què aquest segon: Perquè després de la CLI ja domines la base del llenguatge. Ara toca aprendre com Go gestiona HTTP, JSON, middleware i tot el que envolta el desenvolupament web backend.
Què aprendràs
- El paquet
net/httpi com funciona un servidor en Go - Routing amb el mux estàndard o amb frameworks com Gin
- Serialització i deserialització JSON amb struct tags
- Connexió a PostgreSQL amb
database/sqlosqlx - Organització de codi: handlers, services, repositories
- Middleware per a logging, autenticació, CORS
- Testing d’endpoints amb
httptest
Exemple: handler bàsic
func GetTaskHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue(\"id\")
var task Task
err := db.QueryRow(
\"SELECT id, title, done FROM tasks WHERE id = $1\", id,
).Scan(&task.ID, &task.Title, &task.Done)
if err == sql.ErrNoRows {
http.Error(w, \"task not found\", http.StatusNotFound)
return
}
if err != nil {
http.Error(w, \"internal error\", http.StatusInternalServerError)
return
}
w.Header().Set(\"Content-Type\", \"application/json\")
json.NewEncoder(w).Encode(task)
}
}Fixa’t en el que no hi ha: no hi ha framework màgic que amagui el request i el response. No hi ha anotacions. No hi ha injecció de dependències automàtica. En Go veus exactament el que passa en cada línia. Això és incòmode al principi i un avantatge enorme quan alguna cosa falla en producció.
Si vols un projecte més complet amb PostgreSQL i Docker inclòs, tinc un tutorial específic: API de tasques amb Go, PostgreSQL i Docker.
Tutorial de l’API: API REST amb Go
Projecte 3: Worker de processament en segon pla
Què construeixes: Un servei que recull tasques d’una cua (pot ser Redis, una taula en PostgreSQL o un canal en memòria) i les processa en segon pla. Redimensionar imatges, enviar emails, generar PDFs, el que encaixi amb el teu cas.
Per què aquest tercer: Perquè aquí és on Go comença a brillar. Les goroutines i els channels deixen de ser teoria i es converteixen en l’eina que usa el teu worker per processar N tasques en paral·lel sense reventar la memòria.
Què aprendràs
- Goroutines i channels en un escenari real
- El patró worker pool
context.Contextper a cancel·lació i timeoutssync.WaitGroupper esperar que acabin els workers- Graceful shutdown amb senyals del sistema operatiu
- Logging estructurat
Exemple: worker pool bàsic
func startWorkers(ctx context.Context, jobs <-chan Job, results chan<- Result, numWorkers int) {
var wg sync.WaitGroup
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func(workerID int) {
defer wg.Done()
for {
select {
case <-ctx.Done():
log.Printf(\"worker %d: apagant-se\", workerID)
return
case job, ok := <-jobs:
if !ok {
return
}
result := process(job)
results <- result
}
}
}(i)
}
go func() {
wg.Wait()
close(results)
}()
}Aquest patró és el pa de cada dia en serveis Go de producció. El veuràs en processadors de cues, en pipelines de dades, en qualsevol sistema que necessiti fer treball pesat sense bloquejar el flux principal.
L’important aquí no és només el codi. És entendre com context et permet propagar cancel·lacions, com els channels et donen sincronització sense locks explícits, i com el graceful shutdown evita que el teu worker mori a mig processament quan Kubernetes envia un SIGTERM.
Tutorial complet: worker en Go
Projecte 4: Consumidor Kafka per a processament d’esdeveniments
Què construeixes: Un servei que es subscriu a un topic de Kafka, llegeix missatges, els deserialitza, els processa i gestiona offsets i errors. És el projecte més proper al que trobaries en una arquitectura de microserveis real.
Per què aquest quart: Perquè si ja has construït una API i un worker, tens la base per entendre sistemes distribuïts. Kafka afegeix la complexitat de particions, consumer groups, offsets i rebalancejos. I aprendre a gestionar tot això en Go et dóna un skill directament aplicable en producció.
Què aprendràs
- Com funciona Kafka a nivell de consumidor (topics, particions, offsets, consumer groups)
- Ús de llibreries com
confluent-kafka-goosegmentio/kafka-go - Deserialització de missatges (JSON, Avro, Protobuf)
- Gestió d’errors i reintents
- Processament idempotent
- Mètriques i health checks
Exemple: consumidor bàsic
func consume(ctx context.Context, reader *kafka.Reader) error {
for {
select {
case <-ctx.Done():
return reader.Close()
default:
msg, err := reader.ReadMessage(ctx)
if err != nil {
if errors.Is(err, context.Canceled) {
return nil
}
log.Printf(\"error llegint missatge: %v\", err)
continue
}
var event OrderCreated
if err := json.Unmarshal(msg.Value, &event); err != nil {
log.Printf(\"error deserialitzant missatge: %v\", err)
continue
}
if err := processOrder(ctx, event); err != nil {
log.Printf(\"error processant comanda %s: %v\", event.OrderID, err)
// Aquí decideixes: reintentar? enviar a DLQ? loguejar i continuar?
continue
}
log.Printf(\"comanda %s processada de la partició %d offset %d\",
event.OrderID, msg.Partition, msg.Offset)
}
}
}Kafka és una d’aquelles tecnologies que pots usar durant anys sense entendre-la del tot. Construir un consumidor des de zero t’obliga a entendre què passa quan un consumer cau i un altre pren la seva partició, què significa commit manual vs automàtic d’offsets, i per què el processament idempotent no és opcional.
Tutorial complet: Kafka amb Go
Projecte 5: Conversor CSV a JSON
Què construeixes: Una eina que llegeix fitxers CSV (potencialment grans), els parseja, transforma i escriu com a JSON. Sembla simple. No ho és quan el CSV té milions de files, encodings estranys o camps que no compleixen l’esquema esperat.
Per què aquest cinquè: Perquè toca un domini completament diferent: processament de dades. I perquè t’obliga a pensar en streaming, en ús de memòria i en com Go gestiona l’I/O de forma eficient.
Què aprendràs
- Paquets
encoding/csviencoding/json - Lectura streaming sense carregar tot en memòria
- Interfícies
io.Readeriio.Writer - Buffered I/O amb
bufio - Validació i transformació de dades
- Testing amb fitxers d’exemple
- Flags per configurar el comportament (delimitador, encoding, format de sortida)
Exemple: streaming CSV a JSON
func convertCSVtoJSON(input io.Reader, output io.Writer) error {
reader := csv.NewReader(input)
headers, err := reader.Read()
if err != nil {
return fmt.Errorf(\"llegint capçaleres: %w\", err)
}
encoder := json.NewEncoder(output)
encoder.SetIndent(\"\", \" \")
for {
record, err := reader.Read()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf(\"llegint registre: %w\", err)
}
row := make(map[string]string, len(headers))
for i, header := range headers {
if i < len(record) {
row[header] = record[i]
}
}
if err := encoder.Encode(row); err != nil {
return fmt.Errorf(\"codificant fila: %w\", err)
}
}
return nil
}L’interessant d’aquest projecte és que treballa amb les interfícies d’I/O de Go, que són una de les peces més elegants del llenguatge. io.Reader i io.Writer són a tot arreu: fitxers, connexions HTTP, buffers, compressors. Entendre com compondre-les és fonamental.
A més, aquest projecte escala naturalment. Comences amb un conversor bàsic i pots afegir: suport per a fitxers enormes amb processament concurrent, detecció automàtica de tipus, output en múltiples formats (JSON Lines, Parquet), validació contra un esquema.
Tutorial complet: CSV a JSON en Go
Bonus: web scraper amb concurrència
No és en els cinc principals perquè el scraping té les seves pròpies complicacions (legals, d’infraestructura, d’estabilitat), però com a projecte d’aprenentatge és excel·lent.
Què construeixes: Un scraper que visita una llista d’URLs, extreu dades estructurades i les emmagatzema. La gràcia és fer-ho concurrent: llançar N goroutines, limitar la taxa de peticions, gestionar errors per URL sense que el sistema sencer caigui.
Què aprendràs
- HTTP client avançat: timeouts, retries, headers personalitzats
- Concurrència controlada amb semàfors (
chan struct{}) - Rate limiting amb
time.Ticker - Parsing HTML amb llibreries com
goquery - Patrons de resiliència: circuit breaker, backoff exponencial
func scrape(ctx context.Context, urls []string, concurrency int) []Result {
results := make([]Result, 0, len(urls))
sem := make(chan struct{}, concurrency)
var mu sync.Mutex
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go func(u string) {
defer wg.Done()
sem <- struct{}{} // adquirir semàfor
defer func() { <-sem }() // alliberar semàfor
data, err := fetchAndParse(ctx, u)
mu.Lock()
defer mu.Unlock()
if err != nil {
results = append(results, Result{URL: u, Error: err})
return
}
results = append(results, Result{URL: u, Data: data})
}(url)
}
wg.Wait()
return results
}El semàfor amb un channel buffered és un patró que veus constantment en Go. És simple, no requereix cap llibreria externa, i et dóna control precís sobre quantes operacions concurrents vols permetre.
Tutorial complet: scraper en Go
Com presentar aquests projectes en el teu portfolio
Construir els projectes és només la meitat. L’altra meitat és que algú pugui mirar el teu GitHub i entendre què has fet i per què. Això s’aplica tant si busques feina com si vols documentar el teu aprenentatge.
Estructura de cada repositori
Cada projecte hauria de tenir:
- README clar: Què fa, com executar-lo, quines tecnologies usa. No un README de tres paràgrafs: un de deu línies amb instruccions concretes.
- Makefile o Taskfile: Comandes per a build, test, lint, run. Que qualsevol pugui clonar i executar en menys d’un minut.
- Tests reals: No tests de mentida que comproven que
1+1 == 2. Tests que validen comportament, edge cases, errors esperats. - Docker (quan apliqui): Un
Dockerfilemulti-stage que produeixi una imatge neta. Undocker-compose.ymlsi el projecte necessita bases de dades o altres serveis. - CI configurat: Un workflow de GitHub Actions que executi tests i linting en cada push. És una línia en el teu repo que diu “em prenc això seriosament”.
El que demostra cada projecte
| Projecte | Demostra |
|---|---|
| CLI | Domini del llenguatge base, gestió d’errors, testing |
| API REST | Arquitectura web, base de dades, middleware, testing HTTP |
| Worker | Concurrència, patterns de producció, graceful shutdown |
| Kafka consumer | Sistemes distribuïts, event-driven architecture |
| CSV a JSON | I/O eficient, streaming, composició d’interfícies |
| Scraper (bonus) | Concurrència avançada, resiliència, rate limiting |
No necessites els sis. Tres projectes ben fets ja expliquen una història coherent. Però si fas els cinc principals, tens un portfolio que cobreix pràcticament tot el que un equip busca en un desenvolupador Go.
Progressió: en quin ordre construir-los
L’ordre importa. Cada projecte assumeix que ja domines el que has après en l’anterior.
Nivell 1: CLI
És el teu primer contacte real amb Go. Aquí aprens el llenguatge: tipus, control de flux, error handling, paquets, compilació. Sense distraccions externes.
Temps estimat: 1-2 dies si ja programes en un altre llenguatge.
Nivell 2: API REST
Pujada de complexitat. Ara tens HTTP, JSON, base de dades. Aprens com Go estructura aplicacions web i com es testegen.
Temps estimat: 3-5 dies. Més si inclous PostgreSQL i Docker.
Nivell 3: Worker
El salt a concurrència real. Goroutines, channels, context, wait groups. Aquí és on Go deixa de semblar-se a qualsevol altre llenguatge i comences a pensar de forma diferent.
Temps estimat: 2-3 dies.
Nivell 4: Kafka consumer
Sistemes distribuïts. Complexitat operacional. Aquest projecte no és només codi: és entendre com funcionen les peces a nivell d’infraestructura.
Temps estimat: 3-5 dies, incloent aixecar Kafka en local amb Docker.
Nivell 5: CSV a JSON
Tornes a un problema aparentment simple, però l’atacas amb tot el que has après. Streaming, interfícies, testing robust, gestió d’edge cases.
Temps estimat: 1-2 dies per a la versió bàsica. Més si afegiu concurrència o suport per a fitxers enormes.
El roadmap complet
CLI → API REST → Worker → Kafka Consumer → CSV/JSON Converter
│ │ │ │ │
│ │ │ │ └─ I/O, streaming, interfícies
│ │ │ └─ Sistemes distribuïts, event-driven
│ │ └─ Concurrència, goroutines, channels
│ └─ HTTP, JSON, BD, middleware, testing
└─ Fonaments: tipus, errors, paquets, compilacióSi vols un mapa més ampli de tot l’ecosistema de Go, incloent conceptes intermedis i avançats, ho detallo a la guia general: Aprendre Go el 2026.
Errors comuns en aprendre Go amb projectes
Abans que comencis, alguns errors que he vist (i comès):
Començar massa gran
No facis un “microservei complet amb Kafka, Redis, PostgreSQL i gRPC” com a primer projecte. Abandonaràs al tercer dia. La CLI és el teu primer projecte per alguna cosa: és petit, terminable i et dóna confiança.
No escriure tests des del principi
En Go, testejar és trivial. El paquet testing ve inclòs, go test ./... executa tot, i la convenció de _test.go és tan natural que no hi ha excusa. Si no testegeu els vostres projectes d’aprenentatge, esteu deixant sobre la taula una de les millors eines del llenguatge.
Copiar sense entendre
Els LLMs et generen codi Go correcte en segons. Però si copies sense entendre per què s’usa defer aquí, per què l’error es comprova allà, per què el channel és buffered en aquest cas i no en un altre, no estàs aprenent. Usa la IA com a accelerador, no com a substitut.
Ignorar el tooling
go fmt, go vet, golangci-lint. Usa’ls des del primer projecte. No després. El tooling de Go és part de la cultura del llenguatge i t’estalvia discussions sobre estil que en altres llenguatges consumeixen hores.
No llegir codi d’altres
Després de cada projecte, busca implementacions similars a GitHub. Mira com ho fan els altres. El codi Go idiomàtic té un estil reconeixible, i comparar la teva solució amb d’altres és la forma més ràpida de millorar.
Construir és l’única forma d’aprendre de debò
Go no s’aprèn llegint. S’aprèn construint. I no qualsevol cosa: projectes que t’obliguin a resoldre problemes reals amb les eines que el llenguatge et dóna.
Els cinc projectes que he proposat van des d’una CLI en Go per assentar els fonaments sense distraccions, passant per una API REST amb Go que et fica de ple en el desenvolupament web amb base de dades, fins a un worker en Go on la concurrència amb goroutines i channels deixa de ser teoria. Kafka amb Go et porta a sistemes distribuïts i event-driven architecture, i el conversor CSV a JSON en Go t’obliga a treballar amb I/O eficient, streaming i interfícies. I com a bonus, el scraper en Go per a concurrència avançada i patrons de resiliència.
No necessites seguir l’ordre al peu de la lletra, però et recomano no saltar-te els primers dos. La CLI et dóna els fonaments i l’API et dóna el context web. A partir d’aquí, pots anar al worker, a Kafka o al conversor segons el que més t’interessi o el que necessitis per a la teva feina. El que sí necessites és començar. Obre el terminal, executa go mod init i escriu el primer main.go. El millor moment va ser fa una setmana. El segon millor moment és ara.


