Golang创建构造函数的方法超详细讲解
梦想画家 人气:0组合字面量
组合字面量是最直接方式初始化Go对象,假设定义了Book类型,使用字面量初始化代码如下:
type Book struct { title string pages int } // creating a new struct instance b := Book{} // creating a pointer to a struct instance bp := &Book{} // creating an empty value nothing := struct{}{}
当然还可以直接个属性赋值:
b := Book{ title: "Julius Caesar", pages: 322, }
这种方式的优势是语法直接、简单易读。但不能给每个属性设置缺省值。所以当类型包括多个缺省值字段时,需要重复写缺省值字段赋值语句。举例:
type Pizza struct { slices int toppings []string } somePizza := Pizza{ slices: 6, toppings: []string{"pepperoni"}, } otherPizza := Pizza{ slices: 6, toppings: []string{"onion", "pineapple"}, }
上面示例每次都设置slices属性为6,另外,如果toppings属性可以为空,如果没有初始化则为nil,这可能导致错误。
自定义构造函数
如果属性需要设置默认值或进行初始化,自定义构造函数可能会很有用。下面通过NewPizza构造函数定义Pizza实例:
func NewPizza(toppings []string) () { if toppings == nil { toppings = []string{} } return Pizza{ slices: 6, toppings: toppings, } }
通过使用构造函数可以自定义实例创建过程:
- 给字段设置缺省值,当然还可以利用可选参数方式给不同属性设置默认值。
- 还可以执行合理性检查,如toppings是否为nil并初始化。可以利用make或new构造一些数据类型并更好控制内存和容量。
从构造函数返回错误
当构造属性时,可能依赖其他系统或库会产生错误,这时最好返回error。
func NewRemotePizza(url string) (Pizza, error) { // toppings are received from a remote URL, which may fail toppings, err := getToppings(url) if err != nil { // if an error occurs, return the wrapped error along with an empty // Pizza instance return Pizza{}, fmt.Errorf("could not construct new Pizza: %v", err) } return Pizza{ slices: 6, toppings: toppings, }, nil }
返回错误有助于将故障条件封装在构造函数本身中。
interface构造函数
构造函数可以直接返回interface类型,同时在其中初始化具体类型。如果我们想将结构设为私有,同时将其初始化设为公共,这将很有帮助。
还是用Pizza类型举例,如果有bakery接口,判断pizza是否可烘烤类型。首先创建Bakeable接口,然后给Pizza类型增加isBaked字段:
// Pizza implements Bakeable type Bakeable interface { Bake() } type Pizza struct { slices int toppings []string isBaked bool } func (p Pizza) Bake() { p.isBaked = true } // this constructor will return a `Bakeable` // and not a `Pizza` func NewUnbakedPizza(toppings []string) Bakeable { return Pizza{ slices: 6, toppings: toppings, } }
最佳实践
让我们来看看Go中关于构造函数命名和组织的一些约定:
基本构造函数
对于简单构造函数返回类型(如Abc,或Xyz类型),则函数分别命名为NewAbc和NewXyz。对于Pizza实例,则构造函数命名为NewPizza。
主包类型
如果在给定包中,初始化变量为主包类型,可以直接命名为New(无需前缀)。举例,Pizza结构定义在pizza包中,构造函数定义如下:
package pizza type Pizza struct { // ... } func New(toppings []string) Pizza { // ... }
当在其他包中调用函数时,代码为 p := pizza.New()
。
多个构造函数
有时相同类型可能有多个构造函数。为此,我们使用NewXyz名称的变体来描述每个方法。举例,下面有三个方法创建Pizza:
- NewPizza 为主构造方法.
- NewRemotePizza 基于远处资源的构造方法.
- NewUnbakedPizza 返回Bakeable接口类型的构造方法.
加载全部内容