在 Go 语言中实现链式调用(Method Chaining),可以通过让每个方法返回对象本身(或对象的指针)来实现。这样每次方法调用后可以继续调用其他方法。
示例:实现字符串的链式操作
假设你想对一个字符串连续执行 TrimSuffix
、TrimPrefix
、ToUpper
等操作,可以自定义一个类型并为其定义方法:
1. 定义包装类型
type StringWrapper struct {
value string
}
// 构造函数
func NewStringWrapper(s string) *StringWrapper {
return &StringWrapper{value: s}
}
// 获取最终结果
func (sw *StringWrapper) String() string {
return sw.value
}
2. 实现链式方法
每个方法返回 *StringWrapper
,以便继续调用其他方法:
// TrimSuffix 链式调用
func (sw *StringWrapper) TrimSuffix(suffix string) *StringWrapper {
sw.value = strings.TrimSuffix(sw.value, suffix)
return sw // 返回自身指针
}
// TrimPrefix 链式调用
func (sw *StringWrapper) TrimPrefix(prefix string) *StringWrapper {
sw.value = strings.TrimPrefix(sw.value, prefix)
return sw
}
// ToUpper 链式调用
func (sw *StringWrapper) ToUpper() *StringWrapper {
sw.value = strings.ToUpper(sw.value)
return sw
}
3. 使用示例
func main() {
s := NewStringWrapper(" hello, world! ").
TrimPrefix(" "). // 去掉前缀空格
TrimSuffix("! "). // 去掉后缀 "! "
ToUpper(). // 转为大写
String() // 获取最终结果
fmt.Println(s) // 输出: "HELLO, WORLD"
}
更简洁的实现(直接扩展 string
类型)
Go 不允许直接为内置类型(如 string
)添加方法,但可以通过类型别名实现:
type MyString string
func (ms MyString) TrimSuffix(suffix string) MyString {
return MyString(strings.TrimSuffix(string(ms), suffix))
}
func (ms MyString) TrimPrefix(prefix string) MyString {
return MyString(strings.TrimPrefix(string(ms), prefix))
}
func main() {
result := MyString(" hello! ").
TrimPrefix(" ").
TrimSuffix("! ")
fmt.Println(result) // 输出: "hello"
}
关键点
- 返回对象自身:每个方法返回
*StringWrapper
或类型别名,以支持链式调用。 - 不可变 vs 可变:
- 上例中
StringWrapper
是可变的(修改原对象)。 - 若希望每次操作生成新对象(类似字符串的不可变性),可以返回新实例:
func (sw StringWrapper) TrimSuffix(suffix string) StringWrapper { return StringWrapper{value: strings.TrimSuffix(sw.value, suffix)} }
- 上例中
实际应用场景
- Builder 模式(如
strings.Builder
、bytes.Buffer
)。 - 流式 API 设计(如数据库查询构造器)。
通过链式调用,代码可以更流畅(Fluent Interface),但需注意避免过度使用导致调试困难。