跳到主要内容

建造者模式

问题

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-zerorest.MustNewServer 用建造者模式配置
var b strings.Builder
b.WriteString("hello")
b.WriteString(" world")
result := b.String() // "hello world"

相关链接