2. 流程控制 與 函式 |《 刻意學習 Golang 》

jerrkill發表於2019-03-07

起源:學習 golang 筆記,看到 @Summer 的刻意練習、每日精進後,收益匪淺。程式設計就是需要刻意練習。堅持用此方法把 golang 看完。
書寫思路說明:對比 php,理解 Go 的特性,然後程式碼示例加深理解,並進行刻意的練習達到精進

Go 基礎

流程控制和函式

Go 中流程控制有三大類:條件判斷、迴圈控制、無條件跳轉

  • if
  • goto
  • for
  • switch

if

  • 不需要()
  • 允許宣告變數「作用域只在條件邏輯內」
if a > b {
    //
} else {
    //
}
// 宣告變數
if x := computedValue(); x > 10 {
    fmt.Println("x is greater than 10")
} else {
    fmt.Println("x is less than 10")
}
// 多個條件
if a > 4 {
    //
} else if a < 5 {
    //
} else {
    //
}

goto

跳轉到必須在當前函式定義的標籤

func myFunc() {
    i := 0
Hear:   // 這行的第一個詞,以冒號結束作為標籤
    fmt.Println(i)
    i++
    goto Hear   // 跳轉到 Hear 去「大小寫敏感」
}

for

go 中的 for 的三大用處

  • 迴圈讀取資料map slice = php 的 foreach
  • while 來控制邏輯 = php 的 while
  • 迭代操作 = php 的 for
// foreach
for k, v := range map {
    fmt.Println("map's key is ", k)
    fmt.Println("map's value is ", v)
}
//由於 Go 支援 “多值返回”, 而對於“宣告而未被呼叫”的變數, 編譯器會報錯, 在這種情況下, 可以使用 _ 來丟棄不需要的返回值
for _, v := range map {
    //
}
// while
sum := 1
for sum < 100 {
    sum += sum
}
// for
sum := 0
for i := 0; i < 10; i++ {
    sum += i
}

switch

與 Php 比較

  • case 的資料型別必須一致
  • 表示式不必是常量或者整數,可以沒有表示式就找 true
  • 自帶 break
  • 支援多值聚合在一個 case 裡面
  • fallthrough 強制執行下一個 case
  • case 裡面不能有重複條件
i := 10
switch i {
case 10:
    fmt.Println("i match 10")
    fallthrough // 強制執行下一個 case
case i*2 - 10:
    fmt.Println("表示式")
    fallthrough
case 1, 2, 3: // 不能有重複條件 如果有 10 就會報錯
    fmt.Println("多值聚合 i is 1 2 or 10")
    fallthrough
case i == 10:
    fmt.Println("bool 型別會報錯")
    fallthrough
case 4:
    fmt.Println("預設就有 break 的")
    default:
    fmt.Println("default")
}

函式

與 Php 不一樣的地方

  • 關鍵字 func
  • 引數 & 返回值需要指定型別 name type
  • 多返回值
  • 變參
// 多返回值1 引數相同型別可以簡寫
func sumAndProduct(a, b int) (int, int) {
    return a + b, a * b
}
// 多返回值2
func sumAndProduct(a int, b int) (sum int, product int) {
    sum = a + b
    product = a * b
    return
}
// 變參
func myfunc(arg ...int) {
    for _, n := range arg { // arg 是一個int 的 slice

    }
}

傳值與傳指標

PHP 一樣,傳值是傳值的 copy, & 傳地址。\
不同的是:\
channel,slice,map這三種型別的實現機制類似指標,所以可以直接傳遞,而不用取地址後傳遞指標

defer

Php 中沒有

作用:defer 後指定的函式會在函式退出前呼叫。多個 defer 呼叫順序後進後出「棧」

func ReadWrite() bool {
    file.Open("file")
    defer file.close() // 函式退出前這裡會被呼叫執行
    if FailureX {
        return false
    }
    return true
}

函式作為值型別

函式當做值來傳遞

  • 宣告函式型別 = 定義資料型別
  • 實現函式型別 = 實現資料型別
  • 通過型別跟函式名 = 宣告一個變數
type testInt func(int) bool // 宣告型別
// 型別的實現
func isTwo(integer int) bool {
    if (integer % 2) {
        return true
    }
    return false
}
// 型別的實現
func isFive(integer int) bool {
    if (integer % 5) {
        return true
    }
    return false
}
// 宣告引數函式型別
func filter(slice []int, f testInt) []int {
    var result = []int
    for _, value := range slice {
        if f(value) {
            result = append(result, value)
        }
    }
    return result
}

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    fmt.Println("slice = ", slice)
    two := filter(slice, isTwo)
    five := filter(slice, isFive)
    fmt.Println("倍 2 整除的:", two)
    fmt.Println("被 5 整除的:", five)
}

Panic 和 Recover

Go 沒有 try catch \
用的 Panic Recover

  • Panic 中斷流程,並退出,延時函式繼續執行
  • Recover 可以捕獲 Panic 中的引數

main 函式和 init 函式

引用圖片

import

與 PHP 對比 \
類似於 include require

  • 絕對路徑 相對於 GOROOT 目錄
  • 相對路徑跟 PHP 一樣,但不推薦使用
  • . 操作
  • 別名操作:顧名思義
  • _ 操作:不匯入包而是呼叫包的 init()
// . 操作 可以省略字首的包名
import (
    . "fmt"
)
fmt.Println("hello world") 可以省略的寫成 Println("hello world")
// 別名
import f "fmt"
f.Println("hello world")

高度自律,深度思考,以勤補拙

相關文章