Go(4 [函數])

Go函數,

寫法:聲明函數:func 函數名(參數列表)[(返回值列表)]{}

特點:

  1. 不支持重載,一個包不能有兩個名字一樣的函數

  2. 函數是一等公民,函數也是一種類型,一個函數可以賦值給變量

  3. 匿名函數

  4. 多返回值

函數傳遞方式:

  1. 值類型

  2. 引用類型

  3. map slice、 chan、指針、 interface默認以引用的方式傳遞

無論是值傳遞,還是引用傳遞,傳遞給函數的都是變量的副本,不過,值傳遞是值的拷貝。引用傳遞是地址的拷唄,一般來說,地址拷唄更爲高效。而值拷貝取決於拷貝的對象大小,對象越大,則性能越低。

測試一:函數賦值

func add (a int,b int) int  {
   return  a + b
}




func main()  {
   c:=add

   fmt.Printf("%P %T %p %T \n",c,add,c,add)

   sum :=add(30,40)
   fmt.Println(sum)

   ccc :=c(30,40)
   fmt.Println(ccc)
}

一:自定義函數:

type add_func func(int ,int)int

//自定義一個函數類型,也可以傳遞
func operator(op add_func,a ,b int) int {
    //值傳遞給自定義函數
   return op(a,b)

}

func main(){
sum :=operator(c,100,200)
fmt.Println(sum)
}

測試二:返回值寫法

func test2(a,b int)(c int)  {
   c = a +b
   //不必寫c,默認會把c返回
   return
}
func test3(a,b int)(sum int,avg int)  {
   sum  = a +b
   avg = (a +b)/2
   return
}
func main(){
e,q:=test3(6,7)
fmt.Println(d,e,q)
}

二:可變參數:     (這裏又有...用法)

func add(arg…int) int {
}
0個或多個參數
func add(a int, arg…int) int {
}
1個或多個參數
func add(a int, b int, arg…int) int {
}
2個或多個參數

其中arg是一個slice,我們可以通過arg[index]依次訪問所有參數通過len(arg)來判斷傳遞參數的個數

測試三:多個值傳遞

func test4(arg...int) int {
   var sum int
   fmt.Println("test4---arg",arg)
   for i:=0;i<len(arg);i++{
      sum = sum + arg[i]
   }
   return sum
}

func testArg()  {
   fmt.Println(test4(1))
   fmt.Println(test4())
   fmt.Println(test4(1,3,4,5,6,2121,21,12,))
}
func main(){
testArg()
}

三:關鍵字defer

  1. 當函數返回時,執行defer語句,因此,可以用來做資源清理 例如:

    1. 關閉文件句柄

    2. 鎖資源釋放

    3. 數據庫連接釋放

  2. 多個defer語句,按先進後出的方式執行,

  3. defer語句中的變量,在defer聲明時就決定了

示例1:

func test5()  {
   i:=0
   defer fmt.Println("test5",i)
   i++
   return
}
>>>test5 0

示例二:

func test6()  {
   for i:=0;i<5;i++{
      defer fmt.Println("test6",i)
   }
}
>>
test6 4
test6 3
test6 2
test6 1
test6 0

四:函數遞歸

func test7(a int) int  {
   if a == 1{
      return 1
   }
   return test7(a-1) * a
}

n:=test7(5)
fmt.Println(n)

五:斐波那契

func test8( a int) int  {
   if a <= 1{
      return 1
   }
   return test8(a -1) + test8(a - 2)
}

for i:=0;i<20;i++{
   n:=test8(i)
   fmt.Printf("%d ",n)
}

六:閉包:

func test9() func(int) int  {
   var x int
   fmt.Println("---XXX",x)
    //返回一個匿名函數
   return func(a int) int {
      //x就是閉包裏面的全局變量
      //因爲全局變量生命週期長

      //調用的結果存在x裏面,所以下次調用的時候,是在之前結果基礎上在相加、
      //觀察哪個是外部變量, 這個外部變量就是成員變量!,值一直會在, 這裏x就是外部變量
      fmt.Println("---funcXXX",x)
      x+=a
      return x
   }

}
func main(){

var f = test9()
fmt.Println(f(1),"-")
fmt.Println(f(20),"-")
fmt.Println(f(300),"-")

}

》》
---XXX 0
---funcXXX 0
1 -
---funcXXX 1
21 -
---funcXXX 21
321 -

例子二:

func test10(suffix string) func(string) string {
   //suffix 可以當成 成員變量, 一直存在
   f:= func(name string) string {
      if !strings.HasSuffix(name,suffix){
         return name + suffix
      }
      return name
   }
   return f
}

func main(){

func1 :=test10(".bmp")
func2 :=test10(".jgp")

fmt.Println(func1("zcq"))
fmt.Println(func2("rch"))
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章