Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何编写惯用构造函数_Go_Constructor - Fatal编程技术网

Go 如何编写惯用构造函数

Go 如何编写惯用构造函数,go,constructor,Go,Constructor,我对围棋中的构造器感到困惑。我见过的大多数构造函数都会返回一个结构,但根据 我相信“有效的Go”能提供好的想法,但这似乎没有遵循“接受接口,返回结构”的原则。我猜很多类型都实现了一个接口,仅此而已,所以在这种情况下,通常会看到返回接口的构造函数 另一个相关声明是接口应由使用者定义,但“通用性”表示接口由生产者定义 有人能澄清一下吗?在大多数情况下,构造函数返回具体类型(或指向类型的指针)。 在调用工厂函数或构建器函数时,如果底层具体类型满足该接口,则返回接口可能是一个好主意 考虑error接口,

我对围棋中的构造器感到困惑。我见过的大多数构造函数都会返回一个结构,但根据


我相信“有效的Go”能提供好的想法,但这似乎没有遵循“接受接口,返回结构”的原则。我猜很多类型都实现了一个接口,仅此而已,所以在这种情况下,通常会看到返回接口的构造函数

另一个相关声明是接口应由使用者定义,但“通用性”表示接口由生产者定义


有人能澄清一下吗?

在大多数情况下,构造函数返回具体类型(或指向类型的指针)。 在调用工厂函数或构建器函数时,如果底层具体类型满足该接口,则返回接口可能是一个好主意

考虑
error
接口,例如,当您调用
http.NewRequest
时,底层的集中式错误类型可以是
net.error
net.DNSError
等。现在试着想想,如果函数返回具体类型,您将如何创建这样一个没有
错误的api
接口?我能想到的唯一解决办法是为
net
包创建一个大规模错误类型,并添加额外信息字段,但维护、测试这种错误类型可能更难,更不用说内存膨胀了


无论您选择返回具体类型还是接口是一种设计选择,都有一些指导原则可以为常见场景提供解决方案。

正如前面所提到的,返回接口应该被视为例外

返回类型为
error
的错误(作为接口)是这些异常之一

返回表示未报告类型的接口是另一个例外。但是,为什么您会有一个描述未导出结构的导出接口,而不仅仅是一个导出结构

原因很简单,它允许您对结构的构造方式进行更高程度的控制

比较这两段代码:

type MyType struct {
    MyField string
}

func NewMyType(value string) MyType {
    return MyType{value}
}

func (t MyType) MyMethod() string {
    return t.MyField
}
在第一种情况下,我可以这样做:
myVar:=MyType{}
,而在第二种情况下,我无法这样做,我被迫使用提供的构造函数。第一种情况还允许在创建后修改字段值,这在第二种情况下是不允许的。使字段未报告将解决第二部分,而不是第一部分

这个例子显然微不足道,但能够构造无效的结构可能会产生可怕的影响。通过使用特定的构造函数,您可以确保对象处于有效的启动状态,并且只需要确保它始终处于有效状态。如果无法确保,则可能需要在每个方法开始时检查它是否处于有效状态


例如考虑一个DB请求。它需要一个数据库连接。如果用户能够在没有DB连接的情况下创建DB请求,则必须检查它在每个方法中是否有效。如果您强制他使用构造函数,您可以在创建时检查并完成。

“接受接口,返回结构”不是规则。这是一个指导方针。有时应该违反它。例如,我们总是返回
error
接口,而不是它们的具体类型。构造函数可以返回具体类型,因为它的全部任务是返回特定类型的实例。它仍然可以由期望接口的使用者使用,并存储在接口变量中或在接口参数中传递。有效Go指的是返回接口,在该节的特定上下文中-“如果某个类型的存在只是为了实现一个接口,并且永远不会将方法导出到该接口之外,则无需导出该类型本身。仅导出接口可以清楚地表明,除了接口中所描述的以外,该值没有任何有趣的行为。“例如,这是专门针对未报告类型的构造函数的。在几乎所有情况下,构造函数都构造非接口类型。您似乎很少考虑这种情况。在Go中,您从“real”开始(即非接口类型)并在需要时引入接口。是的,既然您提到了它,我意识到错误是何时返回接口的一个很好的例子。可能到目前为止我对接口的经验太有限。主要原因(如果不是唯一原因的话)我定义接口的原因是为了能够以一种方便的方式进行模拟。在这种情况下,具体类型不会提供比接口更多的方法,因此我没有遇到返回接口的构造函数的任何问题(除了我不高兴我可能以错误的方式进行模拟)。
type MyType interface {
    MyMethod() string
}

type myType struct {
    MyField string
}

func NewMyType(value string) MyType {
    return myType{value}
}

func (t myType) MyMethod() string {
    return t.MyField
}