从导出的函数返回未导出的类型是否被视为不良样式?
当我使用它时,我发现它只会产生问题。
更好的问题可能是:何时从导出的函数返回未导出的类型是个好主意。
答案 0 :(得分:8)
我想说从导出的函数返回一个未导出的变量没有错。根据定义,这就是访问者。
尽管如此,我只会在每次需要访问未导出变量时需要发生某些逻辑的情况下这样做。
编辑: 我希望我理解你澄清的问题。
如果您有一个未导出的type user struct{}
,并且将其与NewUser()
一起返回,那么这适合您的用例吗?如果是这样,那么这是一个工厂设计模式,如果您不希望第三方开发人员直接创建user
类型对象,则在Go中很有用。这样,你的“构造函数”或“工厂”是获得新实例的唯一地方。
那么,这是“糟糕的风格”吗?我要说这取决于需要克服哪些挑战。
答案 1 :(得分:0)
当您返回未导出的类型时,Golang的短毛绒会返回警告,因此,我会说,尽管从技术上讲它也是不鼓励使用的。 1
一个原因是某些接收到未导出类型的代码无法保存它(iirc不会降级为interface{}
)。
例如:
package me
type me string
func NewMe() me {
return "me"
}
// in main.go
package main
type eff struct {
m *me.me // <-- cant do this
}
答案 2 :(得分:0)
我认为值得为其他人在这个问题上发表另一种观点。解决这个问题的更好方法是,如果用户打算以任何方式与其交互,则为该类型定义一个实际的导出接口,或者只是不返回未导出的类型,这样您就不必解决这种情况。这主要是一个设计问题,让我解释一下。
虽然从技术上讲可以返回未导出的类型,如上所示,但对于该包外的代码,必须将该类型分配给 interface{}
。这对我来说是一种代码异味,是我在代码审查中会认真质疑的东西。同样,我会质疑接受未导出参数的导出函数/方法。
我遇到的最大问题是函数签名没有清楚地传达其使用范围。它是一个内部函数,因为它返回一个内部类型?因为它是一个导出函数,所以它是否意味着被外部消费者调用?真是模棱两可。
另外,虽然返回 interface{}
使这种类型可转移,但它也在一定程度上破坏了类型安全。如果返回 interface{}
的目的是为了防止用户在将数据传递给 API 的另一部分之前更改数据,那么辅助 API 需要然后接受 interface{}
并在使用之前检查有效类型.代码也很臭,编译器无法帮助我们处理错误的调用。