入門筆記 --- Golang 語法注意事項(一)

炎灸紋舞發表於2018-12-18

1. import 寫法

  • 匯入標準庫或其他模組

    • 匯入標準庫,直接寫庫的名稱即可

    • 匯入其他模組可以使用相對路徑或絕對路徑

      import (
         "fmt"  // 庫的名稱
         "./modal" // 絕對路徑
         "my/modal" // 相對路徑(GOPATH/src/my/modal)  
      )
      複製程式碼
  • 特殊的匯入包的使用方法

    • 點操作
      使用點操作匯入的包你可以直接使用包內的函式而省略包名如fmt.Print()可以寫成Print()

    • 別名操作

      當你匯入的包名稱比較難記憶或者有命名衝突的時候,你可以使用別名操作可以把包命名成一個另外一個不會衝突且容易記憶的名稱

    • _ 操作 該操作只是引入一個包。當它匯入一個包時,包所有的init()函式都會執行,但是我們無法通過包名等來呼叫包內的匯出函式(我們有時候只需要包的init()函式而不需要其他函式) 所以,該操作的作用只是用來呼叫包的init() 函式

      import (
          . "fmt" // 點操作
          f "fmt" // 別名操作
          _ "my/modal" // _ 操作
      )
      複製程式碼
  • import 匯入包的過程 程式的初始化和執行都從main包開始,如果,mian包還匯入了其他的包,那麼在main包中,會先匯入其他的包(其餘包也一樣),然後再將包的全域性常量和變數進行初始化,接著在執行init()函式,最後在執行main函式。在匯入的其餘包中,重複匯入包、初始化常量、變數、執行init操作。

    入門筆記 --- Golang 語法注意事項(一)

2.雙引號、單引號、反引號 & byte與rune區別

  • 雙引號表示字串string,其實質是一個byte型別的陣列,Go語言的字串的位元組使用UTF-8編碼標識Unicode文字。它建立的字串是可解析、可轉義的字串字面量,但是它不支援多行.

    golang中string底層是通過byte陣列實現的。中文字元在unicode下佔2個位元組,在utf-8編碼下佔3個位元組,而golang預設編碼正好是utf-8。所以, str="abc 中文" 長度為10

  • 單引號表示rune型別,該型別是int32的別名,功能與int32相差無幾。它建立的是碼點字面量,是不做任何轉義的原始內容.

    它與byte型別類似,都用來表示字元型別的變數,但是

    • byte 等同於int8,常用來處理ascii字元
    • rune 等同於int32,常用來處理unicode或utf-8字元

    所以在使用rune型別將str = "abc 中文" 轉化型別,即 len([]rune(str))的值為6

  • 反引號是用來建立字串,但是它建立的是原生的字串字面量(與雙引號表示的string不同),它可以由多行組成,但是不支援任何轉義序列,原生的字串字面量多用於書寫多行訊息、HTML以及正規表示式。

3.變數宣告後預設值

  • 數字型別(包括整型、浮點型:int8、byte、int16、uint、uintprt、float32、float64):預設值為0。
  • 布林型別(bool):預設值為false。
  • 複數型別(complex64、complex128):預設值為0+0i。
  • 字串(string):預設值為”“。
  • 錯誤型別(error):預設值為nil。
  • 派生型別:其中如:指標、切片、字典、通道、介面等:預設值為nil。而陣列的預設值要根據其資料型別來確定。例如:var a [4]int,其預設值為[0 0 0 0]。

4.錯誤捕獲&異常處理機制

  • 其他語言處理機制 在Java、JavaScript、PHP等語言中,異常處理是依靠try...catch、throw來處理。

    try{
       // 可能發生異常的語句
    }catch(e){
       // 捕獲到錯誤e,停止執行上面的語句,跳轉到這個程式碼塊
    }finally{
       // 無論上述程式碼塊怎麼執行,這部分程式碼都肯定執行
    }
    
    throw Error("") // 丟擲錯誤,可被try...catch捕獲
    複製程式碼
  • go錯誤處理機制 在go中,依靠panic、recover函式來處理,它們的作用分別與throw和catch語句相似,當然也存在不同之處。

  • panic函式

    func panic(interface{})//接受任意型別引數 無返回值
    複製程式碼
    • panic可以將原有的控制流程中斷,進入到一個"恐慌"流程。這種恐慌流程可以顯式呼叫panic()函式產生或者由執行時錯誤產生(例如訪問越界的陣列下標)。
    • panic會在呼叫它的函式中向本層和它的所有上層逐級丟擲,若一直沒有recover將其捕獲,程式退出後會產生crash。
    • panic並不會影響defer的函式的執行。
    • 與其他語言throw相識,會丟擲異常。
  • recover函式

    func recover() interface{}//可以返回任意型別 無引數
    複製程式碼
    • 它是一個內建函式,可以使進入令人恐慌的進行中的goroutime恢復(即捕獲panic丟擲的異常)。
    • 在正常的執行過程中,呼叫recover會返回nil,並且沒有其它任何效果。
    • 功能與其他語言的catch相似,可以捕獲異常。
    • 一般情況下,recover()應該在一個使用defer關鍵字的函式中執行以有效擷取錯誤處理流程。如果沒有在發生異常的goroutine中明確呼叫恢復
  • defer函式

    • 它是go的延遲執行語句,它會延遲執行一個函式,在他所屬的那個函式的return將結果寫入返回值後,才執行被延遲的函式

    • defer執行順序

          * 執行到return語句->
          * return給返回值賦值->
          * 執行的defer延遲的函式->
          * 函式攜帶返回值返回
      複製程式碼
    • 多個defer的執行順序為LIFO(後進先出),所有的的份兒儲存在一個延遲呼叫棧

    • defer修飾的函式值和引數取值都會在defer語句執行時儲存,等到上一級函式返回時,按LIFO執行defer函式

      如果函式的引數為指標,則需要注意函式執行時,引數是否修改,因為defer執行時,儲存的也是引數的指標

    • defer函式的任何返回都會被丟棄

    • 如果一個defer的函式值為nil,則這個defer函式會在函式執行時panic(異常),而不是在defer語句執行時。

    • 如果defer修飾的是一個含有閉包的函式(同時你也想讓閉包函式執行)

    • 那麼你需要定義一個變數,將函式返回的閉包複製給這個變數後再修飾這個變數

      func test(){
           return func(){}
      }
      test1 := test()
      defer test1
      複製程式碼
    • 或者你直接在修飾的後面再加個()代表返回的閉包立即執行

      defer test()()
      複製程式碼

相關文章