作者:陈明勇

个人网站:chenmingyong.cn

文章继续更新,如果本文能让您有所收获,欢迎重视本号。

微信阅览可搜《Go 技能干货》。这篇文章已被收录于 GitHub github.com/chenmingyon…
,欢迎大家 Star 催更并继续重视。

前语

在日常开发中,有些函数或许需求接纳许多参数,其间一些参数是必需的,而其他参数则是可选的。当函数参数过多时,函数会变得臃肿且难以了解。此外,如果在将来需求添加更多参数,就有必要修正函数签名,这将影响到已有的调用代码。

而函数选项形式(functional options)的呈现解决了这个问题,本文将对其进行解说,预备好了吗?预备一杯你最喜欢的饮料或茶,跟着本文一探终究吧。

函数选项形式

什么是函数选项形式

Go 语言中,函数选项形式是一种优雅的设计形式,用于处理函数的可选参数。它供给了一种灵活的方法,答应用户在函数调用时传递一组可选参数,而不是依赖于固定数量和次序的参数列表。

函数选项形式的优点

  • 易于运用:调用者能够选择性的设置函数参数,而不需求记住参数的次序和类型;
  • 可读性强:函数选项形式的代码有着自文档化的特色,调用者能够直观地了解代码的功用;
  • 扩展性好:通过添加新的 Option 参数选项,函数能够方便地扩展功用,无需修正函数的签名;
  • 函数选项形式能够供给默许参数值,以减少参数传递的杂乱性。

函数选项形式的完成

函数选项形式的完成一般包含以下几个部分:

  • 选项结构体:用于存储函数的装备参数
  • 选项函数类型:接纳选项结构体参数的函数
  • 界说功用函数:接纳 0 个或多个固定参数和可变的选项函数参数
  • 设置选项的函数:界说多个设置选项的函数,用于设置选项

代码示例:

type Message struct {
   // 标题、内容、信息类型
   title, message, messageType string
   // 账号
   account     string
   accountList []string
   // token
   token     string
   tokenList []string
}
type MessageOption func(*Message)
func NewMessage(title, message, messageType string, opts ...MessageOption) *Message {
   msg := &Message{
      title:       title,
      message:     message,
      messageType: messageType,
   }
   for _, opt := range opts {
      opt(msg)
   }
   return msg
}
func WithAccount(account string) MessageOption {
   return func(message *Message) {
      message.account = account
   }
}
func WithAccountList(accountList []string) MessageOption {
   return func(message *Message) {
      message.accountList = accountList
   }
}
func WithToken(token string) MessageOption {
   return func(message *Message) {
      message.token = token
   }
}
func WithTokenList(tokenList []string) MessageOption {
   return func(message *Message) {
      message.tokenList = tokenList
   }
}
func main() {
   // 单账号推送
   _ = NewMessage(
      "来自陈明勇的信息",
      "你好,我是陈明勇",
      "单账号推送",
      WithAccount("123456"),
   )
   // 多账号推送
   _ = NewMessage(
      "来自陈明勇的信息",
      "你好,我是陈明勇",
      "多账号推送",
      WithAccountList([]string{"123456", "654321"}),
   )
}

上述例子中,运用了函数选项形式来创立 Message 结构体,并根据音讯类型装备不同音讯的特点。

首要界说了 Message 结构体,其包含 7 个字段;

其次界说 MessageOptionm选项函数类型,用于接纳 Message 参数的函数;

再次界说 NewMessage 函数,用于创立一个 Message 指针变量,在 NewMessage 函数中,固定参数包括 titlemessagemessageType,它们是必需的参数。然后,通过可选参数 opts ...MessageOption 来接纳一系列的函数选项;

然后界说了四个选项函数:WithAccountWithAccountListWithTokenWithTokenList。这些选项函数别离用于设置被推送音讯的账号、账号列表、令牌和令牌列表。

最后,在 main 函数中,展现了两种不同的用法。第一个示例是创立单账号推送的音讯,通过调用 NewMessage 并传递相应的参数和选项函数(WithAccount)来装备音讯。第二个示例是创立多账号推送的音讯,相同通过调用 NewMessage 并运用不同的选项函数(WithAccountList)来装备音讯。

这种运用函数选项形式的方法能够根据需求音讯类型去装备音讯的特点,使代码更具灵活性和可扩展性。

函数选项形式的缺陷

前面提到了函数选项形式的优势(优点),但也有必要供认它存在一些缺陷。

  • 杂乱性:函数选项形式引入了更多的类型和概念,需求更多的代码和逻辑来处理。这增加了代码的杂乱性和了解的难度,尤其是关于初学者来说。

  • 或许存在过错的选项组合:由于函数选项形式答应在函数调用中指定多个选项,某些选项之间或许存在抵触或不兼容的状况。这或许导致意外的行为或过错的结果。

  • 不适用于所有状况:函数选项形式适用于有很多可选参数或许可装备选项的函数,但关于只要几个简单参数的函数,运用该形式或许过于杂乱和冗余。在这种状况下,简单的命名参数或许更直观和易于运用。

小结

本文对 Go 函数选项形式(Functional Options Pattern)进行了具体介绍,并通过封装一个音讯结构体的例子,展现了怎么运用函数选项形式进行代码完成。

在合适的状况下,我们能够运用函数选项形式来封装一些功用,定制函数的行为,提高代码的可读性和可扩展性。

你是否在实践开发中运用过函数选项形式?欢迎评论区留言探讨。