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.
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
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:
// 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, kper indici di loop.vper valori,kper chiavi.rper*Request/io.Reader,wperWriter/ResponseWriter.errper gli errori.ctxpercontext.Context.- Receiver di metodi: 1–2 lettere coerenti in tutto il tipo (
s *Server,u *User). Maithisoself.
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"
// 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;
goimportsaggiunge anche import mancanti. - Spazi attorno agli operatori.
Esegui sempre prima del commit:
go fmt ./...
goimports -w .
go vet ./...I linter (staticcheck, golangci-lint) aggiungono regole extra (variabili non usate, shadowing, comparazioni inutili, ...).
Esercizi
Rinomina la struct Http_Client in HTTPClient (e il campo Url in URL) seguendo le convenzioni Go sugli acronimi.
Soluzione disponibile dopo 3 tentativi
Inverti la visibilità: rendi Username esportato (maiuscolo) e password privato (minuscolo).
Soluzione disponibile dopo 3 tentativi
Quale di questi nomi è idiomatico in Go per un tipo esportato 'server HTTP'?
type ??? struct {}