Aprendre Go el 2026: guia per a programadors que ja saben programar

Guia completa per aprendre Go si ja programes en Python, Java o Kotlin. Casos reals, comparacions honestes i un roadmap pràctic.

Cover for Aprendre Go el 2026: guia per a programadors que ja saben programar

Porto anys construint backends en Kotlin i Python. He lluitat amb Spring Boot, amb FastAPI, amb Gradle i amb pip. He viscut els problemes típics de cada llenguatge, des de mantenir microserveis en producció que reben milers de peticions per segon fins a serveis que queien cada dimarts per un memory leak que ningú trobava. I un dia, llegint per enèsima vegada com configurar correctament les coroutines de Kotlin amb un dispatcher personalitzat per no bloquejar el fil d’I/O, vaig pensar: hi ha d’haver alguna cosa més senzilla.

Aquella alguna cosa va resultar ser Go. No perquè sigui el llenguatge perfecte —si segueixes aquest blog sabràs que tendeixo a ser una persona pràctica i poc dogmàtica— sinó perquè és el llenguatge que menys et demana per donar-te alguna cosa funcional. I sent honestos, en un context on la IA ja ens ajuda a escriure una part important del codi, aquesta simplicitat no és un defecte: és un avantatge competitiu real.

Aquest article és la guia que m’hauria agradat tenir quan vaig començar. No és un tutorial de sintaxi. He intentat crear un mapa complet per a programadors que ja saben programar i volen entendre si Go mereix el seu temps, com aprendre’l de forma eficient i què esperar del camí.


Què és Go i què no és

Go és un llenguatge compilat, tipat estàticament, creat per Google el 2009 i dissenyat amb una obsessió clara: simplicitat. No té herència de classes, no té excepcions, no té genèrics elaborats (té genèrics des de la versió 1.18, però deliberadament limitats), no té macros ni metaprogramació màgica.

Si véns de Java o Kotlin, Go et semblarà auster. Si véns de Python, et semblarà rígid just en la mesura justa. I si véns de Rust, et semblarà que li falta rigor. Totes aquestes percepcions són correctes i totes són incompletes.

Crec que Go és, sobretot, un llenguatge d’enginyeria. Va ser dissenyat perquè equips grans poguessin escriure, llegir i mantenir programari a escala sense que el llenguatge s’hi interposés. No intenta ser elegant, intenta ser predictible.

Go no és el llenguatge que més et deixa fer. És el llenguatge que menys et deixa trencar.

El que podem esperar de Go:

  • Un llenguatge que compila en segons a un binari estàtic sense dependències
  • Un llenguatge enfocat a la concurrència (goroutines i channels)
  • Un llenguatge amb una biblioteca estàndard extremadament capaç per a backend, HTTP, JSON, criptografia, testing
  • formatter, test runner, profiler i eines d’anàlisi com go vet
  • I el bonus inevitable: poder fer jocs de paraules dolents amb el nom de les teves aplicacions

El que no hauries de buscar en Go:

  • Un llenguatge funcional (no té immutabilitat per defecte ni pattern matching avançat)
  • Un substitut de Rust per a sistemes de baix nivell
  • Un llenguatge per a frontend, data science o machine learning
  • Un llenguatge que et deixi escriure abstraccions sofisticades

Si vols aprofundir en si Go encaixa amb el teu perfil i els teus projectes, tinc un article específic: Val la pena aprendre Go?.


Per què aprendre Go el 2026

Hi ha moltes raons per aprendre un nou llenguatge. La majoria són dolentes. “Perquè està de moda” és la pitjor. Així que intentaré ser concret sobre per què crec que Go té sentit ara, el 2026, si ja ets desenvolupador backend.

L’ecosistema cloud-native parla Go

Kubernetes, Docker, Terraform, Prometheus, Grafana, etcd, CockroachDB, Caddy, Traefik. No són projectes menors. Són la infraestructura sobre la qual corre mig internet. Tots estan escrits en Go. Això no és casualitat: Go produeix binaris petits, ràpids d’arrencar, fàcils de distribuir en contenidors, i amb un consum de memòria predictible.

Si treballes amb infraestructura cloud o vols contribuir a eines de l’ecosistema, Go no és opcional. He escrit més sobre això a Go en cloud-native.

Compilació instantània, desplegament trivial

En Java, un build amb Gradle pot trigar minuts; si ho fas natiu amb GraalVM, et pot donar temps de preparar-te un cafè i tornar amb calma. En Go, un projecte mitjà compila en segons. I el resultat és un binari estàtic que copies a un contenidor scratch mínim i despliegues. Sense JVM, sense runtime, sense dependències de sistema.

