Golang struct 使用工厂方法创建结构体实例
结构体工厂
Go 语言不支持面向对象编程语言中那样的构造子方法,但是可以很容易的在 Go 中实现 “构造子工厂” 方法。为了方便通常会为类型定义一个工厂,按惯例,工厂的名字以 new 或 New 开头。假设定义了如下的 File 结构体类型:
type File struct {
fd int // 文件描述符
name string // 文件名
}
下面是这个结构体类型对应的工厂方法,它返回一个指向结构体实例的指针:
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
return &File{fd, name}
}
然后这样调用它:
f := NewFile(10, "./test.txt")
在 Go 语言中常常像上面这样在工厂方法里使用初始化来简便的实现构造函数。
如果 File 是一个结构体类型,那么表达式 new(File) 和 &File{} 是等价的。
这可以和大多数面向对象编程语言中笨拙的初始化方式做个比较:File f = new File(...)。
我们可以说是工厂实例化了类型的一个对象,就像在基于类的 OOP 语言中那样。
如果想知道结构体类型 T 的一个实例占用了多少内存,可以使用:size := unsafe.Sizeof(T{})。
如何强制使用工厂方法
通过应用可见性规则参考 4.2.1 节、9.5 节就可以禁止使用 new 函数,强制用户使用工厂方法,从而使类型变成私有的,就像在面向对象语言中那样。
type matrix struct {
...
}
func NewMatrix(params) *matrix {
m := new(matrix) // 初始化 m
return m
}
在其他包里使用工厂方法:
package main
import "matrix"
...
wrong := new(matrix.matrix) // 编译失败(matrix 是私有的)
right := matrix.NewMatrix(...) // 实例化 matrix 的唯一方式
map 和 struct vs new () 和 make ()
new 和 make 这两个内置函数已经在第 7.2.4 节通过切片的例子说明过一次。
现在为止我们已经见到了可以使用 make()
的三种类型中的其中两个:
slices / maps / channels(见第 14 章)
下面的例子说明了在映射上使用 new 和 make 的区别以及可能发生的错误:
示例 10.4 new_make.go(不能编译)
type Foo map[string]string
type Bar struct {
thingOne string
thingTwo int
}
func main() {
// OK
y := new(Bar)
(*y).thingOne = "hello"
(*y).thingTwo = 1
// NOT OK
z := make(Bar) // 编译错误:cannot make type Bar
(*z).thingOne = "hello"
(*z).thingTwo = 1
// OK
x := make(Foo)
x["x"] = "goodbye"
x["y"] = "world"
// NOT OK
u := new(Foo)
(*u)["x"] = "goodbye" // 运行时错误!! panic: assignment to entry in nil map
(*u)["y"] = "world"
}
试图 make() 一个结构体变量,会引发一个编译错误,这还不是太糟糕,但是 new() 一个映射并试图使用数据填充它,将会引发运行时错误! 因为 new(Foo) 返回的是一个指向 nil 的指针,它尚未被分配内存。所以在使用 map 时要特别谨慎。
相关文章
- Python 技巧篇-pip卸载python库实例演示,查看pip命令大全方法[通俗易懂]
- 归一化方法总结_实例归一化
- Postgresql中return setof函数的使用方法与实例
- postgresql合并string_agg函数的实例
- Linux系统设置开机自动运行脚本的方法实例
- linux查看防火墙是否关闭的实例方法
- JBPM工作流(八)——流程实例(PI)Process Instance详解编程语言
- [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口编程语言
- Linux环境下快速安全删除数据库实例(linux删除数据库实例)
- Linux ln命令:示例与用法(linuxln命令实例)
- 一台服务器,多个实例!深入了解Oracle多个SID的应用和管理方法(oracle多个sid)
- MySQL中CHAR方法详解及实例演示(mysql中char方法)
- asp.net中静态方法和动态方法调用的区别实例分析
- java调用Oracle存储过程的方法实例
- jqueryvalidation验证身份证号,护照,电话号码,email(实例代码)
- 通过LinQ查询字符出现次数的实例方法
- C#测量程序运行时间及cpu使用时间实例方法
- python二叉树的实现实例
- python装饰器使用方法实例
- 在线一元二次方程计算器实例(方程计算器在线计算)
- JqueryUploadify上传带进度条的简单实例
- JQuery调用WebServices的方法和4个实例
- JavaScript中实现继承的三种方式和实例
- Python中使用Boolean操作符做真值测试实例