Go语言精进之路读书笔记第25条——了解变长参数函数的妙用

25.1 什么是变长参数#

变长参数函数:调用时可以接受零个、一个或多个实际参数的函数。

func Println(a ...interface{}) (n int, err error)
  • 只能有一个“...T”类型形式参数,且该形式参数应该为函数参数列表中的最后一个形式参数。
  • “...T”类型形式参数在函数内呈现为[]T类型的变量
  • 在函数外部,“...T”类型形式参数可匹配和接受的实参类型有两种(二者不能混用):
    • 多个T类型变量;
    • t...(t为[]T类型变量)
func sum(args ...int) int {
    var total int

    for _, v := range args {
        total += v
    }

    return total
}

func main() {
    a, b, c := 1, 2, 3
    println(sum(a, b, c))
    nums := []int{4, 5, 6}
    println(sum(nums...))
}

容易出现实参与形参不匹配的问题

  • []string类型变量不能直接赋值给[]interface{}类型变量
func dump(args ...interface{}) {
    for _, v := range args {
        fmt.Println(v)
    }
}

func main() {
    //s := []string{"Tony", "John", "Jim"}
    s := []interface{}{"Tony", "John", "Jim"}
    dump(s...)
}
  • 不过append函数例外
func foo(b ...byte) {
    fmt.Println(string(b))
}

func main() {
    b := []byte{}
    b = append(b, "hello"...)
    fmt.Println(string(b))

    foo("hello"...)
}

25.2 模拟函数重载#

Go语言不允许在同一个作用域下定义名字相同但函数原型不同的函数

要重载的函数的参数,类型相同/不同,参数的个数的变化的,可以通过变长参数函数结合interface{}类型来实现

25.3 模拟实现函数的可选参数与默认参数#

如果参数在传入时有隐式要求的固定顺序,可以利用变长参数函数模拟实现。局限性:调用者只能从右侧的参数开始逐一进行省略传递的处理。

25.4 实现功能选项模式#

Rob Pike的博文“自引用函数与选项设计”,功能选项(functional option)模式
好处:

  • 不随时间变化的公共API
  • 参数可读性更好
  • 配置选项高度可扩展
  • 提供使用默认选项的最简单方式
  • 使用更安全(调用者无法修改options)
type FinishedHouse struct {
    style                  int    // 0: Chinese, 1: American, 2: European
    centralAirConditioning bool   // true or false
    floorMaterial          string // "ground-tile" or ”wood"
    wallMaterial           string // "latex" or "paper" or "diatom-mud"
}

type Option func(*FinishedHouse)

func NewFinishedHouse(options ...Option) *FinishedHouse {
    h := &FinishedHouse{
        // default options
        style:                  0,
        centralAirConditioning: true,
        floorMaterial:          "wood",
        wallMaterial:           "paper",
    }

    for _, option := range options {
        option(h)
    }

    return h
}

func WithStyle(style int) Option {
    return func(h *FinishedHouse) {
        h.style = style
    }
}

func WithFloorMaterial(material string) Option {
    return func(h *FinishedHouse) {
        h.floorMaterial = material
    }
}

func WithWallMaterial(material string) Option {
    return func(h *FinishedHouse) {
        h.wallMaterial = material
    }
}

func WithCentralAirConditioning(centralAirConditioning bool) Option {
    return func(h *FinishedHouse) {
        h.centralAirConditioning = centralAirConditioning
    }
}

func main() {
    fmt.Printf("%+v\n", NewFinishedHouse()) // use default options
    fmt.Printf("%+v\n", NewFinishedHouse(WithStyle(1),
        WithFloorMaterial("ground-tile"),
        WithCentralAirConditioning(false)))
}

作者:brynchen

出处:https://www.cnblogs.com/brynchen/p/18014631

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   brynchen  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示