如何在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中,一个关键的经验规则是使零值可用。a
Foo{}
如果没有指定字段,就不应该只是内爆;如果发生了内爆,那就是
Foo
设计中的一个缺陷。请看一下标准库;其中有很多很好的示例,说明如何在Go中创建一个好的类型。