Aşağıdaki soruya birden fazla cevap / teknik vardır:
- Golang yapılarına varsayılan değerler nasıl ayarlanır?
- Golang'daki yapıları başlatma
Birkaç cevabım var ama daha fazla tartışma gerekiyor.
Aşağıdaki soruya birden fazla cevap / teknik vardır:
Birkaç cevabım var ama daha fazla tartışma gerekiyor.
Yanıtlar:
Olası bir fikir, ayrı yapıcı işlevi yazmaktır
//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
ve hatta alanları Text
ve DefaultText
, ama sadece yapı türü ihracat yapmamaktadır something
.
reflect.New()
örneğin, aracılığıyla ), özel olarak adlandırılmış fabrika işlevinizi bilmeniz beklenemezdi. Bu durumda ve dilin değiştirilmesinin kısa olmasının, sadece (kütüphanenin kontrol edebileceği bir arayüz) yapabileceğini düşünüyorum.
Yapıyı almak için bir yöntemi zorlayın (yapıcı yolu).
Gönderen bu yazı :
İyi bir tasarım, türünüzü dışa aktarmamaktır, ancak yapınızı
NewMyType()
/ türünüzü düzgün bir şekilde başlatabileceğiniz gibi dışa aktarılmış bir yapıcı işlevi sağlamaktır . Ayrıca somut bir türü değil, bir arayüz türü döndürün ve arayüz, başkalarının değerinizle yapmak istediği her şeyi içermelidir. Ve somut tipiniz elbette bu arayüzü uygulamalıdır.
Bu, tipin kendisini dışa aktarılarak yapılabilir. NewSomething işlevini ve hatta Text ve DefaultText alanlarını dışa aktarabilirsiniz, ancak yapı türü bir şeyi dışa aktarmayın.
Kendi modülünüz için özelleştirmenin başka bir yolu, varsayılan değerleri ayarlamak için bir Config yapısı kullanmaktır (bağlantıdaki Seçenek 5). Ama iyi bir yol değil.
Victor Zamanian'ın yanıtında 1. seçenekle ilgili bir sorun, tür dışa aktarılmazsa, paketinizin kullanıcılarının bunu işlev parametreleri vb. Türü olarak bildirememesidir. Bunun bir yolu, yapı örneğin
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
}
Bu, dışa aktarılan Aday arayüzünü kullanarak işlev parametre türlerini bildirmemizi sağlar. Bu çözümden görebileceğim tek dezavantaj, tüm yöntemlerimizin arayüz tanımında bildirilmesi gerektiğidir, ancak bunun yine de iyi bir uygulama olduğunu iddia edebilirsiniz.
Bunu, birden çok varsayılana izin veren etiketlerle yapmanın bir yolu vardır.
2 Varsayılan etiketleri ile, aşağıdaki yapı var varsayalım default0 ve default1 .
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Artık varsayılanları ayarlamak mümkün.
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...
}
İşte bir oyun alanındaki tam program .
Daha karmaşık bir örnekle ilgileniyorsanız, dilimler ve haritalarla söyleyin, o zaman creasty / defaultultse'a bir göz atın
Gönderen https://golang.org/doc/effective_go.html#composite_literals :
Bazen sıfır değeri yeterince iyi değildir ve bu örnekte olduğu gibi os paketinden türetilen bir başlangıç yapıcısı gereklidir.
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"`
}