Go 學習筆記 - Go 基礎語法(2)

Refrain_xxx發表於2021-07-06

條件語句

  1. if

    1. if的條件裡是不需要括號的
    2. if 的條件裡可以賦值
    3. if 條件裡賦值的變數作用於就在這個 if 語句裡面
      func readsfile() {
       const filename = "abc.txt" // 注意建立檔案
       // 寫法1 比較多
       // go 語言的函式是可以返回兩個值的
       countents, err := ioutil.ReadFile(filename)
       if err != nil {
           fmt.Print(err)
       } else {
           fmt.Printf("%s\n", countents)
       }
       // 寫法2 if可以跟多個語句
       if countents, err := ioutil.ReadFile(filename); err != nil {
           fmt.Print(err)
       } else {
           fmt.Printf("%s\n", countents)
       }
      }
  2. switch

    1. switch 會自動 break, 除非使用 fallthrough
    2. switch 後可以沒有表示式
    3. panic 會自動報錯
      func grade(score int) string {
       g := ""
       switch {
       case score < 0 || score > 100:
           panic(fmt.Sprintf(
               "Wrong scor: %d", score))
       case score < 60:
           g = "F"
       case score < 80:
           g = "C"
       case score < 90:
           g = "B"
       case score <= 100:
           g = "A"
           // default:
           //     panic(fmt.Sprintf("Wrong scor: %d", score))
       }
       return g
      }
      

    // 函式入口
    func main() {

    fmt.Println(
        grade(0),
        grade(20),
        grade(50),
        grade(69),
        grade(98),
        grade(100),
        // grade(101),  // grade 報錯不會返回前面的已經運算的結果,是直接跳出err
    )

    }


迴圈

  1. for

    1. for 的條件裡不需要括號

    2. for 的條件裡面可以省略初始條件,結束條件,遞增表示式

    3. 省略初始條件相當於while, go 語言中沒有 while

    4. 省略所有條件就是死迴圈

      func converToBin(n int) string {
        // 省略初始條件
        result := ""
        for ; n > 0; n /= 2 {
            lsb := n % 2
            result = strconv.Itoa(lsb) + result
        }
        return result
      }
      
      func printFile(filename string) {
        file, err := os.Open(filename)
        if err != nil {
            panic(err)
        }
        scanner := bufio.NewScanner(file)
        // 省略遞增條件,省略初始條件,只有結束條件
        // 相當於while, go 語言中沒有while
        for scanner.Scan() {
            fmt.Println(scanner.Text())
        }
      }
      
      func forever(){
        // 省略所有條件就是死迴圈
        // 死迴圈設計的這麼好寫是因為 go 中死迴圈使用的頻率很高
        for {
            fmt.Println("hello")
        }
      }
      
      // 函式入口
      func main() {
        fmt.Println(
            converToBin(5),
            converToBin(13),
            converToBin(23333),
            converToBin(0),
        )
        printFile("abc.txt")
        forever()    
      }

函式

  1. 函式格式 func eval(a, b int, op string) int 函式名在前 型別在後

  2. 函式可以返回多個值

  3. 函式返回多個值可以起名(起名適用於非常簡單的函式),對於呼叫者而言沒有區別

     func eval(a, b int, op string) (int, error) {
         switch op {
         case "+":
             return a + b, nil
         case "-":
             return a - b, nil
         case "*":
             return a * b, nil
         case "/":
             return a / b, nil
         default:
             // 函式的多返回值不要亂用,一般是一個返回值,加一個 err
             // panic("unsupported operation:" + op)  // panic 直接報錯中斷程式,不建議使用
             return 0, fmt.Errorf("unsupported operation: %s", op)
         }
     }
    
     // 取餘
     func div(a, b int) (q, r int) {
         // q,r 方便他人理解,返回值可以取個名字
         return a / b, a % b
    
         // 但是如果函式體過長,使用這這方法來 return 看起來會很累
         // q = a / b
         // r = a % b
         // return
     }
    
     // 函式入口
     func main() {
         fmt.Println(eval(3, 4, "*"))
         if result, err := eval(2, 3, "x"); err != nil {
             fmt.Printf("Error:", err)
         } else {
             fmt.Println(result)
         }
         // fmt.Println(div(13, 4))
         q, r := div(13, 4)
         s, _ := div(13, 4) // go 語言定義的變數一定要使用到,兩個返回的變數就可以使用 _ 跳過不需要的返回值
         fmt.Println(q, r, s)
     }
  4. 函數語言程式設計:函式的條件,引數包括函式內都可以巢狀函式

     // 簡化上面的方法,不需要那麼複雜的switch
     func apply(op func(int, int) int, a, b int) int {
         return op(a, b)
     }
    
     // 定義一個函式不需要再去轉換浮點
     func pow(a, b int) int {
         return int(math.Pow(float64(a), float64(b)))
     }
    
     // 函式入口
     func main() {
         fmt.Println(apply(pow, 2, 4))
         // 如果覺得定義一個包比較麻煩,也可以直接寫一個匿名函
         fmt.Println(apply(
             func(a, b int) int {
                 return int(math.Pow(float64(a), float64(b)))
             }, 2, 4))
     }
  5. go 語言函式沒有預設引數,可選引數,引數過載.
    只有一個可變引數列表

     // ...int 代表隨意傳多少個int都可以
     func sum(numbers ...int) int {
         s := 0
         for i := range numbers {
             s += numbers[i]
         }
         return s
     }
    
     // 函式入口
     func main() {
         fmt.Println(sum(1, 2, 3, 4, 5)) // 15
     }

指標

  1. go 的指標不能運算

  2. go 只有值傳遞一種方式
    (值傳遞:拷貝,原函式中的值不會變. 引用傳遞:會改變原函式中的值)
    Go 學習筆記 - Go 基礎語法(2)

    (值傳遞)
    Go 學習筆記 - Go 基礎語法(2) (通過指標+值傳遞實現引用傳遞的效果) ![Go 學習筆記 - Go 基礎語法(2)](https://cdn.learnku.com/uploads/images/202107/06/41040/hZqQ18KzT1.png!large) (object 的傳遞)
  3. 例子

     func swap(a, b *int) {
         *a, *b = *b, *a
     }
    
     // 函式入口
     func main() {
         a, b := 3, 4
         swap(&a, &b)
         fmt.Println(a, b)
     }
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章