目錄
一、常量
1.1 常量基本定義
1.2 常量組的定義
1.3 常量枚舉
二、運算符
2.1 算數運算符
2.2 關系運算符
2.3?邏輯運算符
2.4?位運算符
2.5?賦值運算符
2.6?指針運算符
2.7 運算符優先級
三、流程控制
3.1?if-else 條件語句
3.2 switch-case語句
3.3?for 循環
3.3 break &?continue
break
continue
break &?continue 的區別
3.4 goto跳轉
四、練習
4.1 九九乘法表
4.2 數字金字塔
4.3 斐波那契數列
????????在學習編程的過程中,掌握常量、運算符和流程控制是理解和使用任何編程語言的基礎。對于Go語言,這些概念同樣至關重要。通過本筆記,我們將詳細介紹Go語言中的常量、運算符以及流程控制的相關知識,幫助讀者在實際編程中靈活運用這些基本概念。
一、常量
1.1 常量基本定義
????????常量是在程序編譯時就確定下來的固定值。它們可以是數值、布爾值或字符串。Go語言的常量具有以下特點:
- 使用
const
關鍵字聲明 - 在編譯時被創建
- 只能是基本數據類型(數值、字符串或布爾值)
- 不可在運行時修改
注意:
- 一個常量被聲明后可以不使用,但是變量一旦聲明則必須使用。
- 顯式定義:常量的聲明以關鍵字const開頭,后接變量類型并進行賦值,行尾沒有其他標點符號。const 常量名 常量類型 = value
- 隱式定義:由于Go是編譯型語言,定義常量時可以省略常量類型,因為編譯器可以根據變量的值來推斷其類型。const 常量名 = value
package mainimport "fmt"// 單個常量聲明
const PI = 3.14159// 多個常量聲明
const (StatusOK = 200StatusNotFound = 404StatusServerError = 500
)func main() {fmt.Println("PI:", PI)// 常量的數學運算fmt.Println("圓的面積 (半徑為5):", PI*5*5)// 嘗試修改常量會導致編譯錯誤fmt.Println("HTTP狀態碼 - OK:", StatusOK)fmt.Println("HTTP狀態碼 - Not Found:", StatusNotFound)fmt.Println("HTTP狀態碼 - Server Error:", StatusServerError)
}
//result
PI: 3.14159
圓的面積 (半徑為5): 78.53975
HTTP狀態碼 - OK: 200
HTTP狀態碼 - Not Found: 404
HTTP狀態碼 - Server Error: 500
1.2 常量組的定義
????????如果程序需要用到大量值相同的常量,我們可以直接定義常量組。 在定義常量組時,若不提供初始值,則表示將使用上行的表達式。
package mainimport "fmt"const (a = 3.14bcd = 100
)func main() {fmt.Println("a:", a)fmt.Println("b:", b)fmt.Println("c:", c)fmt.Println("d:", d)
}
//result
a: 3.14
b: 3.14
c: 3.14
d: 100
1.3 常量枚舉
????????枚舉通常針對一個有窮序列集而言,一個集的枚舉就是列出有窮序列集的所有成員。Go語言現階段還沒有枚舉,但是我們可以使用一種特殊常量“iota”來模擬枚舉。
??iota
是Go語言的一個預定義標識符,它表示從0開始的連續整數。在每個const關鍵字出現時,iota都會重置為0。
package mainimport "fmt"func main() {const (a = iota // 0b // 1, 沿用上一行的 iotac = "Hello" // "Hello", iota = 2 但未使用d // "Hello", 沿用上一行的表達式e = iota // 4, iota 繼續計數f // 5g = iota * 2 // 12, iota = 6h // 14, 沿用 iota * 2 表達式i = 1 << iota // 512, iota = 9,這是位運算j // 1024, 沿用 1 << iota 表達式)fmt.Println("a:", a)fmt.Println("b:", b)fmt.Println("c:", c)fmt.Println("d:", d)fmt.Println("e:", e)fmt.Println("f:", f)fmt.Println("g:", g)fmt.Println("h:", h)fmt.Println("i:", i)fmt.Println("j:", j)// 在新的 const 塊中 iota 重新從 0 開始const (k = iota // 0l // 1_ // 2, 使用下劃線跳過這個值m // 3)fmt.Println("k:", k)fmt.Println("l:", l)fmt.Println("m:", m)// 在一行中使用多個 iotaconst (a1, a2 = iota + 1, iota + 2 // 1, 2b1, b2 // 2, 3c1, c2 // 3, 4)fmt.Printf("a1: %d, a2: %d\n", a1, a2)fmt.Printf("b1: %d, b2: %d\n", b1, b2)fmt.Printf("c1: %d, c2: %d\n", c1, c2)
}
//result
a: 0
b: 1
c: Hello
d: Hello
e: 4
f: 5
g: 12
h: 14
i: 256
j: 512
k: 0
l: 1
m: 3
a1: 1, a2: 2
b1: 2, b2: 3
c1: 3, c2: 4
二、運算符
????????Go數據是通過使用操作運算符來進行操作的,與數學運算符類似。操作運算符接受一個或多 個參數,并生成一個新的值
2.1 算數運算符
算術運算符用于Go語言的數學表達式中,它們的作用和在數學中的作用一樣。
運算符 | 說明 | 示例 |
+ | 加法:相加運算符兩側的值 | a + b |
- | 減法:左操作數減去右操作數 | a - b |
* | 乘法:操作符兩側的值相乘 | a * b |
/ | 除法:左操作數除以右操作數 | a / b |
% | 取模:左操作數除以右操作數的余數 | a % b |
++ | 自增:操作數加1 | a++ |
-- | 自減:操作數減1 | a-- |
package mainimport "fmt"func main() {// 算術運算符a, b := 10, 3fmt.Printf("a = %d, b = %d\n", a, b)fmt.Printf("a + b = %d\n", a+b)fmt.Printf("a - b = %d\n", a-b)fmt.Printf("a * b = %d\n", a*b)fmt.Printf("a / b = %d\n", a/b)fmt.Printf("a %% b = %d\n", a%b) //注意:要使用兩個百分號,轉意a++fmt.Printf("a = %d\n", a)b--fmt.Printf("b = %d\n", b)
}
a = 10, b = 3
a + b = 13
a - b = 7
a * b = 30
a / b = 3
a % b = 1
a = 11
b = 2
2.2 關系運算符
????????比較運算符,對符號兩邊的變量進行比較,包括大小、相等等。如果比較結果是正確,返回 真(true),否則返回假(false)
運算符 | 說明 | 示例 |
== | 等于:比較對象是否相等 | a == b |
!= | 不等于:比較兩個對象是否不相等 | a != b |
> | 大于:返回a是否大于b | a > b |
< | 小于:返回a是否小于b | a < b |
>= | 大于等于:返回x是否大于等于y | x >= y |
<= | 小于等于:返回x是否小于等于y | x <= y |
package mainimport "fmt"func main() {// 關系運算符a, b := 10, 3fmt.Printf("a == b: %t\n", a == b)fmt.Printf("a != b: %t\n", a != b)fmt.Printf("a > b: %t\n", a > b)fmt.Printf("a < b: %t\n", a < b)fmt.Printf("a >= b: %t\n", a >= b)fmt.Printf("a <= b: %t\n", a <= b)
}
//result
a == b: false
a != b: true
a > b: true
a < b: false
a >= b: true
a <= b: false
2.3?邏輯運算符
運算符 | 說明 | 示例 |
&& | 邏輯與,當且僅當兩個操作數都為真,條件才為真 | a && b |
|| | 邏輯或,兩個操作數中任意一個為真,條件為真 | a || b |
! | 邏輯非,用來反轉操作數的邏輯狀態。如果條件為true,則邏輯非運 算符將得到false | ! a |
package mainimport "fmt"func main() {// 邏輯運算符x, y := true, falsefmt.Printf("x && y: %t\n", x && y)fmt.Printf("x || y: %t\n", x || y)fmt.Printf("!x: %t\n", !x)
}
//result
x && y: false
x || y: true
!x: false
2.4?位運算符
運算符 | 名稱 | 描述 | 示例 |
& | 按位與 | 兩個位都為1時,結果為1 | 1100 & 1010 = 1000 |
| | 按位或 | 至少一個位為1時,結果為1 | 1100 | 1010 = 1110 |
^ | 按位異或 | 兩個位不同時,結果為1 | 1100 ^ 1010 = 0110 |
^ | 按位非(一元) | 翻轉所有位 | ^1100 = 0011 |
<< | 左移 | 將位向左移動指定數量 | 1100 << 2 = 110000 |
>> | 右移 | 將位向右移動指定數量 | 1100 >> 2 = 0011 |
&^ | 位清空(AND NOT) | 清除指定的位 | 1100 &^ 1010 = 0100 |
package mainimport ("fmt"
)func main() {a := 60 // 二進制: 0011 1100b := 13 // 二進制: 0000 1101fmt.Printf("a = %d, binary: %08b\n", a, a)fmt.Printf("b = %d, binary: %08b\n", b, b)// 1. 按位與 (&)result := a & bfmt.Printf("a & b = %d, binary: %08b\n", result, result)// 2. 按位或 (|)result = a | bfmt.Printf("a | b = %d, binary: %08b\n", result, result)// 3. 按位異或 (^)result = a ^ bfmt.Printf("a ^ b = %d, binary: %08b\n", result, result)// 4. 按位非 (^)result = ^afmt.Printf("^a = %d, binary: %08b\n", result, uint8(result))// 5. 左移 (<<)result = a << 2fmt.Printf("a << 2 = %d, binary: %08b\n", result, result)// 6. 右移 (>>)result = a >> 2fmt.Printf("a >> 2 = %d, binary: %08b\n", result, result)// 7. 位清空 (&^)result = a &^ bfmt.Printf("a &^ b = %d, binary: %08b\n", result, result)
}
//result
a = 60, binary: 00111100
b = 13, binary: 00001101
a & b = 12, binary: 00001100
a | b = 61, binary: 00111101
a ^ b = 49, binary: 00110001
^a = -61, binary: 11000011
a << 2 = 240, binary: 11110000
a >> 2 = 15, binary: 00001111
a &^ b = 48, binary: 00110000
2.5?賦值運算符
????????最常用的賦值運算符是等號“=”,表示把右邊的結果值賦值給左邊的變量。其他的賦值運算 符大多都是算術運算符和賦值運算符的簡寫。
運算符 | 說明 | 示例 | 展開形式 |
= | 將右邊值賦給左邊 | a=100 | a=100 |
+= | 將左邊值加上右邊值 | a+=10 | a=a+10 |
-= | 將左邊值減去右邊值 | a-=10 | a=a-10 |
*= | 將左邊值乘以右邊值 | a*=10 | a=a*10 |
/= | 將左邊值除以右邊值 | a/=10 | a=a/10 |
%= | 將左邊值對右邊值做取模 | a%=10 | a=a%10 |
**= | 將左邊值的右邊值次方賦給左邊 | a**=2 | a=a**2 |
//= | 將左邊值除以右邊值(取整除) | a//=3 | a=a//3 |
&= | 按位與運算后賦值 | a&=5 | a=a&5 |
|= | 按位或運算后賦值 | a|=5 | a=a|5 |
^= | 按位異或運算后賦值 | a^=5 | a=a^5 |
>>= | 右移運算后賦值 | a>>=2 | a=a>>2 |
<<= | 左移運算后賦值 | a<<=2 | a=a<<2 |
package mainimport "fmt"func main() {var a int = 100fmt.Println("Initial value of a:", a)a += 10fmt.Println("After a += 10:", a)a -= 5fmt.Println("After a -= 5:", a)a *= 2fmt.Println("After a *= 2:", a)a /= 4fmt.Println("After a /= 4:", a)a %= 7fmt.Println("After a %= 7:", a)// Go doesn't have **= operator, so we'll use regular multiplicationa *= afmt.Println("After a *= a (simulating a **= 2):", a)// Go uses / for both float and integer divisiona /= 3fmt.Println("After a /= 3:", a)a &= 5fmt.Println("After a &= 5:", a)a |= 8fmt.Println("After a |= 8:", a)a ^= 3fmt.Println("After a ^= 3:", a)a >>= 1fmt.Println("After a >>= 1:", a)a <<= 2fmt.Println("After a <<= 2:", a)
}
//result
Initial value of a: 100
After a += 10: 110
After a -= 5: 105
After a *= 2: 210
After a /= 4: 52
After a %= 7: 3
After a *= a (simulating a **= 2): 9
After a /= 3: 3
After a &= 5: 1
After a |= 8: 9
After a ^= 3: 10
After a >>= 1: 5
After a <<= 2: 20
2.6?指針運算符
運算符 | 描述 | 示例 |
& | 返回變量的內存地址 | &a // 將給出變量a的實際地址 |
* | 指向變量。用于聲明指針類型或訪問指針指向的值 | *p // 是一個指針變量 |
^ | 一元運算符時:對整數按位取反(NOT) 二元運算符時:按位異或(XOR) | ^a? ?// 對a的所有位取反 a ^ b??// a和b按位異或 |
package mainimport "fmt"func main() {a := 10var p *intp = &afmt.Println("a =", a)fmt.Printf("變量a的地址: %p\n", p)fmt.Println("指針p指向的值:", *p)
}
//result
a = 10
變量a的地址: 0xc00000a0b8
指針p指向的值: 10
2.7 運算符優先級
優先級 | 運算符 |
5 | * / % << >> & &^ |
4 | + - | ^ |
3 | == != < <= > >= |
2 | && |
1 | || |
- 最高優先級(5級):
*
、/
、%
:乘、除、取模<<
、>>
:左移、右移&
:按位與&^
:按位清零(AND NOT)
- 次高優先級(4級):
+
、-
:加、減|
:按位或^
:按位異或
- 比較運算符(3級):
==
、!=
:等于、不等于<
、<=
、>
、>=
:小于、小于等于、大于、大于等于
- 邏輯與(2級):
&&
- 邏輯或(1級):
||
三、流程控制
????????與其他編程語言一樣,使用Go語言的編程者需要通過流程控制語句來控制程序的邏輯走向和 執行次序。 Go語言基本上繼承了C/C++語言所有流程控制語句,如果有C/C++的編程經驗,那么理解本章內容將較為輕松。
????????流程控制語句主要包括:條件判斷語句(if、switch和select)、循環控制語句(for、break和continue) 和跳轉語句(goto)。selects是用于處理多個通道操作,以后結合通道在學
3.1?if-else 條件語句
用于根據條件執行不同的代碼塊。
if condition {// 條件為真時執行
} else if anotherCondition {// 另一個條件為真時執行
} else {// 所有條件都為假時執行
}
特點:
- 條件表達式不需要括號
- 支持在 if 語句中聲明局部變量
條件表達式使用例子
以下程序引入了runtime包,使用NumCPU()函數獲取了程序使用的CPU核數并傳遞給num變量。
package mainimport ("fmt""runtime"
)func main() {if num := runtime.NumCPU(); num >= 1 {fmt.Println("程序使用的CPU核數為:", num)}
}
//result
程序使用的CPU核數為: 16
3.2 switch-case語句
switch語句常用于基于大量不同條件來執行不同動作,每一個條件對應一個case分支。 ?
switch語句的執行過程從上至下,直到找到匹配項,匹配項后面也不需要再加break。
?每一個switch語句只能包含一個可選的default分支,若沒有找到匹配項,會默認執行default分支 中的代碼塊
switch variable {
case value1:// 代碼塊
case value2,value3:// 代碼塊
default:// 默認代碼塊
}
????????變量varible可以是任何類型,但value1和value2必須是相同的類型或最終結果為相同類型的表達式。每個case分支后可跟多個可能符合條件的值,使用逗號分隔它們,例如:case value2, value3
特點:
- 默認情況下,case 語句后不需要 break
- 支持多個條件在同一個 case 中
- 支持 fallthrough 關鍵字實現穿透到下一個 case
使用fallthrough的例子
package mainimport "fmt"func main() {switch {//false,肯定不會執行case false:fmt.Println("case1 為false")fallthrough//true,肯定執行case true:fmt.Println("case2 為 true")fallthrough//由于上一個case中有fallthrough,即使是false,也強制執行case false:fmt.Println("case3 為 false")fallthroughdefault:fmt.Println("默認 case")}
}
//result
case2 為 true
case3 為 false
默認 case
3.3?for 循環
Go 只有一種循環結構:for 循環。不同于其他編程語言,Go語言沒有while關鍵字,不存在while循環
// 標準 for 循環
for i := 0; i < 10; i++ {// 循環體
}// 類似 while 循環
for condition {// 循環體
}// 無限循環
for {// 循環體
}// 遍歷數組、切片或 map
for index, value := range collection {// 使用 index 和 value
}
3.3 break &?continue
??break
和 continue
是Go語言中用于控制循環執行的關鍵字。它們可以改變循環的正常執行流程,但有著不同的作用。
Go 沒有 do-while
循環,所以 break
和 continue
主要用在 for
循環中。
break
在 for 循環中:
for i := 0; i < 10; i++ {if i == 5 {break}fmt.Println(i)
}
// 輸出: 0 1 2 3 4
在 switch 語句中:
switch n {
case 1:fmt.Println("一")
case 2:fmt.Println("二")breakfmt.Println("這行不會執行")
default:fmt.Println("其他")
}
Go 支持帶標簽的 break,可以跳出多層嵌套循環:
package mainimport "fmt"func main() {
outerLoop:for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if i == 1 && j == 1 {break outerLoop}fmt.Printf("%d %d\n", i, j)}}
}
//result
0 0
0 1
0 2
1 0
continue
continue
語句用于跳過當前循環的剩余部分,直接進入下一次迭代。
基本用法
for i := 0; i < 5; i++ {if i == 2 {continue}fmt.Println(i)
}
// 輸出: 0 1 3 4
標簽用法,類似于break
package mainimport "fmt"func main() {
outerLoop:for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if i == 1 && j == 1 {continue outerLoop}fmt.Printf("%d %d\n", i, j)}}
}
// result
// 0 0
// 0 1
// 0 2
// 1 0
// 2 0
// 2 1
// 2 2
break &?continue 的區別
break
終止整個循環,而continue
只跳過當前迭代。break
可以用在 for 循環和 switch 語句中,而continue
只用在循環中。- 帶標簽的
break
可以跳出多層循環,而帶標簽的continue
會跳到外層循環的下一次迭代。
3.4 goto跳轉
goto語句用于代碼間的無條件跳轉,格式如下:
goto label
// ... 其他代碼 ...
label:// 跳轉到這里
一般情況下,在程序中不建議使用goto語句,過多的goto語句會破壞程序結構,使程序的可讀 性變差。
package mainimport "fmt"func main() {fmt.Println("Hello")goto signfmt.Println("無效代碼")
sign:fmt.Println("world")
}
//result
Hello
World
四、練習
4.1 九九乘法表
實現的效果
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
package mainimport "fmt"func main() {// 遍歷1到9的乘法表for i := 1; i <= 9; i++ {for j := 1; j <= i; j++ {fmt.Printf("%d * %d = %2d ", j, i, i*j)}fmt.Println()}
}
4.2 數字金字塔
實現的效果
****************************************************************
*****************
package mainimport "fmt"func Pyramid(n int) {// n 表示總層數for i := 1; i <= n; i++ {// 打印空格for j := 1; j <= n-i; j++ {fmt.Print(" ")}// 打印星號for k := 1; k <= 2*i-1; k++ {fmt.Print("*")}fmt.Println()}
}func main() {n := 9Pyramid(n)
}
4.3 斐波那契數列
斐波那契數列,又稱黃金分割數列,因數學家列昂納多·斐波那契(Leonardoda Fibonacci)
以兔子繁殖為例子而引入,故又稱為兔子數列,指的是這樣一個數列:1、1、2、3、5、8、13、 21、34……這個數列從第三項開始,每一項都等于前兩項之和。斐波那契數列在現代物理、準晶 體結構、化學等領域都有直接的應用。 那么,我們是否可以編寫一個斐波那契數列的程序,輸入第n項,程序輸出對應第n項的值? 答案是肯定的,最常見的實現方式就是循環和遞歸。
前20個例子:
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
使用for循環實現斐波那契數列的程序如下:
package mainimport "fmt"func Fibonacci(n int) (res int) {a := 1b := 1for i := 2; i < n; i++ {c := bb = a + ba = c}return b
}func main() {n := 9fmt.Printf("Fibonacci(%d) = %d\n", n, Fibonacci(n))
}
//result
Fibonacci(9) = 34
使用遞歸實現斐波那契數列的程序如下:
package mainimport "fmt"func Fibonacci(n int) (res int) {if n == 1 || n == 2 {return 1} else {return Fibonacci(n-2) + Fibonacci(n-1)}
}func main() {n := 10fmt.Printf("Fibonacci(%d) = %d\n", n, Fibonacci(n))
}
//result
Fibonacci(10) = 55
使用switch分支來進行代替:
package mainimport "fmt"func Fibonacci(n int) (res int) {switch n {case 1:return 1case 2:return 1default:return Fibonacci(n-1) + Fibonacci(n-2)}
}func main() {n := 6fmt.Printf("Fibonacci(%d) = %d\n", n, Fibonacci(n))
}
//result
Fibonacci(6) = 8