共计 2254 个字符,预计需要花费 6 分钟才能阅读完成。
导读 | 构造器一般面向对象语言的典型特性,用于初始化变量。Go 语言没有任何具体构造器,但我们能使用该特性去初始化变量。本文介绍不同类型构造器的差异及其应用场景 |
组合字面量是最直接方式初始化 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 类型,同时在其中初始化具体类型。如果我们想将结构设为私有,同时将其初始化设为公共,这将很有帮助。
还是用 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:
到此这篇关于 Golang 创建构造函数的方法超详细讲解的文章就介绍到这了
