一.初始化
代码示例:
packagemain
import"fmt"
typeRectstruct{
x, y float64
width, height float64
}
func(this *Rect) Area () float64 {
returnthis.width * this.height
}
funcmain() {
rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{,,100,200}
rect4 := &Rect
fmt.Println(rect1.Area())
fmt.Println(rect2.Area())
fmt.Println(rect3.Area())
fmt.Println(rect4.Area())
}
在定义Rect之后,咱们通过以下几种方式初始化Rect类型的对象实例:
rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{,,100,200}
rect4 := &Rect
其实,在go语言中,未进行初始化的变量都会被初始化为该类型的0值,如bool类型的零值为false,int型的零值为0,string类型的零值为空字符串。
在go语言中,没有构造函数这个概念,对象的创建通常交由一个去全局函数来完成,以NewXXX来命名,表示“构造函数”。
funcNewRect(x, y, width, height float64) *Rect {
return&Rect
}
二.匿名组合
1.匿名组合解释
在go语言,我们是不能明显看到继承,实际上,go语言也提供继承,但是它采用组合文法,所以我们称之为匿名组合。
typeBasestruct{
Name string
}
typeFoostruct{
*Base
}
func(base* Base) Foo() {}
func(base* Base) Bar() {}
func(foo *Foo) Bar() {
foo.Base.Bar()
}
Base类:
实现Foo()成员方法
实现Bar()成员方法
Foo类:
从Base类继承并改写了Bar()方法(该方法实现时先调用了基类
的Bar()方法)。
如果在派生类Foo没有改写基类Base的Bar方法,相应的方法被继承,其实上面的例子中调用Foo.foo()和调用foo.Base.Foo(),效果完全一样
与其他语言不一样的是咱们的go语言很清晰地告诉你内存布局是怎么的。当然,在go语言中你可以随心所欲地修改内存的布局。
上面代码中:
typeFoostruct{
*Base
}
也可以改写为:
typeFoostruct{
Base
}
对应*Base的派生,Foo创建实例的时候,需要外部提供一个Base类的实例指针。
2.Effective Go上面的小案例:
typeJopstruct{
Command string
*log.Logger
}
func(this *Jop) Start() {
this.Log("starting now...")
//....很多事要做
this.Log("started")
}
上面例子中,对于Jop实现者来说,根本没有必要意识到log.Logger的存在。
这就是匿名组合优势所在。那这是为什呢?
解释:组合的类型并不知道自己被什么类型组合,当然就没发在实现方法
的时候去使用未知的一个组合者的功能了。
3.匿名组合中的名字冲突问题
1).场景一
typeXstruct{
Name string
}
typeYstruct{
X
Name string
}
组合类型和被组合的类型都包含一个Name成员,这样是没有任何问题,
所有Y类型的Name成员的访问都只会访问最外层的那个Name变量,X.Name
变量相当于被隐藏
2).场景2
typeLoggerstruct{
Level int
}
typeYstruct{
*Logger
Name string
*log.Logger
}
存在Logger冲突,这样有时是会报错,但是有事编译器并不会告
诉错,直到开发者使用其中某个Logger时,才会告诉你冲突了。
三.可见性
在go语言中,实际上是没有private,protect和public等关键,go语言中要使某个符号对其它包可见(可访问),需要将该符号定义为大写字母开头。
packagehandle
import(
"errors"
"fmt"
)
funcAdd(a, b, c int) (ret int, err error){
ifa
err = errors.New("不能有负数存在")
return1, err
}
ArrayBianli()
returna + b + c, err
}
funcArrayBianli() {
arr :=[10]int{1,3,5,6,7,9}
fori :=; i
fmt.Print(arr[i],", ")
}
fmt.Println("")
}
packagemain
import"main/pkg/handle"
funcmain() {
handle.Add(1,2,3)
handle.ArrayBianli()
}
小写在本包内可以被访问,不能跨包访问,大写本包内可以访问,跨包也可以访问。
和C++一样,在go语言中也有friend关键字。做为扩展知识,大家可以去网上了解一下go语言的friend关键字。
领取专属 10元无门槛券
私享最新 技术干货