Això canvia bastant el teu cicle de desenvolupament. El feedback loop s’escurça. Els desplegaments se simplifiquen. Els contenidors són minúsculs. I el consum de memòria en producció és una fracció del que consumiria l’equivalent en Java o Python. Tècnicament podries aconseguir alguna cosa similar amb una imatge GraalVM nativa, però l’esforç no és comparable.

Concurrència que pots entendre

La concurrència en Go no requereix un doctorat. Les goroutines són funcions que s’executen de forma concurrent, els channels són la forma de comunicar-se entre elles, i el runtime de Go s’encarrega de l’scheduling. No hi ha thread pools que configurar, no hi ha ExecutorService, no hi ha asyncio amb els seus event loops i els seus await oblidats.

func main() {
    ch := make(chan string)

    go func() {
        ch <- \"resultat d'una tasca pesada\"
    }()

    resultat := <-ch
    fmt.Println(resultat)
}

Això és concurrència real, no una abstracció sobre callbacks. I escala: pots llançar desenes de milers de goroutines sense esforç. Més endavant al roadmap enlaço els articles detallats sobre concurrència en Go i channels.

La simplicitat com a avantatge amb la IA

Aquest punt és contraintuïtiu però crec que important. El 2026, bona part del codi l’escrivim assistits per eines d’IA. I resulta que la simplicitat de Go és un avantatge enorme per a aquestes eines. El llenguatge té poques formes de fer cada cosa, les convencions són clares, i el codi generat sol ser correcte o fàcilment corregible.

Amb llenguatges més complexos, com Kotlin o Rust, la IA sovint genera codi que compila però que no és idiomàtic, o que fa servir patterns incorrectes per al context. Amb Go, almenys en la meva experiència, l’espai d’error és més petit.


Go per a desenvolupadors backend: què canvia

Si véns de Java, Kotlin o Python, Go et sorprendrà en llocs inesperats. No per la sintaxi, que s’aprèn en un parell de dies, sinó per les decisions de disseny que el llenguatge t’imposa.

Si véns de Java o Kotlin

El canvi més gran no és tècnic, és mental. En el món JVM estàs acostumat a frameworks que fan màgia: injecció de dependències, proxies, anotacions que generen codi, reflexió per tot arreu. En Go, no hi ha màgia. Si necessites injecció de dependències, la fas passant structs per constructor. Si necessites un middleware, l’escrius com una funció que embolcalla una altra funció.

// Injecció de dependències en Go: passes el que necessites
type UserService struct {
    repo UserRepository
    log  *slog.Logger
}

func NewUserService(repo UserRepository, log *slog.Logger) *UserService {
    return &UserService{repo: repo, log: log}
}

No hi ha @Autowired, no hi ha contenidors IoC, no hi ha @Transactional. Tot és explícit. Al principi se sent com retrocedir deu anys. Però després d’un temps, agraïes no haver de depurar errors causats per la màgia de Spring. No dic que Spring sigui dolent —l’he fet servir durant anys i funciona— però aquesta explicitud de Go té un valor que no aprecies fins que la vius.

Per a una comparació detallada, he escrit Go vs Java i Go vs Kotlin.

Si véns de Python

El canvi és gairebé oposat. Python et dóna llibertat total i tu poses la disciplina. Go et dóna poca llibertat i la disciplina ve inclosa. No trobaràs a faltar mypy perquè el compilador ja t’obliga a tipar tot. No tindràs errors en runtime per un None inesperat perquè el sistema de tipus els atrapa abans.

El que sí trobaràs a faltar: la rapidesa de prototipatge, les one-liners amb list comprehensions, i la riquesa de l’ecosistema per a dades. Go no és millor que Python per a tot, ni de lluny. Però per a serveis backend que necessiten rendiment, concurrència i un binari desplegable, crec que Go guanya amb bastant claredat.

He comparat tots dos en profunditat a Go vs Python.

I sobre Rust

Rust és objectivament més potent que Go en control de memòria i garanties de seguretat. Però el cost és real: un temps de compilació molt major, una corba d’aprenentatge més pronunciada, i una productivitat inicial més baixa. I sent honestos, si no necessites control a nivell de sistema ni garanties de zero-cost abstractions, Go et dóna el 80% dels beneficis amb el 20% de l’esforç. Si necessites aquest 20% restant, llavors sí: aprèn Rust. Ho comparo a Go vs Rust.


La corba d’aprenentatge: què és fàcil i què és diferent

