struct的导出特性
- 如果struct名称的首字母是小写的,这个struct不会被导出。即使有首字母大写的字段名,字段也不会被导出。
- 如果struct名称的首字母是大写法的,则struct会被导出。但是只会导出内部首字母大写的字段
- 如果struct嵌套了,那么即使被嵌套在内部的struct名称首字母小写,也能访问到它内部首字母大写的字段
type animal struct{ name string Speak string } type Horse struct{ animal sound string }
不要暴露struct
一般,不讲包中的struct直接暴露给外部,所以struct的名字会以小写字母开头,不将其导出。
外部如果需要创建struct的实例,调用struct的操作,那么就给这个struct编写一个构造函数。
// abc/abc.go文件内容:
package abc
type animal struct{
name string
Speak string
}
func NewAnimal() *animal{
a := new(animal)
a.name = "ok"
return a
}
// test.go内容:
package main
import (
"fmt"
"./abc"
)
func main() {
t1 := abc.NewAnimal()
// t1.name = "haha" // 无法访问name属性
t1.Speak = "hhhh" // 可以访问Speak属性
fmt.Println(t1.Speak)
}
嵌套struct中的方法导出问题
当内部struct嵌套进外部struct时,内部struct的方法也会被嵌套,也就是说外部struct拥有了内部struct的方法。
但是需要注意方法的首字母大小写问题。由于内、外struct在同一包内,所以直接在该包内构建外部struct实例,外部struct实例是可以直接访问内部struct的所有方法的。但如果在其它包内构建外部struct实例,该实例将无法访问内部struct中首字母小写的方法。
同一个包内:
package main
import (
"fmt"
)
type person struct {
name string
age int
}
// 未导出方法
func (p *person) speak() {
fmt.Println("speak in person")
}
// 导出的方法
func (p *person) Sing() {
fmt.Println("Sing in person")
}
// Admin exported
type Admin struct {
person
salary int
}
func main() {
a := new(Admin)
a.speak() // 正常输出
a.Sing() // 正常输出
}
不同包的struct实例化,不能导出小写方法
package abc
import "fmt"
// 未导出的person
type person struct {
name string
age int
}
// 未导出的方法
func (p *person) speak() {
fmt.Println("speak in person")
}
// 导出的方法
func (p *person) Sing() {
fmt.Println("Sing in person")
}
// Admin exported
type Admin struct {
person
salary int
}
// ----------------------
package main
import "./abc"
func main() {
a := new(abc.Admin)
// 下面报错
// a.speak()
// 下面正常
a.Sing()
}