在使用go编程的时候,如果采用面向对象的方法,那么我们需要构造对象。而go语言并不是纯粹的面向对象语言,所以不像C++类似 的语言有默认构造函数,带参的构造函数,复制构造函数等。接下来,就来介绍下go 语言中如何构造对象
0x01 对象和方法
在面向对象编程中,对象的定义是具有属性和方法的集合体。所以在go中,用struct来定义的对象的属性。例如:
type Person struct{
age int
}
对象一般都是有自己的方法的,在这个例子中,人可以有很多的行为。go中通过接收器将方法和类型对象绑定。例如:
func (p *Person)Sleep(){
}
通过上面的代码,我们就获得了一个通过面向对象方法定义的Person对象。
0x02 new 方法构造
new 为语言内置方法,创建一个传入其中类型的对象:
jessica := new(Person)
0x03 直接定义
在代码中需要使用对象的地方直接声明
jessica := Person{}
tom := &Person{}
0x04 定义构造函数
在C++中,我们构造函数和对象是一体的,如果我们不写构造函数,那么语言系统会使用默认的构造函数,在go中,上述两种方式使用了默认参数构造,不过 都是空类型,int的是0,在go中,我们通常在一个包中定义一个对象类型,并开放一个构造函数,构造对象返回:
package person
type person struct{
age int
}
func NewPerson() *person {
return &person{
}
}
上面定义的方法可以看出,其是不传参的默认构造和使用系统提供的new函数没有差别。那如果我们需要构造的时候强制传入参数呢:
func NewPerson(age int) *person {
return &person{
age:age,
}
}
上面的方法就是带参构造的情况。 那如果我们想要另一种情况,参数是可选的,如果不传,那就用默认构造,如果传了的话,就用传入的参数,那应该怎么写呢, 这个时候就需要通过go的闭包特性来是实现了。
package person
type person struct{
opt Options
}
type Options struct{
age int
}
type Option func(o *Options)
func newOptions(opts ...Option) Options {
options := Options{
age:15,
}
for _, o := range opts{
o(&options)
}
return options
}
func Age(age int) Option{
return func(o *Options){
o.age = age
}
}
func NewPerson(opts ...Option) *person{
options := newOptions(opts...)
return &person{
opt:options,
}
}
通过上面的代码我们可以看到,如果没有传入自定义的年龄,那对象构造出来的就是用默认年龄构造的对象。对象的构造就很灵活。
0x05 总结
上面我们介绍了GO 中对象的构造的几种方式。大家可以通过自己的需要来决定采用哪种方式。不同的方式,代码量是不一样的,所以慎选。options看着很 优美的,但是代码量还是很大的.
-
如果对象很简单,或者是允许对象中的某个属性为空,那么直接用内建的new方法或者直接声明。如前面提到的 0x02, 0x03 方式
-
如果参数较少,但是必须都要填参数,那么采用带参数的构造函数 如前面提到的 0x04 方式
-
如果在构造对象的时候参数或者属性可选,那么就可以采用 0x04 方式构造对象