首页 > 其他分享 >Go语言精进之路读书笔记第25条——了解变长参数函数的妙用

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

时间:2024-02-13 16:23:04浏览次数:28  
标签:25 函数 ... 读书笔记 参数 func FinishedHouse Go string

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)))
}

标签:25,函数,...,读书笔记,参数,func,FinishedHouse,Go,string
From: https://www.cnblogs.com/brynchen/p/18014631

相关文章

  • 三十五、Django实践的笔记
    Django时间时区datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S'),得到的是标准时区的时间字符串https://blog.csdn.net/qiaominghe/article/details/86593744https://blog.csdn.net/qq_42778001/article/details/111088130https://zhuanlan.zhihu.com/p/24246164fro......
  • Go 100 mistakes - #6: Interface on the producer side
        Aninterfaceshouldliveontheconsumersideinmostcases.However,inparticu-larcontexts(forexample,whenweknow—notforesee—thatanabstractionwillbe helpfulforconsumers),wemaywanttohaveitontheproducerside.Ifwedo,w......
  • Go - When to use interfaces?
    CommonbehaviorDecouplingRestrictingbehavior Commonbehavior: Decoupling:Restrictingbehavior:Thelastusecasewewilldiscusscanbeprettycounterintuitiveatfirstsight.It’sabout restrictingatypetoaspecificbehavior.Let’simagine......
  • Go语言精进之路读书笔记第24条——方法集合决定接口实现
    24.1方法集合方法决定接口实现:如果某个自定义类型T的方法集合是某个接口类型的方法集合的超集,那么就说类型T实现了该接口,并且类型T的变量可以赋值给该接口类型的变量Go语言规范,对于非接口类型的自定义类型T:类型T,方法集合由所有receiver为T类型的方法组成类型*T,方法集合由所......
  • Go语言精进之路读书笔记第23条——理解方法的本质以选择正确的receiver类型
    和函数相比,Go语言中的方法在声明形式上仅仅多了一个参数,Go称之为receiver参数。receiver参数是方法与类型之间的纽带。Go方法特点:方法名的首字母是否大写决定了该方法是不是导出方法。方法定义要与类型定义放在同一个包内。由此可以推出,不能为原生类型(如int/float64/map等)添加......
  • C1. Good Subarrays (Easy Version)
    找子数组的个数双指针#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=2e5+10;inta[N];voidsolve(){ intn; cin>>n; for(inti=1;i<=n;i++)cin>>a[i]; intl=1,r=1; intans=0; while(l<=r){ if(l>n||r>......
  • Go语言精进之路读书笔记第22条——使用defer让函数更简介、更健壮
    22.1defer的运行机制在Go中,只有在函数和方法内部才能使用defer。defer关键字后面只能接函数或方法,这些函数被成为deferred函数。defer将它们注册到其所在goroutine用于存放deferred函数的栈数据结构中。在执行defer的函数退出前,按后进先出(LIFO)的顺序调度执行。22.2defer的......
  • Google Earth Pro谷歌地球专业版
    GoogleEarthPro谷歌地球专业版,标准版,在国内可以用的,常见的黑屏问题可以解决的需要解决黑屏问题的可以找我(V×:F2233F) ......
  • Go语言精进之路读书笔记第21条——让自己习惯于函数是"一等公民"
    21.1什么是"一等公民"(1)正常创建//$GOROOT/src/fmt/print.gofuncnewPrinter()*pp{p:=ppFree.Get().(*pp)p.panicking=falsep.erroring=falsep.wrapErrs=falsep.fmt.init(&p.buf)returnp}(2)在函数内创建,定义匿名函数赋值给......
  • Go语言精进之路读书笔记第20条——在init函数中检查包级变量的初始状态
    20.1认识init函数init函数的特点:运行时调用,Go程序中不能显式调用顺序执行,等待一个init函数执行完毕并返回后再执行下一个init函数在整个Go程序生命周期内仅会被执行一次先被传递给Go编译器的源文件中的init函数先被执行,同一个源文件中的多个init函数按声明顺序依次执行。但......