Go 函数选项模式(Functional Options Pattern)

简介: 本文对 Go 函数选项模式(Functional Options Pattern)进行了详细介绍,并通过封装一个消息结构体的例子,展示了如何使用函数选项模式进行代码实现。

作者:陈明勇
个人网站:https://chenmingyong.cn
文章持续更新,如果本文能让您有所收获,欢迎关注本号。
微信阅读可搜《Go 技术干货》。这篇文章已被收录于 GitHub https://github.com/chenmingyong0423/blog,欢迎大家 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)进行了详细介绍,并通过封装一个消息结构体的例子,展示了如何使用函数选项模式进行代码实现。

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

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

目录
相关文章
|
3月前
|
缓存 NoSQL Go
通过 SingleFlight 模式学习 Go 并发编程
通过 SingleFlight 模式学习 Go 并发编程
|
9天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
21天前
|
编译器 Go
go语言编译选项
【10月更文挑战第17天】
18 5
|
20天前
|
JSON 安全 网络协议
go语言使用内置函数和标准库
【10月更文挑战第18天】
14 3
|
30天前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
30天前
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
|
2月前
|
Go
go函数
go函数
33 10
|
2月前
|
编译器 Go C++
Go to Learn Go之函数
Go to Learn Go之函数
28 0
|
2月前
|
编译器 Go 索引
Go数组、多维数组和切片(动态数组),及常用函数len(),cap(),copy(),append()在切片中的使用
本文介绍了Go语言中数组、多维数组和切片(动态数组)的基本概念和操作,包括数组的定义、初始化、访问,多维数组的定义和访问,以及切片的创建、使用和扩容。同时,还讲解了切片中常用的函数len()、cap()、copy()和append()的使用方法。
|
3月前
|
存储 Unix 测试技术
解释Go中常见的I/O模式
解释Go中常见的I/O模式