从函数返回未导出的类型

def*_*ode 16 go

从导出的函数返回未导出的类型是否被认为是不好的样式?
当我使用它时,我发现它只会产生问题.

一个更好的问题可能是:何时从导出的函数返回未导出的类型是个好主意.

Bre*_*den 10

我想说从导出的函数返回一个未导出的变量没有任何问题.根据定义,这就是访问者.

也就是说,我只会在每次需要访问未导出的变量时需要发生某些逻辑的情况下这样做.

编辑:我希望我理解你澄清的问题.

如果你有一个未被移植的type user struct{}并且你将它归还NewUser(),那是否适合你的用例?如果是这样,那么这是一个工厂设计模式,如果您不希望第三方开发人员直接创建user类型对象,则在Go中很有用.这样,您的"构造函数"或"工厂"是获取新实例的唯一位置.type user struct{}可能需要返回一个,NewUser()因为外部调用代码不知道类型,但我现在无法确认.

那么,这是"糟糕的风格"吗?我要说这取决于需要克服哪些挑战.

  • 要记住的一件事是 godoc 忽略私有结构,因此,例如,如果这是一个开源项目并依赖 godoc.org 来提供文档,则相关结构不会显示在那里。 (3认同)
  • 我已经澄清了这个问题。我的意思是询问未导出的类型而不是变量。 (2认同)

dro*_*sep 8

我认为值得为其他在这个问题上发生的人发表另一种观点。解决此问题的更好方法是,如果用户打算以任何方式与其交互,则为该类型定义一个实际导出的接口,或者只是不返回未导出的类型,这样您就不必解决这种情况。这主要是一个设计问题,让我解释一下。

虽然从技术上讲可以返回未导出的类型(如上所示),但必须interface{}为该包外部的代码分配该类型。对我来说,这是一种代码味道,也是我在代码审查中会认真质疑的问题。同样,我会质疑接受未导出参数的导出函数/方法。

我遇到的最大问题是函数签名没有清楚地传达其使用范围。它是一个内部函数,因为它返回一个内部类型?由于它是导出函数,是否意味着由外部消费者调用?实在是很暧昧。

另外,虽然返回 aninterface{}使该类型可转移,但它也在一定程度上破坏了类型安全。如果返回的目的interface{}是防止用户在将数据传递到 API 的另一部分之前更改数据,则辅助 API 需要在interface{}使用它之前接受并检查有效类型。而且代码很臭,编译器无法帮助我们处理错误的调用。


Mik*_*raf 7

当您返回未导出的类型时,Golang 的 linters 会返回警告,所以我想说虽然从技术上讲这是可能的,但也不应鼓励。1

一个原因是一些接收未导出类型的代码不能将其用于各种“签名”(例如:类型、函数),而不将其键入为接口(例如:interface{} 或其他方式)

例如:

package people
type me string
func NewMe() me {
    return "me"
}

// in main.go
package main

type eff struct {
    m *people.me  // <-- cant do this
}

func main() {
   var m people.me // <-- cant do this
   m2 := people.NewMe() // can do this
}
Run Code Online (Sandbox Code Playgroud)