如何在golang中隐藏默认类型构造函数?
我有这个问题的原因是我经常犯错误,忘记给结构的字段指定一个值,然后编译器就可以了,但是零值会导致错误 这里有一个例子。假设我在包中定义了一个类型如何在golang中隐藏默认类型构造函数?,go,Go,我有这个问题的原因是我经常犯错误,忘记给结构的字段指定一个值,然后编译器就可以了,但是零值会导致错误 这里有一个例子。假设我在包中定义了一个类型Foo: package types type Foo struct { RequiredField1 string RequiredField2 string } 它是公开的,有两个字段,我希望在创建Foo结构时指定这两个字段 然后我可以在我的主要功能中导入并使用它,如下所示: package main import ( "githu
Foo
:
package types
type Foo struct {
RequiredField1 string
RequiredField2 string
}
它是公开的,有两个字段,我希望在创建Foo
结构时指定这两个字段
然后我可以在我的主要功能中导入并使用它,如下所示:
package main
import (
"github.com/foo/bar/types"
)
func main() {
f := &Foo{
RequiredField1: "fff",
}
fmt.Printf("f.RequiredField2: %v", f.RequiredField2)
}
这会导致一个错误,因为我忘记指定所需的RequiredField2
。我经常做这种虫子:p
现在,为了利用编译并防止这个错误,我为Foo
创建了一个构造函数,并请求所需的值
func NewFoo(field1 string, field2 string) *Foo {
return &Foo{Field1: field1, Field2: field2}
}
因此,如果我忘记传递字段2
,编译器将不会编译我的代码:
func main() {
f := NewFoo("foo")
fmt.Printf("f.Field2: %v", f.Field2)
}
生成将失败:
./prog.go:18:13: not enough arguments in call to NewFoo
have (string)
want (string, string)
现在的问题是:如何阻止外部调用方(来自其他名称空间的调用方)调用Foo
的默认构造函数,即&Foo
,并强制它们使用NewFoo
如果可以,那么我就安全了,因为NewFoo是创建Foo
类型的唯一方法,编译器可以帮助我确保调用它时所有字段都存在
如何在golang中隐藏默认类型构造函数
对于导出的类型,不能
习惯吧,这在现实生活中不是问题
(对于未报告的类型,只需提供一个func NewUnexportedType(…)unexportedType
)
在设计数据结构时,将
无需进一步初始化即可使用每种类型的零值
我们经常需要更改类型定义,比如添加更多字段
这就是为什么应该使struct字段的零值非常重要。这种行为是故意的。例如,它用于维护Go 1兼容性保证。您可以通过使Foo类型未报告来避免此问题 您可以创建一个导出的接口,该接口具有Foo-type执行的所有方法 例如:-
type Foo interface{
DoSomething()
}
type foo struct{
RequiredField1 string
RequiredField2 string
}
func NewFoo(requiredField1 string,requiredField2 string)*foo{
return &foo{
RequiredField1:requiredField1,
RequiredField2:requiredField2,
}
}
func (f *foo)DoSomething(){
// your implementation
}
通过这种方式,所有调用者都可以访问它,但如果没有NewFoo函数,就无法创建foo。这实际上是一个非常常见的问题,因为我们经常需要更改类型定义,比如添加更多字段,然后忘记在某处更新调用者以指定缺少的值,最终导致错误。每当我看到
&foo{requirefeld1:“fff”}
,我很紧张,因为我不知道这是否包括所有必需的字段。@LeoZhang,如果你在结构类型中添加了一个字段,而该字段的值为零时会打断你的内容,那么你就做了一个中断性的更改。不要这样做(tm)。而是添加一个新类型。请参阅。但实际上最重要的规则是有用的零值。感谢您的回答。您不能。记住,在Go中,一个关键的经验规则是使零值可用。aFoo{}
如果没有指定字段,就不应该只是内爆;如果发生了内爆,那就是Foo
设计中的一个缺陷。请看一下标准库;其中有很多很好的示例,说明如何在Go中创建一个好的类型。