Seré honest: la sintaxi de Go s’aprèn en un cap de setmana. És deliberadament petita. Però dominar Go idiomàtic porta més temps del que sembla, i el que em va sorprendre és que les coses que costen no són les que esperaves.

El que s’aprèn ràpidament

  • Sintaxi bàsica: variables, funcions, structs, slices, maps. Si saps programar, en dues hores estàs escrivint codi que funciona.
  • La biblioteca estàndard: net/http, encoding/json, fmt, os. És sorprenentment completa i ben documentada.
  • Les eines: go fmt, go test, go build, go mod. Tot funciona des del primer dia sense configurar res.
  • Testing: el runner de tests està inclòs, no necessites frameworks externs. Escrius funcions que comencen per Test i ja està.
func TestSuma(t *testing.T) {
    resultat := Suma(2, 3)
    if resultat != 5 {
        t.Errorf(\"esperava 5, vaig obtenir %d\", resultat)
    }
}

El que costa més del que sembla

  • Gestió d’errors: Go no té excepcions. Cada funció que pot fallar retorna un error explícit. Al principi sembla tediós. Després entens que és una de les millors decisions de disseny del llenguatge, però requereix disciplina per no caure en el if err != nil mecànic sense tractar els errors de debò. Ho detallo a Errors en Go.
user, err := repo.FindByID(ctx, id)
if err != nil {
    return fmt.Errorf(\"buscant usuari %d: %w\", id, err)
}
  • Interfícies implícites: en Go no declares que un tipus “implementa” una interfície. Si té els mètodes, la implementa. Això és enormement poderós però al principi desorienta qui ve de Java on tot és implements. Ho explico a Interfícies en Go.
  • Punters: Go té punters, però sense aritmètica de punters. Si véns de Java mai has pensat en això. Si véns de Python, tampoc. Però en Go necessites entendre quan passar un valor i quan passar un punter. No és difícil, però és un concepte nou per a molts.
  • Goroutines i channels: llançar una goroutine és trivial. Coordinar correctament diverses goroutines sense race conditions ni deadlocks requereix entendre patterns que no són obvis: l’ús de context, worker pools, i com tancar channels de forma segura.
  • L’absència de frameworks grans: no hi ha un “Spring Boot de Go”. Hi ha biblioteques petites que composes tu. Això significa que les decisions d’arquitectura són teves. I sent honestos, això és alliberador i aterridor a parts iguals.

Roadmap: com aprendre Go pas a pas

Aquí va el mapa complet. Està pensat per a algú que ja sap programar i vol un camí eficient, no exhaustiu. Cada fase enllaça a articles específics on aprofundeixo en cada tema.

Fase 0: Decidir si Go és per a tu

Abans d’invertir setmanes, dedica un parell d’hores a entendre on encaixa Go i on no. Llegeix les comparacions amb els llenguatges que ja coneixes:

No et quedis amb opinions alienes. Instal·la Go, escriu un “Hello World” que faci una petició HTTP i retorni JSON, i decideix si l’experiència et convenç.

Fase 1: Els fonaments

Un cop decidit, necessites assentar les bases. Go té poques construccions, però cada una importa.

Un primer projecte per a aquesta fase: escriu una CLI que llegeixi un arxiu CSV i el converteixi a JSON. Així toques el sistema de fitxers, la gestió d’errors, els structs i l’encoding.

package main

import (
    \"encoding/csv\"
    \"encoding/json\"
    \"fmt\"
    \"os\"
)

type Record struct {
    Name  string `json:\"name\"`
    Email string `json:\"email\"`
}

func main() {
    f, err := os.Open(\"dades.csv\")
    if err != nil {
        fmt.Fprintf(os.Stderr, \"error obrint arxiu: %v\n\", err)
        os.Exit(1)
    }
    defer f.Close()

    reader := csv.NewReader(f)
    rows, err := reader.ReadAll()
    if err != nil {
        fmt.Fprintf(os.Stderr, \"error llegint CSV: %v\n\", err)
        os.Exit(1)
    }

    var records []Record
    for _, row := range rows[1:] { // saltar capçalera
        records = append(records, Record{Name: row[0], Email: row[1]})
    }

    output, _ := json.MarshalIndent(records, \"\", \"  \")
    fmt.Println(string(output))
}

Aquest exemple ja té: structs amb tags JSON, gestió d’errors, defer, lectura de fitxers, slices. És més Go idiomàtic del que sembla.

Fase 2: Go idiomàtic

Aquí és on passes de “escriure Go que funciona” a “escriure Go que un gopher no voldria reescriure”. Els conceptes clau:

  • Errors en Go — l’error com a valor, wrapping, sentinel errors, errors personalitzats
  • Interfícies en Go — interfícies implícites, interfícies petites, el patró io.Reader/io.Writer
  • Structs en Go — composició sobre herència, embedding, mètodes amb receiver
  • Punters en Go — quan usar *T vs T, nil safety, receiver per valor vs punter
  • Generics en Go — què pots fer, què no, i quan usar-los (spoiler: menys del que creus)

La regla d’or en Go: accepta interfícies, retorna structs. Això manté el teu codi flexible per a qui el consumeix i concret per a qui l’implementa.

Un projecte per a aquesta fase: refactoritza el CSV-to-JSON de la fase anterior. Extreu la lògica de lectura a una interfície, implementa un reader per a CSV i un altre per a un format diferent (per exemple, TSV). Escriu tests. Veuràs com les interfícies implícites de Go fan que això sigui natural.

Fase 3: Backend amb Go

Aquí arriba el bo. Construir serveis reals. Go brilla en aquest terreny.

  • API REST amb Go — des de net/http fins a routers com chi o gin, handlers, middleware
  • PostgreSQL amb Gopgx, connection pools, queries parametritzades, migracions
  • Testing en Go — tests unitaris, tests d’integració, table-driven tests, mocks
  • Arquitectura neta en Go — capes, injecció de dependències sense frameworks, ports i adaptadors
  • Dockeritzar API Go — multi-stage builds, imatge mínima, configuració per variables d’entorn

El projecte de referència per a aquesta fase és construir una API REST completa: un gestor de tasques amb PostgreSQL, autenticació, tests i desplegament en Docker. Ho detallo pas a pas a API de tasques amb Go, PostgreSQL i Docker.

// Handler típic en Go amb net/http estàndard
func (h *TaskHandler) Create(w http.ResponseWriter, r *http.Request) {
    var input CreateTaskRequest
    if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
        http.Error(w, \"JSON invàlid\", http.StatusBadRequest)
        return
    }

    task, err := h.service.Create(r.Context(), input)
    if err != nil {
        h.log.Error(\"creant tasca\", \"error\", err)
        http.Error(w, \"error intern\", http.StatusInternalServerError)
        return
    }

    w.Header().Set(\"Content-Type\", \"application/json\")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(task)
}

Fixa’t: sense anotacions, sense màgia, sense framework. És una funció que rep una petició i escriu una resposta. Qualsevol programador entén què fa quan la llegeix. Això és Go.

Fase 4: Concurrència de debò

La concurrència en Go és fàcil de començar i difícil de dominar. Però per a backend, certs patterns cobreixen el 90% dels casos:

func processBatch(ctx context.Context, items []Item, workers int) []Result {
    jobs := make(chan Item, len(items))
    results := make(chan Result, len(items))

    // llançar workers
    var wg sync.WaitGroup
    for i := 0; i < workers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for item := range jobs {
                results <- process(ctx, item)
            }
        }()
    }

    // enviar feina
    for _, item := range items {
        jobs <- item
    }
    close(jobs)

    // esperar i recollir
    go func() {
        wg.Wait()
        close(results)
    }()

    var out []Result
    for r := range results {
        out = append(out, r)
    }
    return out
}

Aquest patró de worker pool és probablement el pattern de concurrència més útil en backend Go. L’usaràs per processar cues, fer peticions en paral·lel, ETL, i qualsevol cosa que necessiti concurrència controlada.

Fase 5: Projectes reals

La teoria sense pràctica s’oblida en una setmana, almenys a mi em passa. Aquí tens projectes que cobreixen diferents àrees de Go i que t’obliguen a integrar tot el que has après:

La meva recomanació: tria un projecte que necessitis de debò. No facis un to-do list perquè ho diu un tutorial. Si necessites una eina que processi logs, fes-la en Go. Si necessites una API per a un side project, fes-la en Go. L’aprenentatge que s’ancora a una necessitat real és el que sobreviu.


Go i el desenvolupament assistit per IA

Aquest punt mereix la seva pròpia secció perquè canvia l’equació de forma significativa.

El 2026 molts desenvolupadors fem servir eines d’IA per escriure codi. I aquí Go té un avantatge inesperat: en ser un llenguatge amb poques formes de fer cada cosa, la IA genera codi Go més consistent i correcte que en llenguatges més complexos.

Amb Kotlin, un assistent d’IA pot generar codi que faci servir coroutines on no hauria, que barreja patterns de Flow amb callbacks, o que fa servir extensions de forma no idiomàtica. Amb Python, pot generar codi que funciona però que viola convencions de tipat o que fa servir patterns anti-pythònics. Amb Go, l’espai de decisions és tan reduït que el codi generat sol ser acceptable o fàcilment corregible.

Això té implicacions pràctiques:

  • Les code reviews són més ràpides perquè el codi Go té menys variació estilística
  • Les refactoritzacions assistides per IA són més segures perquè el compilador atrapa errors ràpidament
  • L’onboarding de juniors és més senzill perquè el llenguatge els dóna menys formes d’escriure codi incorrecte

La simplicitat de Go no és una limitació. En l’era de la IA, és una forma de mantenir el control sobre el que es genera.

Ara bé, això no significa que la IA substitueixi el criteri tècnic. Saber quan usar un channel buffered vs unbuffered, quan propagar un context i quan crear-ne un de nou, quan exposar una interfície i quan no… són decisions que, almenys avui, cap eina d’IA prendrà bé de forma consistent. El llenguatge és simple; l’enginyeria continua sent complexa.


Quan NO aprendre Go

Seria deshonest escriure un article pilar sobre aprendre Go sense parlar de les seves limitacions. I crec que Go no és la resposta a tot. Hi ha escenaris on triar-lo seria, directament, un error.

Si necessites manipulació avançada de dades

Go no té DataFrames, ni un ecosistema de data science comparable al de Python. Si el teu dia a dia són notebooks, pandas, visualització de dades o machine learning, Go no aportarà res. Queda’t amb Python.

Si necessites abstraccions d’alt nivell

Si el teu projecte es beneficia de programació funcional avançada, pattern matching, tipus algebraics rics, o metaprogramació, Go et frustrarà. Llenguatges com Kotlin, Scala o Rust et donen molt més poder expressiu. Go sacrifica això deliberadament.

Si el teu equip ja és productiu amb el seu stack

Canviar de llenguatge té un cost enorme en un equip. Si tens un equip expert en Java amb Spring Boot que lliura a temps i amb qualitat, introduir Go “perquè és més ràpid” és, en la meva opinió, una mala decisió. La productivitat de l’equip pesa més que els benchmarks del llenguatge.

Si necessites un ecosistema de GUI

Go té biblioteques per a interfícies gràfiques, però cap és comparable al que ofereixen Swift, Kotlin (Compose), o fins i tot JavaScript amb Electron/Tauri. Per a aplicacions d’escriptori o mòbils, Go no és l’eina adequada.

Si vols contribuir a IA/ML

Els frameworks de machine learning viuen en Python (PyTorch, TensorFlow, JAX) i no migraran a Go. Si la teva carrera s’orienta cap a IA/ML, Python és el teu llenguatge obligatori. Go pot complementar a la capa de servei, però no al core de ML.

Aprendre un nou llenguatge només té sentit si resol problemes que el teu stack actual no resol bé. No aprenguis Go pel currículum; aprèn-lo perquè el necessites.


Menys soroll, més enginyeria

Si has arribat fins aquí, probablement ja saps si Go encaixa amb el que necessites. El que et recomano és no quedar-te en la teoria. Compara amb el teu llenguatge actual llegint Go vs Python, Go vs Java, Go vs Kotlin o Go vs Rust, i després instal·la Go i escriu alguna cosa en una hora seguint Com començar amb Go. No cal res sofisticat: una CLI que faci una petició HTTP i mostri el resultat ja t’ensenyarà bastant sobre com pensa el llenguatge.

Un cop tinguis les bases, entén els mòduls i l’estructura de projecte abans de llançar-te a alguna cosa seriosa, i llegeix Errors en Go com més aviat millor, perquè és el que més diferencia Go de tot la resta. Quan estiguis llest per construir alguna cosa real, munta una API amb PostgreSQL i Docker amb tests. La concurrència pot esperar: primer sigues productiu amb Go seqüencial, i quan tinguis un cas real que ho demani, llavors passa per concurrència i worker pools.

Go no és el llenguatge més potent, ni el més expressiu, ni el més innovador. Però crec que és un llenguatge que et permet construir programari seriós, mantenible i desplegable amb una fricció mínima. En un món on la complexitat accidental s’acumula en cada capa de l’stack, triar una eina que aposta per la simplicitat no és una concessió: és una decisió d’enginyeria. O almenys, aquesta ha estat la meva experiència.

OshyTech

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

Navegació

Copyright 2026 OshyTech. Tots els drets reservats