在 Go 里,这事儿得直说一句:函数参数本身是没有“默认值”这个语法的 😄不像 Python / JS 那样能直接写。
不过别急,Go 社区早就把几种“官方认可的姿势”玩明白了,按使用频率给你捋一遍。
Go 的哲学:
“调用方传零值,我来决定要不要用默认值。”
func Connect(timeout time.Duration) { if timeout == 0 { timeout = 5 * time.Second } // ... }
调用:
Connect(0) // 用默认 5s Connect(10 * time.Second) // 自定义
✔ 简单✔ 读代码就懂❌ 只能区分“零值 vs 非零值”
适合 参数少、顺序固定 的情况:
func Connect(addr string, timeout ...time.Duration) { t := 5 * time.Second if len(timeout) > 0 { t = timeout[0] } }
Connect("localhost") Connect("localhost", 10*time.Second)
✔ 调用体验接近“默认参数”❌ 参数一多就开始灾难❌ 语义不够清晰
这是 Go 里最“正统”的方案 👑
type ConnectOptions struct { Timeout time.Duration Retries int } func Connect(addr string, opt *ConnectOptions) { opts := ConnectOptions{ Timeout: 5 * time.Second, Retries: 3, } if opt != nil { if opt.Timeout != 0 { opts.Timeout = opt.Timeout } if opt.Retries != 0 { opts.Retries = opt.Retries } } }
Connect("localhost", nil) Connect("localhost", &ConnectOptions{ Timeout: 10 * time.Second, })
✔ 参数语义清晰✔ 可扩展、稳定✔ 非常适合公共 API / SDK
你现在写的 WebSocket / Session / Pipeline 代码——强烈推荐这个。
type Option func(*Config) type Config struct { Timeout time.Duration Debug bool } func WithTimeout(d time.Duration) Option { return func(c *Config) { c.Timeout = d } } func WithDebug() Option { return func(c *Config) { c.Debug = true } }
func NewClient(opts ...Option) *Client { cfg := &Config{ Timeout: 5 * time.Second, Debug: false, } for _, opt := range opts { opt(cfg) } return &Client{cfg: cfg} }
NewClient() NewClient(WithTimeout(10*time.Second)) NewClient(WithTimeout(10*time.Second), WithDebug())
✔ 默认值清晰✔ 参数可选、顺序无关✔ 工业级写法(k8s / grpc / zap 全在用)
如果你愿意,我可以 直接用你现在的 Session / Client / WebSocket 代码,帮你改成一套 最地道的 Functional Options 写法,包括默认值、线程安全那种。
Session / Client / WebSocket
Github开源生信云平台 DEMO