Ada beberapa jawaban / teknik untuk pertanyaan di bawah ini:
- Bagaimana cara mengatur nilai default ke struct golang?
- Cara menginisialisasi struct di golang
Saya punya beberapa jawaban tetapi diskusi lebih lanjut diperlukan.
Ada beberapa jawaban / teknik untuk pertanyaan di bawah ini:
Saya punya beberapa jawaban tetapi diskusi lebih lanjut diperlukan.
Jawaban:
Satu ide yang mungkin adalah menulis fungsi konstruktor yang terpisah
//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
}
NewSomething
dan bahkan bidang Text
dan DefaultText
, tapi jangan ekspor jenis struct something
.
reflect.New()
, misalnya), itu tidak bisa diharapkan untuk mengetahui tentang fungsi pabrik Anda yang bernama khusus. Dalam hal itu, dan pendeknya bahasa itu sendiri sedang diubah, hanya antarmuka (yang perpustakaan dapat memeriksa) akan melakukan, saya pikir.
Paksa metode untuk mendapatkan struct (cara konstruktor).
Desain yang bagus adalah membuat tipe Anda tidak diekspor, tetapi menyediakan fungsi konstruktor yang diekspor seperti NewMyType () di mana Anda dapat menginisialisasi struct / tipe Anda dengan benar. Kembalikan juga tipe antarmuka dan bukan tipe konkret, dan antarmuka tersebut harus berisi semua hal yang ingin dilakukan orang lain dengan nilai Anda. Dan tipe konkret Anda harus mengimplementasikan antarmuka itu tentu saja.
Ini dapat dilakukan dengan hanya membuat tipe itu sendiri tidak diekspor. Anda dapat mengekspor fungsi NewSomething dan bahkan bidang Teks dan DefaultText, tetapi jangan ekspor sesuatu jenis struct
Cara lain untuk menyesuaikannya untuk modul Anda sendiri adalah dengan menggunakan struct Config untuk menetapkan nilai default (Opsi 5 di tautan) Namun bukan cara yang baik.
Satu masalah dengan opsi 1 dalam jawaban dari Victor Zamanian adalah bahwa jika tipe tidak diekspor maka pengguna paket Anda tidak dapat mendeklarasikannya sebagai tipe untuk parameter fungsi dll. Salah satu cara untuk mengatasi ini adalah dengan mengekspor antarmuka bukan misalnya struct
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
}
Yang memungkinkan kita mendeklarasikan tipe parameter fungsi menggunakan antarmuka Kandidat yang diekspor. Satu-satunya kelemahan saya dapat melihat dari solusi ini adalah bahwa semua metode kami perlu dideklarasikan dalam definisi antarmuka, tetapi Anda bisa berpendapat bahwa itu adalah praktik yang baik.
Votes unit32
mungkin seharusnyaVotes uint32
Ada cara untuk melakukan ini dengan tag, yang memungkinkan untuk beberapa default.
Asumsikan Anda memiliki struct berikut, dengan 2 tag default default0 dan default1 .
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Sekarang mungkin untuk Mengatur default.
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...
}
Inilah program lengkapnya di taman bermain .
Jika Anda tertarik pada contoh yang lebih kompleks, katakan dengan irisan dan peta, lalu, lihat creasty / defaultse
Dari https://golang.org/doc/effective_go.html#composite_literals :
Terkadang nilai nol tidak cukup baik dan konstruktor inisialisasi diperlukan, seperti dalam contoh ini berasal dari paket os.
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"`
}