認真一點學 Go:5. 常量及運算子

printlove發表於2021-09-13

學到什麼

  1. 什麼是常量?

  2. 如何定義常量?

  3. 常量和變數有什麼不同?

  4. 如何使用常量?

  5. 有哪些運算子?

  6. 如何使用運算子?

  7. 運算子的優先順序?

常量

1. 概念

常量的值在程式執行期間是不能改變的,而變數的值在執行期間是可以改變的。

舉個實際使用到常量的幾個場景:

  • web開發時,根據業務定義的錯誤碼

  • 程式的發行版本號

  • 資料庫連線池數量(如果不通過配置檔案時)

  • 等等

在使用時,只要你確定在程式執行期間不改變它的值,就可以使用常量。

2. 定義

常量的定義格式: const 常量名 [常量型別] = 常量值

[常量型別] 可以省略,編譯器會根據值來推導型別。


// 顯示定義

const b string = "abc"

// 隱式定義

const b = "abc"

對於常量值的資料型別,只可以定義為布林型、數字型(整數型、浮點型和複數)和字串型。


// 預設 bool

const isOpen = true

// 預設 rune,int32 的別名

const MyRune = 'r'

// 預設 int

const occupancyLimit = 12

// 預設 float64

const vatRate = 29.87

// 預設 complex128

const complexNumber = 1 + 2i

// 預設 string

const hotelName = "Gopher Hotel"

定義時還有兩種寫法。


// 第一種,常量塊的形式

const (

    isOpen = true

    MyRune = 'r'

)

// 第二種,並行賦值

const limit, rate = 12, 29.8

注:第一種“常量塊”的形式是實際中用的比較多的。

3. 隱式定義不限制

是什麼意思呢?意思就是我在定義時,省略了資料型別後,值的大小是不受限制,即不會產生溢位。


const num = 111111111111111111111111111111111111111111111

如果顯示定義數字型常量,它必然會有儲存空間大小限制。比如:定義一個int64 型別,它的最大值為 9223372036854775807,但如果超過這個最大值,就會溢位,程式自然會拋異常,還原如下:


// 檔名 main.go

package main

import "fmt"

func main() {

    // 最大值 + 1

    const num int64 = 9223372036854775808

}

執行後輸出以下結果:


go run main.go

## 輸出

.\main.go:6:8: constant 9223372036854775808 overflows int64

4. iota 用法

iota是 Go 語言中的一個關鍵字,先看程式碼,再解釋。


const (

    a = iota  // a = 0

    b         // b = 1

    c         // c = 2

    d = 5     // d = 5   

    e         // e = 5

)

iota 從0開始,每增加新的一行就會自動加一,直到重新宣告一個 constiota 重置為0,遇到新的賦值時 iota 將不再應用。

再說說一個 const塊 中出現多個 iota 關鍵字時是什麼情況。


const (

    a = iota  // a = 0

    b         // b = 1

    c         // c = 2

    d = 5     // d = 5   

    e = iota  // e = 4

)

d 常量賦值為 5 時,iota 只是暫時不應用,直到再次使用,而 iota 繼續保持在增加新的一行時自增一。

iota 也可以參加運算,舉幾個例子就明白了。


// 從1開始自動加一

const (

    Apple = iota + 1 // Apple=1 

    Cherimoya        // Cherimoya=2 

    Elderberry       // Elderberry=3

)

// 並行賦值兩個常量,iota 只會在第一行增長一次

// 而不會因為使用了兩次就增長兩次

const (

    Apple, Banana = iota + 1, iota + 2 // Apple=1 Banana=2

    Cherimoya, Durian   // Cherimoya=2 Durian=3

    Elderberry, Fig     // Elderberry=3, Fig=4

)

// iota參與位運算

const (

    Open = 1 << iota  // 0001

    Close             // 0010

    Pending           // 0100

)

運算子

1. 分類

  • 算術運算子:+(加),-(減),*(乘),/(除),%(求餘),++(自增),–(自減)

  • 比較運算子:==(等於),!=(不等於),>(大於),<(小於), >=(大於等於), <=(小於等於)

  • 賦值運算子:=(右值賦值給左側), += , -=, *=, /=,%=, &=, |=, ^=, >>=, <<= (前面的都是左側值和右側值運算後再賦值給左側)

  • 位運算子: ****&(按位與),|(按位或),^(按位異或/取反),>>(右移位),<<(左移位)

  • 邏輯運算子:&&(與),||(或),!(非)

  • 其他運算子:&(取變數地址),*(指標)

