มีคำตอบ / เทคนิคหลายประการสำหรับคำถามด้านล่าง:
- จะตั้งค่าเริ่มต้นเป็นโครงสร้าง golang ได้อย่างไร?
- วิธีการเริ่มต้นโครงสร้างใน golang
ฉันมีคำตอบสองสามข้อ แต่จำเป็นต้องมีการอภิปรายเพิ่มเติม
มีคำตอบ / เทคนิคหลายประการสำหรับคำถามด้านล่าง:
ฉันมีคำตอบสองสามข้อ แต่จำเป็นต้องมีการอภิปรายเพิ่มเติม
คำตอบ:
แนวคิดหนึ่งที่เป็นไปได้คือการเขียนฟังก์ชันตัวสร้างแยกต่างหาก
//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
และแม้กระทั่งฟิลด์Text
และแต่ก็ไม่ได้ส่งออกประเภทที่DefaultText
struct something
reflect.New()
เป็นต้น) คาดว่าจะไม่ทราบเกี่ยวกับฟังก์ชันโรงงานที่มีชื่อพิเศษของคุณ ในกรณีนั้นและการเปลี่ยนภาษาสั้น ๆ เองฉันคิดว่ามีเพียงอินเทอร์เฟซ (ที่ไลบรารีตรวจสอบได้)
บังคับเมธอดเพื่อรับโครงสร้าง (วิธีตัวสร้าง)
จากโพสต์นี้ :
การออกแบบที่ดีคือการทำให้ประเภทของคุณไม่ถูกส่งออก แต่ให้ฟังก์ชันตัวสร้างที่ส่งออก
NewMyType()
ซึ่งคุณสามารถเริ่มต้นโครงสร้าง / ประเภทของคุณได้อย่างถูกต้อง ส่งคืนประเภทอินเทอร์เฟซไม่ใช่ประเภทคอนกรีตและอินเทอร์เฟซควรมีทุกสิ่งที่คนอื่นต้องการทำกับคุณค่าของคุณ และประเภทคอนกรีตของคุณต้องใช้อินเทอร์เฟซนั้นแน่นอน
ซึ่งสามารถทำได้โดยการทำให้ชนิดไม่ถูกส่งออก คุณสามารถส่งออกฟังก์ชัน NewSomething และแม้แต่ช่อง Text และ DefaultText ได้ แต่อย่าส่งออกโครงสร้างบางอย่าง
อีกวิธีหนึ่งในการปรับแต่งสำหรับโมดูลของคุณเองคือการใช้Config struct เพื่อตั้งค่าเริ่มต้น (ตัวเลือกที่ 5 ในลิงค์) ไม่ใช่วิธีที่ดีแม้ว่า
ปัญหาหนึ่งของตัวเลือกที่ 1 ในคำตอบจาก Victor Zamanian คือหากไม่ได้ส่งออกประเภทดังกล่าวผู้ใช้แพ็คเกจของคุณจะไม่สามารถประกาศว่าเป็นประเภทสำหรับพารามิเตอร์ฟังก์ชันได้วิธีหนึ่งในการแก้ไขปัญหานี้คือการส่งออกอินเทอร์เฟซแทน โครงสร้างเช่น
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
}
ซึ่งช่วยให้เราสามารถประกาศประเภทพารามิเตอร์ของฟังก์ชันโดยใช้อินเทอร์เฟซผู้สมัครที่ส่งออก ข้อเสียเดียวที่ฉันเห็นจากโซลูชันนี้คือวิธีการทั้งหมดของเราจำเป็นต้องได้รับการประกาศในคำจำกัดความของอินเทอร์เฟซ แต่คุณสามารถโต้แย้งได้ว่านั่นเป็นแนวทางปฏิบัติที่ดี
มีวิธีการทำเช่นนี้กับแท็กซึ่งอนุญาตให้มีค่าเริ่มต้นหลายค่า
สมมติคุณมี struct ต่อไปนี้มี 2 เริ่มต้นแท็กdefault0และdefault1
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
ตอนนี้สามารถตั้งค่าเริ่มต้นได้
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...
}
นี่คือโปรแกรมที่สมบูรณ์ในสนามเด็กเล่น
หากคุณสนใจในตัวอย่างที่ซับซ้อนมากขึ้นให้พูดโดยใช้ชิ้นส่วนและแผนที่จากนั้นดูที่creasty / defaultse
จากhttps://golang.org/doc/effective_go.html#composite_literals :
บางครั้งค่าศูนย์ไม่ดีพอและจำเป็นต้องมีการเตรียมใช้งานคอนสตรัคเตอร์เนื่องจากในตัวอย่างนี้ได้มาจากระบบปฏิบัติการแพคเกจ
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"`
}