<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] ## 變量作用域 ### 全局變量 全局變量是定義在函數外部的變量,它在程序整個運行周期內都有效。 在函數中可以訪問到全局變量。 ~~~go //定義全局變量num var num int64 = 10 func main() { fmt.Println(num) } ~~~ ### 局部變量 1、函數內定義的變量無法在該函數外使用,如果局部變量和全局變量重名,優先訪問局部變量。 2、語句塊定義的變量,只能在語句塊內訪問,(包括if條件判斷、for循環、switch語句上使用的定義的變量) eg:函數內定義的變量無法在該函數外使用 ~~~go func testLocalVar() { //定義一個函數局部變量x,僅在該函數內生效 var x int64 = 100 fmt.Printf("x=%d\n", x) } func main() { testLocalVar() fmt.Println(x) // 此時無法使用變量x } ~~~ eg:局部變量和全局變量重名,優先訪問局部變量 ~~~go //定義全局變量num var num int64 = 10 func testNum() { num := 100 fmt.Printf("num=%d\n", num) // 函數中優先使用局部變量 } func main() { testNum() // num=100 } ~~~ eg: ~~~ func testLocalVar2(x, y int) { fmt.Println(x, y) //函數的參數也是只在本函數中生效 if x > 0 { z := 100 //變量z只在if語句塊生效 fmt.Println(z) } //fmt.Println(z)//此處無法使用變量z } ~~~ eg: ~~~ func testLocalVar3() { for i := 0; i < 10; i++ { fmt.Println(i) //變量i只在當前for語句塊中生效 } //fmt.Println(i) //此處無法使用變量i } ~~~ ## 函數類型與變量 ### 定義函數類型 用`type`關鍵字來定義一個函數類型 ~~~go type funcName func(參數) 返回值 ~~~ eg: ~~~go type calculation func(int, int) int ~~~ 凡是滿足這個條件的函數都是calculation類型的函數 ~~~go func add(x, y int) int { return x + y } func sub(x, y int) int { return x - y } ~~~ add和sub都能賦值給calculation類型的變量。 ~~~go var c calculation c = add ~~~ ### 函數類型變量 ~~~go var c calculation c = add c(1,2)//3 n := sub n(5,1)//4 ~~~ ## 高階函數 高階函數分為函數作為參數和函數作為返回值兩部分。 ### 函數作為參數 ~~~go func add(x, y int) int { return x + y } func calc(x, y int, op func(int, int) int) int { return op(x, y) } func main() { ret2 := calc(10, 20, add) fmt.Println(ret2) //30 } ~~~ ### 函數作為返回值 ~~~go func do(s string) (func(int, int) int, error) { switch s { case "+": return add, nil case "-": return sub, nil default: err := errors.New("無法識別的操作符") return nil, err } } ~~~ ## 匿名函數和閉包 ### 匿名函數 函數當然還可以作為返回值,但是在Go語言中函數內部不能再像之前那樣定義函數了,只能定義匿名函數。匿名函數就是沒有函數名的函數,匿名函數的定義格式如下: ~~~go func(參數)(返回值){ 函數體 } ~~~ 匿名函數因為沒有函數名,所以沒辦法像普通函數那樣調用,所以匿名函數需要保存到某個變量或者作為立即執行函數: ~~~go func main() { // 將匿名函數保存到變量 add := func(x, y int) { fmt.Println(x + y) } add(10, 20) // 通過變量調用匿名函數 //自執行函數:匿名函數定義完加()直接執行 func(x, y int) { fmt.Println(x + y) }(10, 20) } ~~~ 匿名函數多用于實現回調函數和閉包。 ### 閉包 閉包指的是一個函數和與其相關的引用環境組合而成的實體。簡單來說,`閉包=函數+引用環境` ~~~go func adder() func(int) int { var x int return func(y int) int { x += y return x } } func main() { var f = adder() fmt.Println(f(10)) //10 fmt.Println(f(20)) //30 fmt.Println(f(30)) //60 f1 := adder() fmt.Println(f1(40)) //40 fmt.Println(f1(50)) //90 } ~~~ 變量`f`是一個函數并且它引用了其外部作用域中的`x`變量,此時`f`就是一個閉包。 在`f`的生命周期內,變量`x`也一直有效 eg1: ~~~go func adder2(x int) func(int) int { return func(y int) int { x += y return x } } func main() { var f = adder2(10) fmt.Println(f(10)) //20 fmt.Println(f(20)) //40 fmt.Println(f(30)) //70 f1 := adder2(20) fmt.Println(f1(40)) //60 fmt.Println(f1(50)) //110 } ~~~ eg2: ~~~go func calc(base int) (func(int) int, func(int) int) { add := func(i int) int { base += i return base } sub := func(i int) int { base -= i return base } return add, sub } func main() { f1, f2 := calc(10) fmt.Println(f1(1), f2(2)) //11 9 fmt.Println(f1(3), f2(4)) //12 8 fmt.Println(f1(5), f2(6)) //13 7 } ~~~ ## defer語句 Go語言中的`defer`語句會將其后面跟隨的語句進行延遲處理。在`defer`歸屬的函數即將返回時,將延遲處理的語句按`defer`定義的逆序進行執行,也就是說,先被`defer`的語句最后被執行,最后被`defer`的語句,最先被執行。 舉個例子: ~~~go func main() { fmt.Println("start") defer fmt.Println(1) defer fmt.Println(2) defer fmt.Println(3) fmt.Println("end") } ~~~ 輸出結果: ~~~go start end 3 2 1 ~~~ 由于`defer`語句延遲調用的特性,所以`defer`語句能非常方便的處理資源釋放問題。比如:資源清理、文件關閉、解鎖及記錄時間等。 ### defer執行時機 Go語言的函數中`return`語句在底層并不是原子操作,它分為給返回值賦值和RET指令兩步。而`defer`語句執行的時機就在返回值賦值操作后,RET指令執行前。 ![](https://img.kancloud.cn/70/c3/70c31fee31dfcb072cad3c732df02568_1289x455.png) ### defer經典案例 ~~~go func f1() int { x := 5 defer func() { x++ }() return x } func f2() (x int) { defer func() { x++ }() return 5 } func f3() (y int) { x := 5 defer func() { x++ }() return x } func f4() (x int) { defer func(x int) { x++ }(x) return 5 } func main() { fmt.Println(f1()) //5 返回值賦值 x=5 defer 一個匿名函數,不影響x,return 5 fmt.Println(f2()) //6 x已經被定義了,x=5,defer 匿名函數 x++ ,return 6 fmt.Println(f3()) //5 y定義,x=y=5 defer x++不起作用,return 5 fmt.Println(f4()) //5 x定義 x=5 ,x作為參數,傳的是副本,return 5 } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看