最初,我认为我只使用指针作为可选的struct字段,在最初构建的情况下,这些字段可能是nil。
随着我的代码的发展,我在我的模型上编写了不同的层 - 用于xml和json(un)编组。在这些情况下,即使是我认为总是需要的字段(Id,Name等)实际上对某些图层来说也是可选的。
最后我在所有字段前放了一个*,所以int变成了* int,string变成了* string等。
现在我想知道我是不是更好地不如此夸大我的代码?我可能会重复代码,我发现它相当丑陋 - 但也许比使用指针用于所有结构域更有效?
所以我的问题是,这是否会变成一种反模式,只是一种糟糕的习惯,或者从性能的角度来看,这种增加的灵活性是否会产生成本?
EG。你能否提出坚持选项A的好理由:
type MyStruct struct {
Id int
Name string
ParentId *int
// etc.. only pointers where NULL columns in db might occur
}
超过此选项B:
type MyStruct struct {
Id *int
Name *string
ParentId *int
// etc... using *pointers for all fields
}
对结构进行建模的最佳实践方法是纯粹的数据库/列视角,或者例如,如果你有:
func (m *MyStruct) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var v struct {
XMLName xml.Name `xml:"myStruct"`
Name string `xml:"name"`
Parent string `xml:"parent"`
Children []*MyStruct `xml:"children,omitempty"`
}
err := d.DecodeElement(&v, &start)
if err != nil {
return err
}
m.Id = nil // adding to db from xml, there's initially no Id, until after the insert
m.Name = v.Name // a parent might be referenced by name or alias
m.ParentId = nil // not by parentId, since it's not created yet, but maybe by nesting elements like you see above in the V struct (Children []*ContentType)
// etc..
return nil
}
此示例可能是您要将XML中的元素添加到数据库的场景的一部分。这里的ID通常没有意义,所以我们在名称或其他别名上使用嵌套和引用。在INSERT查询后获取id之前,不会设置结构的Id。然后使用该ID我们可以遍历层次结构到子元素等。
这将允许我们只有1个MyStruct,并使用例如。不同的POST http请求处理函数,取决于调用是来自表单输入,还是xml导入,嵌套层次结构和不同关系可能需要进行不同的处理。
最后我想我要问的是:
你最好分离db,xml和json操作(或者你能想到的任何场景)的结构模型,而不是一直使用struct field指针,所以我们可以将模型重用于不同但相关的东西?
答案 0 :(得分:10)
除了可能的性能(更多指针=更多用于GC扫描的东西),安全性(零指针取消引用),便利性(s.a = 2
vs s.a = new(int); *s.a = 42
)和内存惩罚(a {{1是一个字节,bool
是四到八个),有一件事在全指针方法中真的困扰我。它违反了Single responsibility principle。
您从XML或DB获得的*bool
是否与MyStruct
相同?如果数据库架构会发生变化怎么办?如果XML改变格式怎么办?如果您还需要将其解组为JSON,但方式略有不同,该怎么办?如果你需要同时支持所有这些(以及多个版本!)该怎么办?
当你试图让一件事做很多事时,你会感到很痛苦。有一种全能型而非N型专用型非常值得吗?