Vai al contenuto
eLearner.app
Modulo 10 · Lezione 1 di 546/50 nel corso~10 min
Lezioni del modulo (1/5)

Naming convention e stile

Go ha convenzioni di naming e stile forti e non negoziabili: il formatter ufficiale gofmt (e il suo super-set goimports) decide indentazione, spazi, ordine degli import. Discutere lo stile è considerato off-topic: si applica gofmt -w e si va avanti. Questo libera energia per problemi più interessanti.

Visibilità: maiuscola o minuscola

Non ci sono keyword public/private. La prima lettera del nome determina la visibilità:

  • Maiuscola → esportato fuori dal package (User, Login, MaxRetries).
  • Minuscola → privato al package (user, parseLine, defaultTimeout).

Vale per: tipi, funzioni, metodi, variabili, costanti, campi di struct.

Go
type User struct {
    Name  string  // esportato
    email string  // privato al package
}

Un campo "privato" della struct non è serializzato da encoding/json (vedi Modulo 8), e non è accessibile dai test in pkg_test.

CamelCase, mai snake_case

Niente underscore nei nomi multi-parola:

  • HTTPClient, userName, parseRequest
  • Http_Client, user_name, parse_request

Gli acronimi vanno tutti in maiuscolo (o tutti in minuscolo, se in scope privato):

  • URL, ID, HTML, JSON, parseURL, userID
  • Url, Id, Html, Json, parseUrl, userId
Go
type APIResponse struct {
    UserID  int
    HTMLURL string
}

Nomi corti per scope corti

Lo stile Go privilegia la brevità a parità di chiarezza in scope ristretti:

Go
// idiomatico
for i, v := range items { ... }
for k, v := range m { ... }

if err := f(); err != nil { ... }

func (s *Server) Serve(w http.ResponseWriter, r *http.Request) { ... }

Convenzioni stabilite:

  • i, j, k per indici di loop.
  • v per valori, k per chiavi.
  • r per *Request/io.Reader, w per Writer/ResponseWriter.
  • err per gli errori.
  • ctx per context.Context.
  • Receiver di metodi: 1–2 lettere coerenti in tutto il tipo (s *Server, u *User). Mai this o self.

Più lo scope è ampio, più il nome deve diventare descrittivo: una count locale va bene, una variabile esportata Count deve raccontare cosa conta.

Niente prefissi "I" sulle interfacce, niente suffissi "Impl"

Go
// idiomatico
type Reader interface { ... }
type fileReader struct { ... } // implementazione concreta

// non idiomatico
type IReader interface { ... }
type ReaderImpl struct { ... }

Le interfacce piccole prendono spesso il suffisso -er: Reader, Writer, Stringer, Closer. È un'eco del fatto che descrivono un comportamento (un solo metodo, idealmente).

Nomi di package

Un package ha un solo nome, breve, tutto minuscolo, senza underscore:

  • bytes, http, os, userauth
  • userAuth, user_auth, UserAuth

Il nome del package è il prefisso d'uso dei suoi simboli: bytes.Buffer, http.Client. Quindi user.User è ridondante: meglio rinominare il tipo (user.Account) o il package.

gofmt non si discute

gofmt impone:

  • Indentazione con tab (non spazi).
  • Brace { sulla stessa riga della firma.
  • Import in gruppi separati da riga vuota; goimports aggiunge anche import mancanti.
  • Spazi attorno agli operatori.

Esegui sempre prima del commit:

Bash
go fmt ./...
goimports -w .
go vet ./...

I linter (staticcheck, golangci-lint) aggiungono regole extra (variabili non usate, shadowing, comparazioni inutili, ...).

Esercizi

Esercizio#go.m10.l1.e1
Tentativi: 0Caricamento…

Rinomina la struct Http_Client in HTTPClient (e il campo Url in URL) seguendo le convenzioni Go sugli acronimi.

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Esercizio#go.m10.l1.e2
Tentativi: 0Caricamento…

Inverti la visibilità: rendi Username esportato (maiuscolo) e password privato (minuscolo).

Caricamento editor…

Soluzione disponibile dopo 3 tentativi

Quiz#go.m10.l1.e3
Pronto

Quale di questi nomi è idiomatico in Go per un tipo esportato 'server HTTP'?

Go
type ??? struct {}
Opzioni di risposta