一篇文章帶你瞭解 Go 語言基礎之函數(下篇)

前言

Hey,大家好呀,我是星期八,這次咱們來學習一下函數的最後一些知識,快來上車叭。之前已經分享了:一篇文章帶你瞭解 Go 語言基礎之函數(上篇)一篇文章帶你瞭解 Go 語言基礎之函數(中篇),沒趕上車的小夥伴去看看吧。

上次主要回顧

上述我們知道,定義一個函數,可以將函數內存分配理解如下。

同時我們也知道,無論進行什麼操作,只會操作上面的

函數和變量

函數名即變量

不知道你想過沒,定義一個變量,接收一個函數,就像這樣。

package main
import "fmt"
func say() {
    fmt.Println("say")
}
func main() {
    var s1 = say
    s1()
}

執行結果如下。

可以發現,通過一個變量接收一個函數名,在通過變量名 + 括號執行,是沒有問題的。

那麼,這個變量是什麼類型的呢???

fmt.Printf("%T\n",s1)

執行結果

如果我將 say 函數改一下呢?

func say(s int) int{
    fmt.Println("say")
    return 1
}
fmt.Printf("%T\n",s1)

可以發現,如果函數參數返回值不一樣,打印出來的類型也是不一樣的。

定義函數類型

上述我們知道,可以通過變量接收一個函數名

通過變量接收函數名沒有約束的,不管函數幾個參數,幾個返回值,都可以接收,真是活出了動態語言的樣子。

定義函數類型就是限制變量接收函數,只能接收指定格式函數

主要用到type關鍵字。

格式

type 變量名 func([參數類型,參數類型]) [返回值類型]
中括號表示可選參數

例如

type a func()
type b func(int)
type a func(int,int) int

具體代碼

package main
import "fmt"
/*
    定義一個函數類型的變量
    接收的函數參數必須是兩個int類型
    函數的返回值也必須是int類型
*/
type cType func(int int) int
func say1(a b int) int {
    fmt.Println("say"a+b)
    return 1
}
func say2(a b int) {
    fmt.Println("say")
}
func main() {
    var s1 cType
    s1 = say1//調用s1其實調用的就是say1
    s1(11)
    //var s2 cType
    //s2 = say2//報錯,cannot use say2 (type func(int, int)) as type cType in assignment
}

高階函數


千萬不要被這個名字唬住了。

簡單點說,高階函數就是把函數當作參數或者把函數當作返回值

函數當作參數

package main
import "fmt"
func add(x int y int) int {
    return x + y
}
func calc(x int y int other func(int int) int) int {
    return other(x y)
}
func main() {
    //將add函數傳入第三個參數
    var result = calc(34 12 add)
    fmt.Println(result)
}

函數當作返回值

package main
import "fmt"
func add(x int y int) int {
  return x + y
}
func test() (func(int int) int) {
  return add
}
func main() {
  var a = test()
  fmt.Println(a(12))
}

至於上述兩個的功能,恕小生不才,至今用到的場景不多。

匿名函數

匿名函數顧名思義,就是沒有名字的函數。

語法如下

func([參數,參數...])[(返回值,返回值)]{
  代碼
}()
//匿名函數後面必須跟括號,直接執行

例如

func()  {
}()
func(x int, y int) (int) {
  return x + y
}()

代碼

package main
import "fmt"
func main() {
    //s1等於一個匿名函數,並且直接執行
  var s1 = func(x int y int) (int) {
    return x + y
  }(12)
  fmt.Println(s1)
}

閉包

閉包,這個有點不太理解,簡單點說就是函數里面套了一個函數裏面函數引用的外面函數變量

示例

package main
import "fmt"
func other() func() {
    //返回的是一個函數類型
  var a = 666
  return func() {
        //內部函數使用的是外面函數的a
    fmt.Println(a)
  }
}
func main() {
  var o = other()
  o()
}

執行結果。

結果是沒有問題的。

雖然我們以前學過,函數執行完畢後,裏面的變量會回收。

但是在用到閉包時,可以這樣理解,裏面函數使用了外面函數的變量,那這個變量就不會被回收。

總結

本文主要講述了函數及變量高階函數匿名函數,**閉包,**其中閉包是比較難以理解的, 一定要花點心思。寶劍鋒從磨礪出, 梅花香自苦寒來, 一定要多多實踐。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/hT3p3bPvVBLzCLT0dn4hUg