2. 算數運算子

初始化 a 和 b 兩個變數進行運算,使用如下:


a := 10

b := 3

fmt.Println("a+b=", a+b)  // a+b= 13

fmt.Println("a-b=", a-b)  // a-b= 7

fmt.Println("a*b=", a*b)  // a*b= 30

fmt.Println("a/b=", a/b)  // a/b= 3

// 不支援 ++a

a++

fmt.Println("a++=", a)  // a++= 11

// 錯誤寫法:fmt.Println(a++),

// 必須經過運算後才可使用, 自減也是一樣

// 不支援 --a

a--

fmt.Println("a--=", a)  // a--= 10

注:自增和自減去只支援後置的++或–。

3. 比較運算子

初始化 a 和 b 兩個變數,進行比較,使用如下:


a := 10

b := 3

fmt.Println("a==b:", a == b)  // a==b: false

fmt.Println("a!=b:", a != b)  // a!=b: true

fmt.Println("a>b:", a > b)    // a>b: true

fmt.Println("a>=b:", a >= b)  // a>=b: true

fmt.Println("a<b:", a < b)    // a<b: false

fmt.Println("a<=b:", a <= b)  // a<=b: false

4. 賦值運算子

初始化 a 變數 為10,使用如下:


// 將 10 賦值給 a 變數

var a = 10  // 簡寫方式: a := 10

// 在10的基礎上加2

// 等價於 a = a + 2

a += 2  // 12

// 在12的基礎上減3

// 等價於 a = a - 3

a -= 3  // 9

// 在9的基礎上乘以2

// 等價於 a = a * 2

a *= 2  // 18

// 在18的基礎上除以3

// 等價於 a = a / 3

a /= 3  // 6

// 在6的基礎上對4求餘

// 等價於 a = a % 4

a %= 4  // 2

注:&=、|=、^=、>>=、<<= 運算子就省略不寫了(不是懶,感覺太囉嗦了),看懂下面的位運算子的意思,照上面的類比理解就明白了。

5. 位運算子

初始化 a 和 b 兩個變數進行運算,前提要明白十進位制如何轉化為二進位制,使用如下:


a := 4  // 二進位制: 0100

b := 3  // 二進位制: 0011

// 按位與

// 對應位都為1時,結果為1

a & b  // 0

// 按位或

// 對應位有一個為1時,結果為1

a | b  // 7

// 按位異或

// 對應位相同時為0,不相同時為1

a ^ b  // 7

// 按位取反

// 取反後變成1100, 最高位1代表負數

^b  // -4

// 按位右移

// 將二進位制 0100 向右移動一位變成 0010

a >> 1  // 2

// 按位左移

// 將二進位制 0100 向左移動一位變成 1000

a << 1  // 8

注:”按位異或“和”按位取反“的運算子是一樣的,區別在於運算元數量上,”按位異或“運算元為兩個,”按位取反“運算元是一個。

6. 邏輯運算子

邏輯運算子只能應用到 bool 型別上,初始化 a 和 b 兩個 bool 值,使用如下:


a := true

b := false

// 與運算,都為 true 時,結果為 true

a && b  // false

// 或運算,有一個為 true 時,結果為 true

a || b // true

// 非運算,為 true 時,結果為 false

// 反之,為 false 時,結果為true

!a  // false

!b  // true

7. 其他運算子

就剩下兩個運算子的使用了,往下看:


// 變數地址

a := 1

fmt.Println(&a) // 0xc00000a9b0

// 指標變數,在變數地址前加個 * 代表取出值

p := &a

fmt.Println(*p)  // 1

8. 運算子優先順序

認真一點學 Go:5. 常量及運算子

優先順序:表中”優先順序“列數字越大優先順序越高,規定了不同優先順序的結合順序,舉例如下:


// '*' 優先順序 > '+' 優先順序

// 等價於 a := (2 * 3) + 1

a := 2 * 3 + 1

結合性:表中“結合性”列中的“從左到右”和“從右到左”表示同優先順序運算子的結合順序,舉例如下


// 從表中看到結合性是從左到右

// 等價於 a := (1 + 2) + 3 

a := 1 + 2 +3

總結

本篇講解了“常量”和“運算子”的使用,如果掌握了其它程式語言,那重點看看常量怎麼使用就行,尤其是 iota 關鍵字的使用,至於“運算子”語言之間都差不多,就可以偷懶不看了,有啥不懂的就在下方留言。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章