建造者模式
问题
Go 中如何实现建造者模式?和选项模式有什么区别?
答案
链式建造者
type ServerBuilder struct {
host string
port int
timeout time.Duration
tls bool
}
func NewServerBuilder() *ServerBuilder {
return &ServerBuilder{
host: "localhost",
port: 8080,
timeout: 30 * time.Second,
}
}
func (b *ServerBuilder) Host(host string) *ServerBuilder {
b.host = host
return b
}
func (b *ServerBuilder) Port(port int) *ServerBuilder {
b.port = port
return b
}
func (b *ServerBuilder) Timeout(d time.Duration) *ServerBuilder {
b.timeout = d
return b
}
func (b *ServerBuilder) TLS(enable bool) *ServerBuilder {
b.tls = enable
return b
}
func (b *ServerBuilder) Build() (*Server, error) {
if b.port <= 0 || b.port > 65535 {
return nil, fmt.Errorf("invalid port: %d", b.port)
}
return &Server{
host: b.host, port: b.port,
timeout: b.timeout, tls: b.tls,
}, nil
}
// 使用
server, err := NewServerBuilder().
Host("0.0.0.0").
Port(443).
TLS(true).
Timeout(10 * time.Second).
Build()
建造者 vs 选项模式
| 维度 | 建造者模式 | 选项模式 |
|---|---|---|
| 代码量 | 多(每个字段一个方法) | 少(函数类型) |
| 校验 | Build() 中统一校验 | 需额外校验 |
| 可读性 | 链式调用清晰 | Go 惯用,更简洁 |
| 适用 | 构建过程有步骤/依赖 | 可选配置项 |
实际选择
- 配置项多但无依赖关系 → 选项模式(Go 惯用)
- 有构建步骤/依赖/校验 → 建造者模式
- 大多数 Go 项目用选项模式,建造者模式较少见
常见面试问题
Q1: Go 中建造者模式的真实例子?
答案:
strings.Builder:构建字符串http.Request通过http.NewRequest+ 设置各种字段go-zero的rest.MustNewServer用建造者模式配置
var b strings.Builder
b.WriteString("hello")
b.WriteString(" world")
result := b.String() // "hello world"