Go中建造者模式通过结构体Builder或函数式选项实现对象组装,分离构造逻辑、避免参数爆炸,支持链式调用与默认值校验。

建造者模式(Builder Pattern)在 Go 中不依赖类和继承,而是通过结构体、函数式选项和链式调用实现清晰、可扩展的对象组装。核心思路是:把对象的构造逻辑从初始化中分离出来,让调用方按需选择配置项,避免参数爆炸和不可变对象的繁琐构造。
定义目标结构体与私有字段
先设计最终要构建的对象,字段设为小写(私有),防止外部直接赋值:
例如构建一个 HTTP 客户端配置:
type HTTPClient struct {
baseURL string
timeout time.Duration
retries int
userAgent string
middleware []func(http.RoundTripper) http.RoundTripper
}所有字段都不导出,确保只能通过 Builder 控制创建过程。
立即学习“go语言免费学习笔记(深入)”;
创建 Builder 结构体并提供设置方法
Builder 是一个普通结构体,持有和目标对象相同的字段(或中间状态),每个设置方法返回 *Builder 自身,支持链式调用:
type HTTPClientBuilder struct {
cfg HTTPClient
}
func NewHTTPClientBuilder() HTTPClientBuilder {
return &HTTPClientBuilder{
cfg: HTTPClient{
timeout: 30 time.Second,
retries: 3,
},
}
}
func (b HTTPClientBuilder) WithBaseURL(url string) HTTPClientBuilder {
b.cfg.baseURL = url
return b
}
func (b HTTPClientBuilder) WithTimeout(d time.Duration) HTTPClientBuilder {
b.cfg.timeout = d
return b
}
func (b HTTPClientBuilder) WithRetries(n int) HTTPClientBuilder {
b.cfg.retries = n
return b
}
func (b HTTPClientBuilder) WithUserAgent(ua string) HTTPClientBuilder {
b.cfg.userAgent = ua
return b
}
func (b HTTPClientBuilder) WithMiddleware(ms ...func(http.RoundTripper) http.RoundTripper) HTTPClientBuilder {
b.cfg.middleware = append(b.cfg.middleware, ms...)
return b
}
提供 Build 方法完成最终构造
Build 方法返回不可变的目标对象(通常做一次深拷贝或只读封装)。Go 中常直接返回结构体值(值语义天然不可变):
func (b *HTTPClientBuilder) Build() HTTPClient {
// 可在此校验必要字段,如:
if b.cfg.baseURL == "" {
panic("baseURL is required")
}
return b.cfg // 返回副本,调用方无法修改原始 builder 状态
}使用示例:
client := NewHTTPClientBuilder().
WithBaseURL("https://api.example.com").
WithTimeout(10 * time.Second).
WithRetries(5).
WithUserAgent("MyApp/1.0").
Build()进阶:用函数式选项(Functional Options)替代 Builder 结构体
更 Go 风格的做法是用函数类型封装配置逻辑,轻量且组合灵活:
type Option func(*HTTPClient)func WithBaseURL(url string) Option { return func(c *HTTPClient) { c.baseURL = url } }
func WithTimeout(d time.Duration) Option { return func(c *HTTPClient) { c.timeout = d } }
func NewHTTPClient(opts ...Option) HTTPClient { c := HTTPClient{ timeout: 30 * time.Second, retries: 3, } for _, opt := range opts { opt(&c) } if c.baseURL == "" { panic("baseURL is required") } return c }
调用更简洁:
client := NewHTTPClient(
WithBaseURL("https://api.example.com"),
WithTimeout(10 * time.Second),
WithRetries(5),
)基本上就这些。Builder 模式在 Go 里不是照搬 Java 写法,而是借其思想——解耦构造、提升可读性、支持默认值与校验。用结构体 Builder 适合复杂流程;用 Functional Options 更符合 Go 的简洁哲学。选哪种,看你的配置维度和团队习惯。










