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.

Cover for 5 projectes reals per aprendre Go si ja saps programar

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:

  1. 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.
  2. 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.Args o llibreries com cobra
  • 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/http i 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/sql o sqlx
  • 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.Context per a cancel·lació i timeouts
  • sync.WaitGroup per 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-go o segmentio/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/csv i encoding/json
  • Lectura streaming sense carregar tot en memòria
  • Interfícies io.Reader i io.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 Dockerfile multi-stage que produeixi una imatge neta. Un docker-compose.yml si 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

ProjecteDemostra
CLIDomini del llenguatge base, gestió d’errors, testing
API RESTArquitectura web, base de dades, middleware, testing HTTP
WorkerConcurrència, patterns de producció, graceful shutdown
Kafka consumerSistemes distribuïts, event-driven architecture
CSV a JSONI/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.

Articles relacionats

OshyTech

Enginyeria backend i de dades orientada a sistemes escalables, automatització i IA.

Navegació

Copyright 2026 OshyTech. Tots els drets reservats