golang中不存在private、protected、public,其符号的可见性是在定义符号时设置符号大小写开头来区分。
- 大写:包外可见
- 小写:包内可见

通过这个特性,可以对应的实现Java OOP中封装的概念。

如下

//在该例子中,成员log为小写,包内可见。则如果在同一个包中(如下test方法中),则可以通过name.log的方式访问到golog.Logger中的方法
//  demo/bean/name.go
package bean
type Name struct {
    log golog.Logger
}

func (n Name)NPrint(){
    n.log.Print()
}

func test(){
    name:=Name{}
    name.log.Print()
}

//但是再其他包中,则只能访问到上面定义的NPrint(),访问不到log成员,也就访问不到golog.Logger中的方法
//  demo/file/impl.go
func test(){
    name:=bean.Name{}
    name.NPrint()
}

//这样也就达到了Java OOP中封装的目的。

如果是匿名组合的话,则类似于继承的概念。

//若为匿名组合,则直接可以访问。而不需通过name.log的方式。
//  demo/bean/name.go
type Name struct {
    golog.Logger
}

func (n Name)NPrint(){
    n.Print()
}

//但是再其他包中,也可以直接访问,并不会隐藏。
//  demo/file/impl.go
func test(){
    name:=util.Name{}
    name.Print() //golog.Logger的方法
}

这是为什么匿名成员是包外可见的呢?
这是因为匿名组合类型是相当于用其类型名称(去掉包名部分)作为成员变量的名字的。
比如上面例子可以写成:

//  demo/bean/name.go
type Name struct {
    golog.Logger
}

func (n Name)NPrint(){
    //下面两种方式都可以
    n.Print()
    n.Logger.Print()
}

func (n Name)Print(){
    n.Logger.Print()
    //n.Print()    --->注意:如果写成这样就变成无限循环调用自己的Print,而不是Logger的。
}