golang中的选项模式
索引
https://waterflow.link/articles/1663835071801
当我在使用go-zero时,我看到了好多像下面这样的代码:
...
type (
// RunOption defines the method to customize a Server.
RunOption func(*Server)
// A Server is a http server.
Server struct {
ngin *engine
router httpx.Router
}
)
...
// AddRoutes add given routes into the Server.
func (s *Server) AddRoutes(rs []Route, opts ...RouteOption) {
r := featuredRoutes{
routes: rs,
}
for _, opt := range opts {
opt(&r)
}
s.ngin.addRoutes(r)
}
...
// WithJwt returns a func to enable jwt authentication in given route.
func WithJwt(secret string) RouteOption {
return func(r *featuredRoutes) {
validateSecret(secret)
r.jwt.enabled = true
r.jwt.secret = secret
}
}
我们可以把重点放在RouteOption上面。这里就使用了选项模式。
什么是选项模式?
选项模式是一种函数式编程模式,用于为可用于修改其行为的函数提供可选参数。
如果你用过php的话,你肯定会看到过这样的函数,毕竟PHP是世界上最好的语言:
public function cache(callable $callable, $duration = null, $dependency = null)
// 我们可以这样调用
cache($callable);
// 也可以把后面的可选参数带上
cache($callable, $duration);
这种能力在 API 设计中非常有用,因为
- 允许用户以最低配置使用方法,同时仍为有经验的用户提供充足的配置选项。
- 允许开发者在不破坏向后兼容性的情况下添加新选项。
然而,在 Golang 中,这是不可能的。该语言不提供添加可选参数的方法。
这就是“选项模式”的用武之地。它允许用户在调用方法 时传递其他选项,然后可以相应地修改其行为。让我们看一个小例子。
假设我们有一个结构体Server,它有 3 个属性port, timeout和maxConnections
type Server struct {
port string
timeout time.Duration
maxConnections int
}
然后我们有个Server的工厂方法
func NewServer(port string, timeout time.Duration, maxConnections int) *Server {
return &Server{
port: port,
timeout: timeout,
maxConnections: maxConnections,
}
}
但是现在我们希望只有端口号是必传的,timeout和maxConnections成为可选参数。在很多情况下,这些的默认值就足够了。另外,我不想用这些不必要的配置来轰炸刚刚学习或试验我的 方法 的新用户。让我们看看该怎么去实现。
首先我们定义一个新的option结构体
type Option func(*Server)
Option是一个函数类型,它接受指向我们的Server. 这很重要,因为我们将使用这些选项修改我们的Server实例。
现在让我们定义我们的选项。惯例是在我们的选项前面加上 With,但可以随意选择适合您的域语言的任何名称
func WithTimeout(timeout time.Duration) Option {
return func(s *Server) {
s.timeout = timeout
}
}
func WithMaxConnections(maxConn int) Option {
return func(s *Server) {
s.maxConnections = maxConn
}
}
我们的两个选项WithTimeout和WithMaxConnections,采用配置值并返回一个Option。这Option只是一个函数,它接受一个指向我们Server对象的指针并将所需的属性设置为提供的值。例如,WithTimeout获取超时持续时间,然后返回一个函数(其签名与 Option相同)将我们服务器的 timeout 属性设置为提供的值。
在这里,我们使用了一种几乎所有现代语言(包括 Golang)都支持的称为闭包的技术
我们的工厂方法Server现在需要修改以支持这种变化
func NewServer(port string, options ...Option) *Server {
server := &Server{
port: port,
}
for _, option := range options {
option(server)
}
return server
}
现在我们就可以用上面世界上最好的语言的方式调用了
NewServer("8430")
NewServer("8430", WithTimeout(10*time.Second))
NewServer("8430", WithTimeout(10*time.Second), WithMaxConnections(10))
在这里你可以看到我们的客户端现在可以创建一个只有端口的最小服务器,但如果需要也可以自由地提供更多的配置选项。
这种设计具有高度的可扩展性和可维护性,甚至比我们在 PHP 中看到的可选参数还要好。它允许我们添加更多选项,而不会膨胀我们的函数签名,也不会触及我们在工厂方法中的代码。
下面是完整代码:
package main
import "time"
type Option func(*Server)
type Server struct {
port string
timeout time.Duration
maxConnections int
}
func NewServer(port string, options ...Option) *Server {
server := &Server{
port: port,
}
for _, option := range options {
option(server)
}
return server
}
func WithTimeout(timeout time.Duration) Option {
return func(s *Server) {
s.timeout = timeout
}
}
func WithMaxConnections(maxConn int) Option {
return func(s *Server) {
s.maxConnections = maxConn
}
}
func main() {
NewServer("8430")
NewServer("8430", WithTimeout(10*time.Second))
NewServer("8430", WithTimeout(10*time.Second), WithMaxConnections(10))
}
golang中的选项模式的更多相关文章
- (13)ASP.NET Core 中的选项模式(Options)
1.前言 选项(Options)模式是对配置(Configuration)的功能的延伸.在12章(ASP.NET Core中的配置二)Configuration中有介绍过该功能(绑定到实体类.绑定至对 ...
- 基于SqlSugar的开发框架循序渐进介绍(7)-- 在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传
在基于SqlSugar的开发框架的服务层中处理文件上传的时候,我们一般有两种处理方式,一种是常规的把文件存储在本地文件系统中,一种是通过FTP方式存储到指定的FTP服务器上.这种处理应该由程序进行配置 ...
- golang中逗号ok模式_转
,ok,第一个参数是一个值或者nil,第二个参数是true/false或者一个错误error.在一个需要赋值的if条件语句中,使用这种模式去检测第二个参数值会让代码显得优雅简洁.这种模式在go语言编码 ...
- asp.net core 3.0 选项模式1:使用
本篇只是从应用角度来说明asp.net core的选项模式,下一篇会从源码来分析 1.以前的方式 以前我们使用web.config/app.config时是这样使用配置的 var count = Co ...
- Go语言设计模式之函数式选项模式
Go语言设计模式之函数式选项模式 本文主要介绍了Go语言中函数式选项模式及该设计模式在实际编程中的应用. 为什么需要函数式选项模式? 最近看go-micro/options.go源码的时候,发现了一段 ...
- Go语言实践模式 - 函数选项模式(Functional Options Pattern)
什么是函数选项模式 大家好,我是小白,有点黑的那个白. 最近遇到一个问题,因为业务需求,需要对接三方平台. 而三方平台提供的一些HTTP(S)接口都有统一的密钥生成规则要求. 为此我们封装了一个独立的 ...
- Golang 常见设计模式之选项模式
熟悉 Python 开发的同学都知道,Python 有默认参数的存在,使得我们在实例化一个对象的时候,可以根据需要来选择性的覆盖某些默认参数,以此来决定如何实例化对象.当一个对象有多个默认参数时,这个 ...
- 安卓中的Model-View-Presenter模式介绍
转载自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0425/2782.html 英文原文:Introduction to M ...
- 基础知识 - Golang 中的正则表达式
------------------------------------------------------------ Golang中的正则表达式 ------------------------- ...
随机推荐
- 最新30系显卡搭建paddle飞浆环境|含CUDA下载安装
下载CUDA 通过这个链接可以下载任意CUDA版本:CUDA Toolkit Archive | NVIDIA Developer 我下载的是这一个:https://developer.downloa ...
- ceph 005 赋权补充 rbd块映射
我的ceph版本 [root@serverc ~]# ceph -v ceph version 16.2.0-117.el8cp (0e34bb74700060ebfaa22d99b7d2cdc037 ...
- 解读Gartner2022年组装式应用报告:从组装式企业到组装式应用
摘要:"到2023年,采用组装式方法的组织在新特性交付速度比竞争对手快80%."Gartner 为什么未来的企业是组装式的? 物竞天择,适者生存,企业也是一样,在发展过程中,会为了 ...
- PlayCover for mac-Mac 上全屏运行 iOS 应用程序
前言 如何在Mac电脑运行ios应用呢?PlayCover for Mac一款彻底解放苹果电脑的iOS软件安装工具,无需付费,操作简单,可以安装ipa文件,可以通过鼠标.键盘和控制器 在Mac上全屏运 ...
- [WPF] 使用 HandyControl 的 CirclePanel 画出表盘刻度
1. 前言 最近需要一个 WPF 的表盘控件,之前 Cyril-hcj 写过一篇不错的博客 <WPF在圆上画出刻度线>,里面介绍了一些原理及详细实现的代码: double radius = ...
- 关于 Math.random()生成指定范围内的随机数的公式推导
关于 Math.random()生成指定范围内的随机数的公式推导 在 java 中,用于生成随机数的 Math 方法 random()只能生成 0-1 之间的随机数,而对于生成指定区间,例如 a-b ...
- Mysql数据库安装到操作到应用
该博文转载(https://www.cnblogs.com/whwh/p/16200066.html) 一.安装和配置数据库: 下载mysql地址:https://dev.mysql.com/down ...
- KingbaseES 数据库软件卸载
关键字: KingbaseES.卸载 一.安装后检查 在安装完成后,可以通过以下几种方式进行安装正确性验证: 1. 查看安装日志,确认没有错误记录; 2. 查看开始菜单: 查看应用程序菜单中是否安 ...
- git reset总结
git reset git 的重置操作 有三种模式:hard.mixed(默认).soft 1. hard 用法 hard会重置stage区和工作区,和移动代码库上HEAD 和branch的指针所指向 ...
- Centos7下安装postgresql(tar包形式安装)
Centos7下安装postgresql(tar包形式安装) 1.官网下载地址: https://www.postgresql.org/ftp/source/ 2.将下载来tar包上传到linux服务 ...