Go笔记-函数

【函数定义】

        func function_name([parameter1 type,parameter2 type])[return_value1 return_type1,return_value2 return_type2,...]{
            //TODO
        }
        func : 函数有func开始声明
        function_name : 函数名称,函数名和参数列表一起构成函数签名
        parameter_list : 参数列表,参数就像是一个占位符,当函数被调用时,你可以将值船体给参数,这个值被称为实际参数。
                        参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
        return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
        函数体:函数定义的代码集合
    备注:除了main() init()函数外,其他的函数尊循以上格式

【函数类型】

  Go中有三种类型:
  • 普通的带有名字的函数
  • 匿名函数或者lambda函数
  • 方法(Method)(与结构体有关)
  • 特殊的有main(),init()函数

【函数的书写格式及调用说明】

  简单举例,如果没有参数、参数类型、返回值,返回类型等,可以省略  
  func functionName(){  // 大括号必须和函数声明同行
      // TODO
  }
  使用方式:调用
  package.FunctionName(arg1,arg2...)  // 包中的函数若想被外部调用,函数必须首字母大写
  使用方式:声明
  type binOp func(int,int) int
 
     调用说明:
  • 包中的函数若想被外部调用,函数必须首字母大写
  • Go中函数重载是不被允许的,会导致一个编译错误
  • 函数也可以作为一个函数类型来声明
  • 函数可以赋值给变量
  • 一个变量不能被赋值不同的函数,就像一个变量不能被声明多次一样的道理
  • Go没有泛型的概念
  • 函数不能在其他函数里嵌套声明,也就是说不能再函数体内声明(创造)函数,一般在函数体内使用匿名函数来完成这个
  • 函数值之间可以互相比较,如果它们引用的是相同的函数或者都是nil的话,则认为它们是相同的

【函数的参数】

    按值传递:就是形参
    引用传递:按变量的内存地址传递,即取变量的内存地址,可以说就是指针,&变量,例如&a
    在函数调用中:切片(slice)字典(map)接口(interface)通道(channel)这样的引用类型都是默认使用引用传递(没有显式的指出指针)
    
    备注:在函数返回值多的时候,可以使用切片(返回值具有相同类型)或者结构体(返回值具有不同类型)

