当前位置: 首页 > news >正文

Go 函数选项模式

在 Go 语言中,函数选项模式(Functional Options Pattern) 是一种优雅的设计模式,用于处理可选配置参数,特别是当配置项较多或可能变化时。它避免了冗长的构造函数参数列表,提高了代码的可读性和可扩展性。

核心思想

  1. 定义一个 Option 函数类型,接收目标结构体的指针
  2. 创建多个返回 Option 的配置函数(通常以 With 开头)
  3. 在构造函数中使用可变参数接收这些选项函数

举个简单的例子

package mainimport ("fmt"
)type Person struct {Name     stringAge      intAddress  stringSalary   float64Birthday string
}type PersonOptions func(p *Person)func WithName(name string) PersonOptions {return func(p *Person) {p.Name = name}
}func WithAge(age int) PersonOptions {return func(p *Person) {p.Age = age}
}func WithAddress(address string) PersonOptions {return func(p *Person) {p.Address = address}
}func WithSalary(salary float64) PersonOptions {return func(p *Person) {p.Salary = salary}
}func WithBirthday(birthday string) PersonOptions {return func(p *Person) {p.Birthday = birthday}
}func NewPerson(options ...PersonOptions) *Person {// 优先应用optionsp := &Person{}for _, option := range options {option(p)}// 默认值处理if p.Age < 0 {p.Age = 0}if p.Name == "" {return nil, errors.New("name is required")}return p, nil
}func main() {pl := NewPerson(WithName("John Doe"),WithAge(25),WithAddress("123 Main St"),WithSalary(10000.00),)p2 := NewPerson(WithName("Mike jane"),WithAge(30),)fmt.Println(pl)fmt.Println(p2)
}

1. 基本架构

type PersonOptions func(p *Person) // 选项函数类型定义func WithName(name string) PersonOptions { /*...*/ } // 具体选项实现func NewPerson(options ...PersonOptions) *Person { // 构造函数p := &Person{}for _, option := range options { // 应用所有选项option(p)}// 默认值处理...
}

2. 模式优势

  • 可扩展性:新增字段只需添加对应With函数,无需修改构造函数签名
  • 可选参数:调用方可自由组合参数(如p2只设置姓名和年龄)
  • 链式调用:支持优雅的链式初始化
  • 默认值处理:在构造函数中集中处理字段默认值(如年龄下限)

项目案例

package mainimport "fmt"// 目标配置结构体
type Server struct {host    stringport    inttimeout int // 秒maxConn int
}// 定义 Option 函数类型
type Option func(*Server)// 配置函数:设置主机
func WithHost(host string) Option {return func(s *Server) {s.host = host}
}// 配置函数:设置端口
func WithPort(port int) Option {return func(s *Server) {s.port = port}
}// 配置函数:设置超时
func WithTimeout(timeout int) Option {return func(s *Server) {s.timeout = timeout}
}// 配置函数:设置最大连接数
func WithMaxConn(maxConn int) Option {return func(s *Server) {s.maxConn = maxConn}
}// 构造函数(接收可变选项)
func NewServer(opts ...Option) *Server {// 初始化默认值s := &Server{host:    "localhost",port:    8080,timeout: 30,maxConn: 100,}// 应用所有选项函数for _, opt := range opts {opt(s)}return s
}// 打印服务器配置
func (s *Server) String() string {return fmt.Sprintf("Server{host: %s, port: %d, timeout: %ds, maxConn: %d}",s.host, s.port, s.timeout, s.maxConn,)
}func main() {// 使用默认配置server1 := NewServer()fmt.Println(server1)// 输出:Server{host: localhost, port: 8080, timeout: 30s, maxConn: 100}// 自定义部分配置server2 := NewServer(WithHost("api.example.com"),WithPort(443),WithMaxConn(500),)fmt.Println(server2)// 输出:Server{host: api.example.com, port: 443, timeout: 30s, maxConn: 500}// 自定义所有配置(顺序无关)server3 := NewServer(WithTimeout(60),WithPort(9000),WithHost("127.0.0.1"),WithMaxConn(1000),)fmt.Println(server3)// 输出:Server{host: 127.0.0.1, port: 9000, timeout: 60s, maxConn: 1000}
}

关键优势

1.可读性强:配置选项通过命名函数明确表达意图

   NewServer(WithHost("api.com"), WithPort(443))

2.灵活的默认值:构造函数中设置默认值,仅覆盖需要的选项

3.顺序无关:配置函数的调用顺序不影响结果

4.易于扩展:新增配置只需添加新的 WithXxx 函数,不影响已有代码

   // 新增 TLS 配置func WithTLS(cert string) Option {return func(s *Server) {s.cert = cert}}

对比替代方案

方案优点缺点
函数选项模式高可读性,强扩展性代码量稍多
配置结构体简单直接破坏性修改,无法区分零值和未设置
链式调用调用流畅需返回对象指针,实现复杂
多参数构造函数简单场景适用参数过多时混乱,破坏性修改

适合使用的环境:当配置参数超过 3 个或可能扩展时,优先使用函数选项模式。

这种模式被广泛应用于 Go 标准库和知名开源项目(如 gRPC、etcd 等),是处理复杂配置的推荐方式。

http://www.lryc.cn/news/610091.html

相关文章:

  • 模型学习系列之考试
  • day15 SPI
  • 疏老师-python训练营-Day35模型可视化推理
  • Golang中的`io.Copy()`使用场景
  • #C语言——刷题攻略:牛客编程入门训练(四):运算(二)
  • 网站从HTTP升级到HTTPS网址方法
  • 北京JAVA基础面试30天打卡01
  • 【多智能体cooragent】CoorAgent 系统中 5 个核心系统组件分析
  • 力扣-1.两数之和
  • 腾讯混元重磅开源:四款小尺寸模型全面发布
  • Git如何为多平台配置密钥和用户信息?
  • 互联网医院整体项目套表整理过程文档全流程分析
  • 【MySQL基础篇】:MySQL常用内置函数以及实用示例
  • Flask + HTML 项目开发思路
  • MySQL中COUNT(\*)、COUNT(1)和COUNT(column),到底用哪个?
  • 从零认识OpenFlow
  • 【SAM】Segment Anything 论文翻译笔记
  • opencv引入libavif
  • 模拟IC设计提高系列8-运算跨导放大器OTA Operational Transconduct Amplifiers
  • 家事速配西安项目启动会圆满举行,开启社区服务新篇章
  • 决策树(回归树)全解析:原理、实践与应用
  • 【动态规划 | 回文字串问题】动态规划解回文问题的核心套路
  • 打卡day28
  • Memcached缓存与Redis缓存的区别、优缺点和适用场景
  • Java 大视界 -- Java 大数据在智能交通智能停车诱导与车位共享优化中的应用(381)
  • 【C#】操作Execl和Word文件-1
  • orchestrator部署
  • 11.Linux 权限管理,控制对文件的访问(ACL)
  • git操作命令和golang编译脚本
  • 【Spring】SpringBoot 自动配置,@ComponentScan、@Import、ImportSelector接口