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 的简洁哲学。选哪种,看你的配置维度和团队习惯。






























