模块 5 · 第 5 课(共 5)课程中的25/50~10 min
模块课程(5/5)
“New...”构造函数模式
Go 没有 constructor 关键字。会议是一个工厂
返回正确初始化的值或指针的函数。由
名称通常称为 NewT (或 NewXxx)。
基本图案:NewT
Go
type User struct {
Name string
Age int
}
func NewUser(name string, age int) *User {
return &User{Name: name, Age: age}
}
u := NewUser("Ada", 36)
fmt.Println(u.Name)相对于直接文字 &User{...} 的优点:
- 您集中验证和默认值。
- 您可以拥有未导出的字段并仅从构造函数填充它们。
- 您可以在不破坏调用者的情况下更改实现。
带验证的构造函数:(*T,错误)
当初始化失败时,返回 (*T, error):
Go
import "errors"
func NewUser(name string, age int) (*User, error) {
if name == "" {
return nil, errors.New("nome obbligatorio")
}
if age < 0 {
return nil, errors.New("eta non valida")
}
return &User{Name: name, Age: age}, nil
}
u, err := NewUser("Ada", 36)
if err != nil {
// handle...
}这是任何构造函数的惯用模式 前提条件:数据库连接、文件句柄、服务器配置等。
多个构造函数
如果您有多种构建“方式”,请使用描述性名称:
Go
func NewUser(name string) *User { ... }
func NewUserFromJSON(data []byte) (*User, error) { ... }
func NewAdmin() *User { ... }Go 中没有重载:名称消除了歧义。
功能选项(高级一瞥)
当有很多可选参数时,惯用模式是 “功能选项”:
Go
type Option func(*Server)
func WithPort(p int) Option {
return func(s *Server) { s.Port = p }
}
func WithTLS(cert, key string) Option {
return func(s *Server) { s.Cert, s.Key = cert, key }
}
func NewServer(opts ...Option) *Server {
s := &Server{Port: 8080} // default
for _, opt := range opts {
opt(s)
}
return s
}
s := NewServer(WithPort(9000), WithTLS("c.pem", "k.pem"))它比字面意思更冗长,但可以很好地扩展许多可选的内容
参数并保留向后兼容性(添加新的 Option
不会破坏现有的调用者)。
当你不需要构造函数时
如果类型的零值已经有用,让调用者使用
直接字面意思。典型示例: sync.Mutex 没有构造函数,
var m sync.Mutex 已经是一个随时可用的互斥体。与 bytes.Buffer 相同。
规则是:“让零值变得有用”。如果可以的话,不 强制构造函数。
尝试一下
锻炼#go.m5.l5.e1
尝试:0加载中...
编写工厂函数NewUser(name string,age int) *User,返回&User{Name: name, Age:age}。
正在加载编辑器...
显示提示
使用文字“&User{...}”返回一个指针。
3 次尝试后可用的解决方案
锻炼#go.m5.l5.e2
尝试:0加载中...
将 NewUser 转为 (name string) (*User, error): if name == '' return nil,Errors.New('nome obbligatorio')。
正在加载编辑器...
显示提示
如果有前提条件,则返回(*T, error),失败时返回nil + error。
3 次尝试后可用的解决方案
Quiz#go.m5.l5.e3
准备好Go 中构造函数的惯用约定是什么?
Go
// Which signature is more idiomatic?回顾
- 无
constructor:使用NewT函数(或同名包内的New)。 - 对于简单情况,返回
*T;(*T, error)具有前提条件或验证。 - 出错时:返回
nil作为指针,并返回解释性错误作为第二个值。 - 严禁超载;使用描述性名称(
NewUserFromJSON、NewAdmin)。 - “使零值有用”:如果可以的话,构造函数是不必要的。
- 许多可选参数的高级模式:功能选项。