• 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】
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译
    编译原理-第二章 一个简单的语法指导编译器-2.3 语法定义
    编译原理-第二章 一个简单的语法指导编译器-2.2 词法分析
    LeetCode 1347. Minimum Number of Steps to Make Two Strings Anagram
    LeetCode 1348. Tweet Counts Per Frequency
    1349. Maximum Students Taking Exam(DP,状态压缩)
    LeetCode 1345. Jump Game IV(BFS)
    LeetCode 212. Word Search II
    LeetCode 188. Best Time to Buy and Sell Stock IV (动态规划)
    LeetCode 187. Repeated DNA Sequences(位运算,hash)
  • 原文地址:https://www.cnblogs.com/ymkfnuiwgij/p/7873462.html
Copyright © 2020-2023  润新知