Modulelessen (5/5)
Het constructorpatroon 'Nieuw...'
Go heeft geen zoekwoord constructor. De conventie is een fabriek
functie die een correct geïnitialiseerde waarde of aanwijzer retourneert. Door
naam wordt meestal NewT (of NewXxx) genoemd.
Basispatroon: NewT
type User struct {
Name string
Age int
}
func NewUser(name string, age int) *User {
return &User{Name: name, Age: age}
}
u := NewUser("Ada", 36)
fmt.Println(u.Name)Voordelen ten opzichte van de directe letterlijke &User{...}:
- Je centraliseert validatie en standaardinstellingen.
- U kunt niet-geëxporteerde velden hebben en deze alleen vanuit de constructor invullen.
- U kunt de implementatie wijzigen zonder bellers te verbreken.
Constructor met validatie: (*T, fout)
Wanneer initialisatie kan mislukken, retourneert u (*T, error):
import "errors"
func NewUser(name string, age int) (*User, error) {
if name == "" {
return nil, errors.New("nome obbligatorio")
}
if age < 0 {
return nil, errors.New("eta non valida")
}
return &User{Name: name, Age: age}, nil
}
u, err := NewUser("Ada", 36)
if err != nil {
// handle...
}Dit is het idiomatische patroon voor elke constructor met randvoorwaarden: db-verbinding, bestandshandle, serverconfiguratie, etc.
Meerdere constructeurs
Als u meerdere 'manieren' heeft om te construeren, gebruik dan beschrijvende namen:
func NewUser(name string) *User { ... }
func NewUserFromJSON(data []byte) (*User, error) { ... }
func NewAdmin() *User { ... }Geen overbelasting in Go: de naam is ondubbelzinnig.
Functionele opties (geavanceerde blik)
Als er veel optionele parameters zijn, is het idiomatische patroon dat wel "functionele opties":
type Option func(*Server)
func WithPort(p int) Option {
return func(s *Server) { s.Port = p }
}
func WithTLS(cert, key string) Option {
return func(s *Server) { s.Cert, s.Key = cert, key }
}
func NewServer(opts ...Option) *Server {
s := &Server{Port: 8080} // default
for _, opt := range opts {
opt(s)
}
return s
}
s := NewServer(WithPort(9000), WithTLS("c.pem", "k.pem"))Het is uitgebreider dan een letterlijke tekst, maar schaalt goed met veel optionele opties
parameters en behoudt de achterwaartse compatibiliteit (door een nieuwe Option toe te voegen
verbreekt geen bestaande bellers).
Wanneer je GEEN constructor nodig hebt
Als de nulwaarde van het type al nuttig is, laat de beller dan de
direct letterlijk. Canonisch voorbeeld: sync.Mutex heeft geen constructor,
var m sync.Mutex is al een gebruiksklare mutex. Hetzelfde voor bytes.Buffer.
De regel is: "Maak de nulwaarde nuttig". Als je kunt, nee verplichte constructeur.
Probeer het
Schrijf de fabrieksfunctie NewUser(name string, age int) *User die &User{Name: name, Age: age} retourneert.
Toon hint
Gebruik de letterlijke `&Gebruiker{...}` om een pointer terug te geven.
Oplossing beschikbaar na 3 pogingen
Verander NewUser in (naamreeks) (*Gebruiker, fout): if naam == '' retourneer nul, fouten.New('nome obbligatorio').
Toon hint
Als er voorwaarden zijn, retourneert u (*T, fout) en retourneert u nul + fout bij falen.
Oplossing beschikbaar na 3 pogingen
Wat is de idiomatische conventie voor constructors in Go?
// Which signature is more idiomatic?Samenvatten
- Nee
constructor: gebruik eenNewTfunctie (ofNewin hetzelfde pakket). - Retourneer
*Tvoor het eenvoudige geval;(*T, error)met randvoorwaarden of validatie. - Bij fout: retourneer
nilals aanwijzer en de verklarende fout als tweede waarde. - Geen overbelasting; gebruik beschrijvende namen (
NewUserFromJSON,NewAdmin). - "Maak de nulwaarde nuttig": als je kunt, is de constructor niet nodig.
- Geavanceerd patroon voor veel optionele parameters: functionele opties.