【函数的返回值】

    命名返回值:作为结果形参(result parameters)被初始化为响应类型的零值,当需要返回的时候,我们只需要一条简单的return。命名返回值 需要用()括起来,即使只有一个 func funcName()(ret int){}
    非命名返回值:作为结果形参,需要返回的时候,return 后面需要跟返回的内容,多个非命名返回值 需要用括号()括起来,一个的时候不需要括起来,func funcName()(int,int)
 1 // 举例
 2 package main
 3  
 4 import "fmt"
 5  
 6 var num int = 10
 7 var numx2, numx3 int
 8  
 9 func main(){
10     numx2, numx3 = getX2AndX3(num)
11     PrintValues()
12     numx2, numx3 = getX2AndX3_2(num)
13     PrintValues()
14 }
15  
16 func PrintValues(){
17     fmt.Printf("num = %d, 2x num = %d, 3x num = %d
", num, numx2, numx3)
18 }
19  
20 func getX2AndX3(input int)(int, int){ // 定义了函数返回的参数个数及参数类型
21     return 2 * intput, 3 * input
22 }
23  // 使用了命名返回值
24 func getX2AndX3_2(input int)(x2 int, x3 int){
25     x2 = 2 * input
26     x3 = 3 * input
27     // return x2, x3    
28     return  // 因为使用了命名返回值,所以return的时候,就按照命名返回值的变量返回。
29
备注:尽量使用命名返回值,使代码更加清晰,提高可读性
 

【传递变长参数】

     如果函数的最后一个参数是采用...type(type表示数据类型)的形式,那么这个函数就可以处理一个变长的参数,这个长度可以为0,这样的函数叫变长函数
  // 结构
  func myFunc(a,b,arg ...int){}
  // 事例及调用
  func Greeting(prefix string, who ...string)
  Greeting("Hello:","Joe","Anna","Robot")  // 变量who的值为[]string{"Joe","Anna","Robot"}
 
  在Greeting函数中,变量who的值为[]string{"Joe","Anna","Robot"}
  如果参数被存储在一个数组中arr,则可以使用arr...的形式传递参数调用 函数
 1 package main
 2  
 3 import "fmt"
 4  
 5 func main(){
 6     x := min(1,3,2,0)
 7     fmt.Printf("The minimum is: %d
", x)
 8     arr := []int{7,9,3,5,1}
 9     x = min(arr...)
10     fmt.Printf("The minimum in array arr is:%d",x)
11 }
12  
13 func min(a ...int)int{
14     if len(a) == 0 {
15         return 0
16     }
17     min := a[0]
18     for _, v := range a{
19         if v < min {
20             min = v
21         }
22     }
23     return min
24 }
 
    如果变长的参数类型不相同怎么办?
        使用结构体
  在这个结构体中存储任意类型的参数
  type Options struct{
      par1 type1,
      par2 type2,
      par3 type3,
  }
  // 使用
  FuncName(a,b,Option{par1:val1,par2:val2})
  使用空接口:该方案不仅可以用于长度未知的参数,可以用于不确定类型的参数,一般使用for-range循环,switch结构对每个参数的类型进行判断
  func typecheck(...,...,values ...interface{}){
      for _, value := range values{
          switch v := value.(type){
              case int:...
              case float:...
              case string:...
              case bool:...
              default:...
          }
      }
  }
 
        

【defer和追踪】

  关键字defer允许我们推迟到函数返回之前一刻,才执行被defer修饰的某个语句或者函数。类似其他语言中的finally
 1 // 示例
 2 package main
 3  
 4 import "fmt"
 5  
 6 func main(){
 7     funciton1()
 8 }
 9  
10 func function1(){
11     fmt.Printf("In function1 at the top
")
12     defer function2()
13     fmt.Printf("In function1 at the bottom
")
14 }
15  
16 func function2(){
17     fmt.Printf("function2:Defered until the end of the calling function!")
18 }
19  
20 // 输出
21 In function1 at the top
22 In function1 at the bottom
23 function2:Defered until the end of the calling function
    使用场景:
        关闭文件流,defer file.Close()
        解锁一个加锁的资源  defer mu.Unclock()
        打印最终报告 defer printFooter()
        关闭数据库链接 defer disconnectFromDB()
 
 

【递归函数】

  演示斐波那契和阶乘
 1 package main
 2  
 3 import "fmt"
 4  
 5 func main(){
 6     result := 0
 7     for i := 0; i<=10;i++{
 8         result = fibonacci(i)
 9         fmt.Printf(result)
10     }
11 }
12  
13 func fibonacci(n int)(ret int){
14     if n < 2{
15         ret = 1
16     }else{
17         ret = fibonacci(n-1)+fibonacci(n-2)
18     }
19     return
20 }
 1 package main
 2  
 3 import "fmt"
 4  
 5 func main(){
 6     var n int = 30
 7     result := factorial(n)
 8     fmt.Printf("n的阶乘是:%d",result)
 9     
10 }
11  
12 func factorial(n int)(res int){
13     if n > 0{
14         res = n * factorial(n-1)
15     }else{
16         res = 1
17     }
18     return
19 }
 
 

【闭包的应用:将函数作为返回值】

    代码来展示Go中如何将函数作为返回值
 1 package main
 2  
 3 import "fmt"
 4  
 5 func main(){
 6     func_param1 := add1(2)
 7     fmt.Println(func_param1(3))
 8     func_param2 := add2()
 9     fmt.Println(func_param2(3))
10 }
11  
12 func add1(n int) func(a int) int{
13     return func(a int) int{
14         return a + n
15     }
16 }
17  
18 func add2() func(a int) int{
19     return func(a int) int{
20         return a + 2
21     }
22 }
23  
24 // 输出结果
25 5
26 5
    
    作为闭包的应用
 1 package main
 2  
 3 import "fmt"
 4  
 5 func main(){
 6     var f = add()
 7     fmt.Println(f(10))
 8     fmt.Println(f(20))
 9     fmt.Println(f(30))
10 }
11  
12 func add() func(a int) int{
13     var x int
14     return func(a int) int{
15         x += a
16         return x
17     }
18 }
19 // 输出结果
20 10
21 30
22 60
    这个程序说明变量x的值在三次调用函数类型变量f()时,都被操作了累积了
    
    下面使用闭包来实现斐波那契数列的程序,放弃递归的方法
 1 package main
 2  
 3 import "fmt"
 4  
 5 func main(){
 6     
 7     var i int
 8     f := fibonacci()
 9     for i = 0; i < 10; i++{
10         fmt.Println(f(i))
11     } 
12 }
13  
14 func fibonacci() func(a int) int{
15     var res int
16     var last int
17     var last_last int
18     return func(a int) int{
19         if a < 2{
20             res = a
21         }else{
22             res = last_last + last
23         }
24         last_last = last
25         last = res
26         return res
27     }
28 }
 【学习参考处:https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/directory.md】
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/ymkfnuiwgij/p/7873462.html