
第4章函数与方法4.1 函数基础函数声明// 基本语法func函数名(参数列表)返回值列表{// 函数体}// 示例funcadd(aint,bint)int{returnab}// 简写参数类型相同类型funcadd(a,bint)int{returnab}多返回值// Go 函数支持多返回值funcdivide(a,bfloat64)(float64,error){ifb0{return0,errors.New(除数不能为零)}returna/b,nil}// 使用result,err:divide(10,3)iferr!nil{fmt.Println(错误:,err)}else{fmt.Println(结果:,result)}命名返回值// 命名返回值相当于在函数内部声明变量funcswap(a,bint)(x,yint){xb yareturn// 裸返回自动返回命名返回值}// 使用x,y:swap(1,2)fmt.Println(x,y)// 输出2 14.2 函数作为值Go 中函数是一等公民可以赋值给变量、作为参数传递// 函数作为变量add:func(a,bint)int{returnab}fmt.Println(add(1,2))// 输出3// 函数作为参数funcapply(a,bint,operationfunc(int,int)int)int{returnoperation(a,b)}result:apply(10,5,func(a,bint)int{returna-b})fmt.Println(result)// 输出5// 函数作为返回值funccreateMultiplier(factorint)func(int)int{returnfunc(xint)int{returnx*factor}}double:createMultiplier(2)fmt.Println(double(5))// 输出104.3 闭包闭包是引用了外部变量的函数// 闭包示例计数器funccounter()func()int{count:0returnfunc()int{countreturncount}}c:counter()fmt.Println(c())// 1fmt.Println(c())// 2fmt.Println(c())// 3// 闭包示例函数工厂funcgreet(prefixstring)func(string)string{returnfunc(namestring)string{returnprefix, name!}}hello:greet(你好)goodbye:greet(再见)fmt.Println(hello(张三))// 你好, 张三!fmt.Println(goodbye(李四))// 再见, 李四!4.4 可变参数// 可变参数函数funcsum(nums...int)int{total:0for_,n:rangenums{totaln}returntotal}fmt.Println(sum(1,2,3))// 6fmt.Println(sum(1,2,3,4,5))// 15// 切片作为可变参数numbers:[]int{1,2,3,4,5}fmt.Println(sum(numbers...))// 154.5 方法方法是带有接收者的函数// 定义结构体typeRectanglestruct{Width,Heightfloat64}// 值接收者方法func(r Rectangle)Area()float64{returnr.Width*r.Height}// 指针接收者方法可以修改接收者func(r*Rectangle)Scale(factorfloat64){r.Width*factor r.Height*factor}// 使用rect:Rectangle{Width:10,Height:5}fmt.Println(面积:,rect.Area())// 50rect.Scale(2)fmt.Println(缩放后面积:,rect.Area())// 200值接收者 vs 指针接收者typeCounterstruct{Valueint}// 值接收者操作副本不影响原值func(c Counter)Increment(){c.Value// 修改的是副本}// 指针接收者操作原值func(c*Counter)Increment(){c.Value// 修改的是原值}// 选择原则// 1. 如果需要修改接收者使用指针接收者// 2. 如果接收者是大型结构体使用指针接收者避免复制// 3. 一致性同一类型的方法应使用相同的接收者类型4.6 内置函数Go 提供了一些内置函数// len - 获取长度s:Hellofmt.Println(len(s))// 5// cap - 获取容量slice:make([]int,5,10)fmt.Println(cap(slice))// 10// make - 创建切片、map、channelslice:make([]int,5)// 长度为5的切片m:make(map[string]int)// 空mapch:make(chanint,100)// 带缓冲的channel// new - 分配内存返回指针p:new(int)// *int 类型*p42fmt.Println(*p)// 42// copy - 复制切片src:[]int{1,2,3}dst:make([]int,len(src))copy(dst,src)// delete - 删除map元素m:map[string]int{a:1,b:2}delete(m,a)// panic - 触发恐慌// recover - 捕获恐慌4.7 练习编写函数计算斐波那契数列实现一个函数工厂根据参数返回不同的排序函数使用闭包实现一个简单的缓存为自定义类型实现 Stringer 接口4.8 下一章下一章我们将学习 Go 语言的数组、切片与 Map。