Esistono più risposte / tecniche alla seguente domanda:
- Come impostare i valori predefiniti per le strutture Golang?
- Come inizializzare le strutture in Golang
Ho un paio di risposte ma sono necessarie ulteriori discussioni.
Esistono più risposte / tecniche alla seguente domanda:
Ho un paio di risposte ma sono necessarie ulteriori discussioni.
Risposte:
Un'idea possibile è scrivere una funzione di costruzione separata
//Something is the structure we work with
type Something struct {
Text string
DefaultText string
}
// NewSomething create new instance of Something
func NewSomething(text string) Something {
something := Something{}
something.Text = text
something.DefaultText = "default text"
return something
}
NewSomethinge persino i campi Texte DefaultText, ma non esportare il tipo di struttura something.
reflect.New(), ad esempio), non ci si può aspettare che conoscano la funzione di fabbrica con un nome speciale. In quel caso, e a parte la lingua stessa che viene cambiata, solo un'interfaccia (che la biblioteca potrebbe verificare) farebbe, penso.
Forzare un metodo per ottenere la struttura (il modo costruttore).
Un buon progetto è rendere il tuo tipo non esportato, ma fornire una funzione di costruzione esportata come NewMyType () in cui puoi inizializzare correttamente la tua struttura / tipo. Restituisce anche un tipo di interfaccia e non un tipo concreto e l'interfaccia dovrebbe contenere tutto ciò che gli altri vogliono fare con il tuo valore. E il tuo tipo concreto deve implementare quell'interfaccia ovviamente.
Questo può essere fatto semplicemente rendendo il tipo stesso non esportato. Puoi esportare la funzione NewSomething e persino i campi Text e DefaultText, ma non esportare qualcosa del tipo struct
Un altro modo per personalizzarlo per il proprio modulo consiste nell'utilizzare una struttura di configurazione per impostare i valori predefiniti (opzione 5 nel collegamento).
Un problema con l'opzione 1 in risposta di Victor Zamanian è che se il tipo non viene esportato, gli utenti del pacchetto non possono dichiararlo come tipo per i parametri della funzione ecc. Un modo per aggirare questo sarebbe esportare un'interfaccia anziché il struct ad es
package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
Name string
Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
return candidate{name, 0} // enforce the default value here
}
Ciò ci consente di dichiarare i tipi di parametri di funzione utilizzando l'interfaccia Candidate esportata. L'unico svantaggio che posso vedere da questa soluzione è che tutti i nostri metodi devono essere dichiarati nella definizione dell'interfaccia, ma si potrebbe sostenere che questa è comunque una buona pratica.
Votes unit32probabilmente dovrebbe essereVotes uint32
C'è un modo per farlo con i tag, che consente impostazioni predefinite multiple.
Si supponga di avere il seguente struct, con le etichette predefinite 2 DEFAULT0 e Default1 .
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Ora è possibile impostare le impostazioni predefinite.
func main() {
ptr := &A{}
Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...
Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}
Ecco il programma completo in un parco giochi .
Se sei interessato a un esempio più complesso, ad esempio con sezioni e mappe, dai un'occhiata a creasty / defaultse
Da https://golang.org/doc/effective_go.html#composite_literals :
A volte il valore zero non è abbastanza buono ed è necessario un costruttore di inizializzazione, come in questo esempio derivato dal pacchetto operativo.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
type Config struct {
AWSRegion string `default:"us-west-2"`
}