【Go】函数参数默认值及关键字参数传递实现一例

函数参数默认值及关键字参数传递实现一例

思路

在 Python 中,定义函数时可以给出部分参数的默认值以及变长关键字参数:

class Work:
    def Run(self, identity, name='Jack', gender=True, age=12, **others):
        ...

其中参数 other 的返回类型为字典(dict)。

然而 Go 中不使用参数默认值。

希望在 Go 中实现形同如下 Python 语句的传参方式:

work.Run('manager', name='Mike', gender=True, married=False)

并为未接受传递的参数提供默认值。

不妨将所有可选参数以映射(map)的形式储存于函数内。

一般地,对于一个工作实例:

type Work struct {
	identity string
	name     string
	gender   bool
	age      int
}

为其绑定一个带有变长参数的方法,并在内部指定参数默认值:

func (work *Work) Run(identity string, others ...interface{}) {
    options := map[string]interface{}{
        "name":   "Jack",
        "gender": true,
    }
}

此时,可以如此传参调用:

func main() {
    work := new(Work)
    work.Run("manager", 1, 2, 3)
}

为使 others 数组中的数据覆盖 options,需要以「键值对」的形式传入每个参数。

为此,可以定义并使用 struct 实例:

type Option struct {
	name  string
	value interface{}
}

在函数中解析数组 Option,以其中数据覆盖映射 options

func (work *Work) Run(identity string, others ...Option) {
    options := map[string]interface{}{
        "name":   "Jack",
        "gender": true,
    }
    for _, other := range others {
        options[other.name] = other.value
    }
    // 如有需要,可按如下方式设置属性值:
    work.identity = identity
	work.name = optionSet["name"].(string)
	work.gender = optionSet["gender"].(bool)
	work.age = optionSet["age"].(int)
}

并通过如下形式调用函数:

work.Run(
    "manager",
    Option{"name": "Mike"},
    Option{"gender": true},
    Option{"age": 7},
)

至此,前文所述的工作经已完成。


进阶

为使代码更加简洁优雅,可以为参数列表 - 映射 options 定义类型:

type Options map[string]interface{}

尔后,options 的初始化语句应修改为:

options := Options{
    "name":   "Jack",
	"gender": true,
}

为结构体 Option 建立构造方法 With

func With(name string, value interface{}) Option {
	return Option{name, value}
}

此时,可以通过如下形式传递参数及调用函数:

work.Run(
	"manager",
	With("name", "Mike"),
	With("gender", true),
	With("age", 7),
)

map 是引用类型,故而可将之传入函数以对其赋值,无需使用指针变量。

定义绑定于结构体 OptionAddTo 方法:

func (option *Option) AddTo(options Options) {
	options[option.name] = option.value
}

将函数 Run 内为 options 赋值的语句修改为:

for _, other := range others {
    other.AddTo(options)
}

最后,可将 OptionOptionsAddToWith 封装以广泛使用。


完整代码

package main

import "fmt"

type Option struct {
	name  string
	value interface{}
}

func With(name string, value interface{}) Option {
	return Option{name, value}
}

type Options map[string]interface{}

func (option *Option) add(options Options) {
	options[option.name] = option.value
}

type Work struct {
	identity string
	name     string
	gender   bool
	age      int
}

func (work *Work) Run(identity string, others ...Option) {
	options := Options{
		"name":   "Jack",
		"gender": true,
	}
	for _, other := range others {
		other.AddTo(options)
	}
	work.identity = identity
	work.name = options["name"].(string)
	work.gender = options["gender"].(bool)
	work.age = options["age"].(int)
	fmt.Printf("%+v\n%+v", options, *work)
}

func main() {
	work := new(Work)
	work.Run(
		"manager",
		With("name", "Mike"),
		With("gender", true),
		With("age", 7),
	)
}

控制台输出:

map[age:7 gender:true name:Mike]
{identity:manager name:Mike gender:true age:7}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值