Go 为什么包通过导出函数返回非导出函数来导出非导出函数

Go 为什么包通过导出函数返回非导出函数来导出非导出函数,go,Go,为什么有些包声明两个相等的函数唯一的区别是一个导出,另一个不导出,但导出的一个只返回未导出的函数,如下所示: func Foo() { return foo() } func foo() { log.Println("Hello") } 为什么不把日志移到导出函数中,去掉多余的一行呢?显然,这是有原因的,但如果你能在任何地方都使用导出的,我真的看不到原因。谢谢 生产中使用it的示例您提到了几个示例。第一个例子(): 可以看到,unexportedverify函数使用了一个额外的

为什么有些包声明两个相等的函数唯一的区别是一个导出,另一个不导出,但导出的一个只返回未导出的函数,如下所示:

func Foo() {
    return foo()
}

func foo() {
   log.Println("Hello")
}
为什么不把日志移到导出函数中,去掉多余的一行呢?显然,这是有原因的,但如果你能在任何地方都使用导出的,我真的看不到原因。谢谢


生产中使用it的示例

您提到了几个示例。第一个例子():

可以看到,unexported
verify
函数使用了一个额外的
urlGetter
参数。这可能是此包的客户端无法或不应提供的内容。导出函数确定包的客户端可以/应该如何使用它;非导出函数的签名反映了执行任何业务逻辑
verify
所需的依赖关系

第二个例子()

这限制了客户端如何构造
staticTokenSource
:只有一种方法可以通过
staticTokenSource
构造函数来实现,而不能直接通过struct literal来实现。出于许多原因,这可能很有用,例如输入验证。在这种情况下,您希望安全地知道客户机不能对对象上的
t
字段进行变异,为此,您将
t
字段保留为未报告。但是当它未被报告时,客户端将无法直接构造struct literal,因此必须提供构造函数

一般来说,它使您的代码更容易解释何时可以限制如何访问、构造或修改内容。Golang包为您提供了封装业务逻辑模块的良好机制。考虑软件的概念组件以及它们的接口应该是什么是一个好主意。使用给定组件的客户端代码真正需要公开什么?只有真正需要出口的东西才应该出口


进一步阅读:

Scientific在这里大胆猜测,但可能是为了使将来的重构更容易。如果您稍后决定“您知道,我希望这个函数是可导出的”,那么您只需编写
Foo
,而不是重构并更改代码中已有的对
Foo
的所有引用。反之亦然。有什么例子吗?我以前从未见过这个例子。Example@codingpickle如果这是你知道的唯一一个例子,那么我建议问问作者。作者的电子邮件地址列在他们的Github配置文件页面上。在您的示例中,这两个函数并不相等
verify
接受一个附加的
urlGetter
参数,该参数是包的本地参数,包的客户端不必构造或了解它。谢谢!完全有道理。
func Verify(uri string, cache DiscoveryCache, nonceStore NonceStore) (id string, err error) {
    return verify(uri, cache, urlGetter, nonceStore)
}
func StaticTokenSource(t *Token) TokenSource {
    return staticTokenSource{t}
}

// staticTokenSource is a TokenSource that always returns the same Token.
type staticTokenSource struct {
    t *Token
}