Golang技巧之默认值设置的高阶玩法

本文探讨了在 Golang 中如何优雅地处理默认值问题,特别是通过 GRPC 的源码分析,展示了如何使用 DialOption 封装和 grpc.DialContext 调用来实现高阶默认值设置。通过定义接口和函数类型,实现了类似动态语言的默认参数效果,增强了代码的扩展性和可维护性。
摘要由CSDN通过智能技术生成

最近使用 GRPC 发现一个设计特别好的地方,非常值得借鉴。

我们在日常写方法的时候,希望给某个字段设置一个默认值,不需要定制化的场景就不传这个参数,但是 Golang 却没有提供像 PHPPython 这种动态语言设置方法参数默认值的能力。

低阶玩家应对默认值问题

以一个购物车举例。比如我有下面这样一个购物车的结构体,其中 CartExts 是扩展属性,它有自己的默认值,使用者希望如果不改变默认值时就不传该参数。但是由于 Golang 无法在参数中设置默认值,只有以下几个选择:

  1. 提供一个初始化函数,所有的 ext 字段都做为参数,如果不需要的时候传该类型的零值,这把复杂度暴露给调用者;
  2. ext 这个结构体做为一个参数在初始化函数中,与 1 一样,复杂度在于调用者;
  3. 提供多个初始化函数,针对每个场景都进行内部默认值设置。

下面看下代码具体会怎么做

const (
	CommonCart = "common"
	BuyNowCart = "buyNow"
)

type CartExts struct {
	CartType string
	TTL      time.Duration
}

type DemoCart struct {
	UserID string
	ItemID string
	Sku    int64
	Ext    CartExts
}

var DefaultExt = CartExts{
	CartType: CommonCart,       // 默认是普通购物车类型
	TTL:      time.Minute * 60, // 默认 60min 过期
}

// 方式一:每个扩展数据都做为参数
func NewCart(userID string, Sku int64, TTL time.Duration, cartType string) *DemoCart {
	ext := DefaultExt
	if TTL > 0 {
		ext.TTL = TTL
	}
	if cartType == BuyNowCart {
		ext.CartType = cartType
	}

	return &DemoCart{
		UserID: userID,
		Sku:    Sku,
		Ext:    ext,
	}
}

// 方式二:多个场景的独立初始化函数;方式二会依赖一个基础的函数
func NewCartScenes01(userID string, Sku int64, cartType string) *DemoCart {
	return NewCart(userID, Sku, time.Minute*60, cartType)
}

func NewCartScenes02(userID string, Sku int64, TTL time.Duration) *DemoCart {
	return NewCart(userID, Sku, TTL, "")
}

上面的代码看起来没什么问题,但是我们设计代码最重要的考虑就是稳定与变化,我们需要做到 对扩展开放,对修改关闭 以及代码的 高内聚。那么如果是上面的代码,你在 CartExts 增加了一个字段或者减少了一个字段。是不是每个地方都需要进行修改呢?又或者 CartExts 如果有非常多的字段,这个不同场景的构造函数是不是得写非常多个?所以简要概述一下上面的办法存在的问题。

  1. 不方便对 CartExts 字段进行扩展;
  2. 如果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值