struct的导出和暴露问题
关于struct的导出
struct的属性是否被导出,也遵循大小写的原则:首字母大写的被导出,首字母小写的不被导出。
所以:
- 如果struct名称首字母是小写的,这个struct不会被导出。连同它里面的字段也不会导出,即使有首字母大写的字段名。
- 如果struct名称首字母大写,则struct会被导出,但只会导出它内部首字母大写的字段,那些小写首字母的字段不会被导出。
也就是说,struct的导出情况是混合的。
但并非绝对如此,如果struct嵌套了,那么即使被嵌套在内部的struct名称首字母小写,也能访问到它里面首字母大写的字段。
例如:
type animal struct{ name string Speak string } type Horse struct { animal sound string }Horse中嵌套的animal是小写字母开头的,但Horse是能被导出的,所以能在其它包中使用Horse struct,其他包也能访问到animal中的Speak属性。
很多时候,Horse这个名字是不安全的,因为这表示导出Horse这个struct给其他包,也就是将Horse给暴露出去了,外界可以直接打开Horse这个"黑匣子"。
但如果不将Horse导出,如何能在其它包构建出Horse实例?见下文。
不要暴露struct
很多时候,不应该将某包(如包abc)中的struct(如animal)直接暴露给其它包,暴露意味着打开了那个"黑匣子",所以struct会以小写字母开头,不将其导出。
这时在外界其它包中构建包abc的animal,就没法直接通过以下几种方式实现:
var xxx abc.animalnew(abc.animal)&abc.animal{...}abc.animal{...}
例如,下面的是错误的:
// abc/abc.go文件内容: package abc type animal struct{ name string Speak string } // test.go内容: package main import "./abc" func main() { // 全都错误 var t1 abc.animal t2 := new(abc.animal) t3 := &abc.animal{} t4 := abc.animal{} }那么如何在外界构建隐藏起来的struct实例?这时可以在abc包中写一个可导出的函数,通过这个函数来构建struct实例。例如:
// abc/abc.go文件内容: package abc type animal struct{ name string Speak string }
