文章内容来自
func25
的 twitter
在Go
中设计函数时,我们可能会遇到需要传递大量参数的情况。
1 | func ConnectToService(host, username, password string, port int, ssl bool) { |
这可能会影响函数的目的,并使维护代码成为一件苦差事,特别是当涉及相同类型的参数时。 为了保持整洁,请考虑两种策略:
- 选项结构
- 函数选项
选项结构体
将参数捆绑到一个结构中,这不仅增强了可读性,还简化了参数传递。
什么时候使用它?
- 你的函数有一个很长的参数列表。
- 您的目标是自记录代码,因为结构字段本质上描述了它们的用途(通过名称)。
- 您希望轻松设置默认值或灵活修改选项。
1 | type ServiceOPtios struct { |
使用此模式时,context.Context
应保留为单独的参数,而不应包含在选项结构中。
1 | func ConnectToService(ctx context.Context, options ServiceOPtions) { |
这是由于上下文在控制请求范围值、截止日期和取消信号方面的独特作用。 但在使用时有一些小技巧:
- 该结构应该向后兼容,以便在添加新字段时,我们不会破坏之前的任何内容。
- 我们始终可以在处理结构之前对其进行验证。
- 考虑隐藏您的选项结构(使其不导出),然后公开
NewXXX()
函数并在那里设置默认值。
函数选项(Functional Options)
此方法利用 Go
的函数功能,允许您以更简洁的方式传递灵活数量的选项。
GO
不支持可选参数,但它好在还是支持可变长参数,即允许函数接受任意数量的参数。这是通过在参数类型
前加上...
来实现的。
它在以下情况下是理想的:
该功能需要高度可配置
大多数选项是可选的或很少使用
您更喜欢简洁的调用站点
1 | type ServiceConfig struct { |
上面这组代码传入一个参数,然后返回一个函数,返回的这个函数会设置自己的 ServiceOption
参数。例如:
• 当我们调用其中的一个函数用 WithSSL(true)
时
• 其返回值是一个 func(cfg* ServiceOption) { cfg.ssl = true }
的函数。
设置默认值比使用可选结构更容易,您不需要隐藏它,只需将默认值直接放在 ConnectToDatabase
中即可。
以上。