# Go

## Vad det är

Go är ett allmänt programspråk som föddes hos Google, utformat med systemprogrammering i åtanke och
med samtidighet inbyggd i själva språket i stället för tillagd som ett bibliotek. Det kallas ofta
golang, efter projektets första webbadress, golang.org, men projektets FAQ är bestämd: språket heter
bara Go, skrivs Go och aldrig GO.

Robert Griesemer, Rob Pike och Ken Thompson började skissa på målen för språket på en
whiteboardtavla den 21 september 2007, och Go blev ett offentligt projekt med öppen källkod den 10
november 2009. Go 1 följde den 28 mars 2012, med ett löfte om att program skrivna för den versionen
skulle fortsätta att kompilera och köra, oförändrade, under varje senare utgåva av Go 1. Löftet
håller fortfarande: specifikationen beskriver nu språkversionen go1.27, och Go 1.27.0 släpptes den
19 augusti 2026. Generiska typer kom i Go 1.18, och språkets konstruktörer kallade dem den största
förändringen sedan den första utgåvan med öppen källkod.

Enligt FAQ:n växte språket fram ur ett val som upphovsmännen hade tröttnat på att göra, mellan
effektiv kompilering, effektiv körning och enkel programmering. Go tar sikte på att ge alla tre. Ett
program byggs av paket, och verktygskedjan är ett enda kommando, `go`, som bygger, testar,
formaterar och hämtar beroenden. Nyckelordet `go` framför ett funktionsanrop startar en goroutine,
en funktion som körs vid sidan av resten av programmet, och goroutiner är så billiga att
hundratusentals, enligt FAQ:n, kan dela ett och samma adressrum. Kanaler förmedlar värden mellan
dem, och [Effective Go](https://go.dev/doc/effective_go) sammanfattar den avsedda stilen i en
slogan: ”Do not communicate by sharing memory; instead, share memory by communicating.”

Två vanor känns igen i Go-kod var den än finns. Programmet `gofmt` skriver ut varje källfil i en och
samma standardlayout, så formateringen blir aldrig en fråga i kodgranskningen. Kompilatorn vägrar
dessutom att bygga ett program med en oanvänd variabel eller en oanvänd import, eftersom den första
kan dölja en bugg och den andra gör varje senare bygge långsammare.

## Varför det spelar roll

Frågan som Go besvarar gäller oftast vad en nätverkstjänst, ett kommandoradsverktyg eller en bit
infrastruktur ska skrivas i, och alternativen finns på var sin sida om det: ett skriptspråk på den
ena, C, C++ eller Rust på den andra.

Jämfört med ett skriptspråk erbjuder Go enkel driftsättning och tidiga fel. Länkaren bygger statiskt
länkade binärer som standard, så resultatet av ett bygge är en enda fil som bär sin egen körmiljö
och kör på en server där inget annat är installerat. FAQ:n anger priset till ett par megabyte för
ett program som skriver ut ”hello, world”, mot ungefär 750 kB för samma program i C. Kompilatorn
visar typfel när programmet byggs och inte när en sällan använd gren körs i produktion, och ett av
de ursprungliga målen var att även en stor körbar fil skulle byggas på några sekunder på en enda
dator.

Jämfört med C, C++ eller Rust erbjuder Go enkelhet och minnessäkerhet till priset av kontroll. En
skräpsamlare återtar minnet, så vanlig kod slipper en hel klass av misstag av typen use-after-free,
men programmet bestämmer inte exakt när minnet släpps, och varje binär levereras med den körmiljö
som gör jobbet. För de flesta servrar är det rätt avvägning. För en systemkärna, en liten inbyggd
enhet eller en het loop som inte tål en skräpsamlare är det fel avvägning.

Det tystare argumentet är tid. År 2023 skrev Russ Cox att ett Go 2 som bryter gamla program ”is
never going to happen” och att projektet i stället skulle ”double down on compatibility”. Löftet
betalas med uppgraderingar snarare än omskrivningar. En ny huvudversion släpps var sjätte månad, i
februari och augusti, och var och en får stöd tills två nyare finns, så ett team som vill ha
säkerhetsrättningar går vidare ungefär en gång om året.

Det lilla språket kräver också att en del saker skrivs ut i sin helhet. I Go är fel vanliga värden,
som returneras och kontrolleras där de uppstår, vilket är lika delar tydligt och upprepande.

## Så ser det ut i praktiken

En goroutine är billig att starta och lika billig att förlora. Sidan om att flytta långsamt arbete
till [en jobbkö i River](/sv/portfolio/moved-slow-work-onto-a-river-job-queue-97/) säger det rakt
ut: lägger du långsamt arbete i en goroutine försvinner det ”i samma stund som processen startas om,
vilket den kommer att göra, mitt under en driftsättning, utan några spår av att det någonsin var
tänkt att ske”. Företaget flyttade arbetet till River, som håller sin kö i PostgreSQL, så att ett
jobb och ”raderna det berör committas eller rullas tillbaka tillsammans”. Bakom kön finns 15
workermoduler och 8 schemalagda uppgifter, med 20 jobb i pg_cron under dem. En goroutine ger
samtidighet; beständigheten måste komma från något annat håll.

Tester ingår i verktygskedjan, och den
[skiktade testsviten](/sv/portfolio/built-a-layered-automated-test-suite-across-four-layers-94/)
visar vad det kan bli. Dess Go-API har 981 testfunktioner fördelade på 310 filer, ett av fyra lager
vid sidan av frontendens testspecifikationer och databasens egna tester i SQL. Sidan formulerar
uppgiften så här: ”Varje lager behövde få sitt beteende verifierat där beteendet faktiskt finns, i
stället för att allt verifierades utifrån genom en webbläsare.”

Det
[kontinuerliga säkerhetsprogrammet](/sv/portfolio/established-a-continuous-security-programme-104/)
lutar sig också mot språkets verktyg. Go-beroenden skannas med govulncheck, och sidan konstaterar:
”En sårbarhet som offentliggörs uppströms visar sig som ett bygge som fallerar i stället för som en
nyhet.” Samma sida kallar mängden fynd för den verkliga kostnaden med skanning, och govulncheck är
konstruerat mot just den kostnaden: verktyget rapporterar en sårbarhet bara när kodens egna
funktioner anropar den berörda funktionen, direkt eller via andra.

## Var det går fel

**En funktion rapporterar ett fel fast allt gick bra.** Ett gränssnittsvärde i Go håller en typ och
ett värde, och det är lika med nil bara när båda saknas. En funktion som returnerar en nil-pekare av
en konkret feltyp genom gränssnittet `error` ger anroparen ett gränssnitt som håller en typ, och det
gränssnittet är inte nil:

```go
func save() error {
    var err *ValidationError // en nil-pekare
    if invalid() {
        err = &ValidationError{}
    }
    return err // aldrig lika med nil: gränssnittet håller en typ
}
```

Returnera ett bokstavligt `nil` när allt gick bra, och deklarera varje felresultat som `error` och
inte som en konkret typ.

**En tjänst som klarade alla tester kraschar under verklig trafik.** Operationer på en map är
medvetet osynkroniserade, eftersom låsning vid varje åtkomst skulle göra de flesta program
långsammare, och FAQ:n varnar för att okontrollerad åtkomst till en map kan krascha programmet.
Orsaken är att en goroutine skriver till en map medan en annan läser eller skriver i den; enbart
läsningar är säkra. Skydda mapen med en mutex, låt en enda goroutine äga den och de andra nå den via
en kanal, eller använd `sync.Map` i de fall den är gjord för. Kör sedan testerna med `go test
-race`. För ett typiskt program kan race-detektorn öka minnesanvändningen fem till tio gånger och
körtiden två till tjugo gånger, och den hittar bara datakapplöpningar på kodvägar som faktiskt körs,
så en binär som byggts med `-race` och körs under realistisk last hittar fler.

**Goroutiner som startas i en loop arbetar alla på det sista elementet.** Före Go 1.22 hade en
`for`-loop en enda variabel som delades av alla iterationer, så en closure som fångade den såg det
värde variabeln råkade ha när goroutinen till slut kördes. Go 1.22 ger varje iteration en egen
variabel, men bara i moduler vars go.mod anger `go 1.22` eller senare, och äldre kod behåller sin
gamla betydelse även när en nyare verktygskedja bygger den. Höj `go`-raden och kör `go vet` och
testerna. Ett test som börjar fallera efter ändringen har ofta kontrollerat fel värde hela tiden.

**Ett bygge på en ny maskin stannar för att ladda ned en annan Go.** Sedan Go 1.21 är `go`-raden ett
krav, och när den installerade verktygskedjan är äldre än vad en modul begär hämtar kommandot `go`
den nyare som en modul och kör den från modulcachen. På en laptop är det bekvämt; i ett bygge utan
nätåtkomst eller med en låst containeravbild är det en överraskning. Installera den verktygskedja
som go.mod anger, och sätt miljövariabeln `GOTOOLCHAIN` när ett bygge måste använda en exakt
version.

## Läs mer

- [The Go Programming Language Specification](https://go.dev/ref/spec) — referensmanualen för varje
  konstruktion i språket, versionerad med varje utgåva.
- [Frequently Asked Questions (FAQ)](https://go.dev/doc/faq) — varför språket skapades,
  designbesluten bakom det och gåtorna om nil-fel och maps ovan.
- [Go 1 and the Future of Go Programs](https://go.dev/doc/go1compat) — kompatibilitetslöftet och de
  undantag det tillåter.
- [Release History](https://go.dev/doc/devel/release) — varje utgåva sedan Go 1, med stödpolicyn
  överst.
- [Data Race Detector](https://go.dev/doc/articles/race_detector) — hur du kör den, vad den fångar
  och vad den kostar.
- [Fixing For Loops in Go 1.22](https://go.dev/blog/loopvar-preview) — ändringen av loopvariabeln,
  varför den är knuten till go.mod och hur du testar gammal kod mot den.

<https://engineer.company/sv/glossary/go/>
