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

Dat*_*sik 4 go

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

func Foo() {
    return foo()
}

func foo() {
   log.Println("Hello")
}
Run Code Online (Sandbox Code Playgroud)

为什么不将日志移到导出的函数中并去掉多余的行?显然是有原因的,但如果你可以在任何地方使用导出的一个,我真的看不到一个。谢谢!

实施例在这里它在生产中使用

Ami*_*pta 5

你提到了几个例子。第一个例子(https://github.com/yohcop/openid-go/blob/master/verify.go#L11-L13):

func Verify(uri string, cache DiscoveryCache, nonceStore NonceStore) (id string, err error) {
    return verify(uri, cache, urlGetter, nonceStore)
}
Run Code Online (Sandbox Code Playgroud)

您可以看到未导出的verify函数需要一个额外的urlGetter参数。这可能是这个包的客户端不能或不应该提供的东西。导出的函数决定了包的客户端可以/应该如何使用它;非导出函数的签名反映了执行任何业务逻辑所需的依赖项verify

第二个例子(https://github.com/golang/oauth2/blob/master/oauth2.go#L259-L266):

func StaticTokenSource(t *Token) TokenSource {
    return staticTokenSource{t}
}

// staticTokenSource is a TokenSource that always returns the same Token.
type staticTokenSource struct {
    t *Token
}
Run Code Online (Sandbox Code Playgroud)

这限制了客户端如何构造staticTokenSource: 只有一种方法可以通过StaticTokenSource构造函数来完成,并且不能直接通过结构体来完成。出于多种原因,这可能很有用,例如输入验证。在这种情况下,您希望知道客户端无法改变t对象上的字段的安全性,为了做到这一点,您不t导出该字段。但是当它未导出时,客户端将无法直接构造 struct 文字,因此您必须提供一个构造函数。

一般来说,它使您的代码更容易推理何时可以限制事物的访问、构造或变异方式。Golang 包为您提供了一种很好的机制来封装业务逻辑模块。考虑软件的概念组件以及它们的接口应该是什么是个好主意。什么真正需要暴露给使用给定组件的客户端代码?只有真正需要导出的东西才应该是。

进一步阅读:组织 Go 代码