# 注释 Go 语言的注释主要分成两类,分别是**单行**注释和**多行**注释。 ```go package main import "fmt" /* 多行注释。 */ func main() { // 单行注释。 fmt.Printf("单行注释。") /* 多行注释 */ fmt.Println("多行注释。") } ``` > 发现一个现象,写在函数上不会被格式化,在代码中会被退格格式化。 # 变量 ## 声明 ```go package main import "fmt" func main() { // 1️⃣ 变量声明(包含默认值) var name string = "田卓" var age int = 27 var isGood bool = true var myAge int // 默认值 0 fmt.Println("默认值示例:") fmt.Println("name:", name) fmt.Println("age:", age) fmt.Println("isGood:", isGood) fmt.Println("myAge (未赋值,默认值):", myAge) fmt.Println() // 2️⃣ 批量声明变量(默认值) var ( name1 string age1 int ) fmt.Println("批量声明:") fmt.Println("name1:", name1) // 默认 "" age1 = 20 fmt.Println("age1:", age1) // 赋值后 20 fmt.Println() // 3️⃣ 变量自动类型推导(语法糖 :=) name2 := "田秉衡" // Go 自动推导为 string age2 := 2 // 自动推导为 int height := 8 // 自动推导为 int weight := 28 // 自动推导为 int fmt.Println("类型推导:") fmt.Println("name2:", name2) fmt.Println("age2:", age2) fmt.Println("height:", height) fmt.Println("weight:", weight) fmt.Println() // 4️⃣ 变量交换 nameA := "田卓" nameB := "田秉衡" fmt.Println("交换前:", nameA, nameB) nameA, nameB = nameB, nameA fmt.Println("交换后:", nameA, nameB) fmt.Println() // 5️⃣ 多返回值赋值(使用 `_` 忽略不需要的值) result, _ := test() // 只取第一个返回值,忽略第二个 fmt.Println("多返回值赋值(忽略不需要的值):", result) } // 定义一个返回两个整数的函数 func test() (int, int) { return 200, 200 } ``` ## 作用域 ```go package main import "fmt" // 1️⃣ 全局变量(作用域:整个 package) var globalVar string = "全局变量" func main() { // 2️⃣ 局部变量(作用域:main 函数内) var localVar string = "局部变量" fmt.Println("🌍 全局变量:", globalVar) fmt.Println("🔹 局部变量:", localVar) // 3️⃣ 代码块作用域 { blockVar := "代码块变量" fmt.Println("📦 代码块变量:", blockVar) } // ❌ 代码块变量超出作用域,下面的代码会报错 // fmt.Println(blockVar) // ❌ 编译错误:未定义 blockVar // 4️⃣ 变量遮蔽(局部变量遮蔽全局变量) globalVar := "局部遮蔽全局" fmt.Println("🚧 遮蔽后的 globalVar:", globalVar) // 5️⃣ 变量交换 a, b := "变量A", "变量B" fmt.Println("🔄 交换前:", a, b) a, b = b, a fmt.Println("🔄 交换后:", a, b) // 6️⃣ 函数参数作用域 printVar("函数参数") // 7️⃣ 访问真正的全局变量(使用 package 级别变量) fmt.Println("🌍 真实的全局变量仍然是:", getGlobalVar()) } // 6️⃣ 函数参数作用域 func printVar(param string) { fmt.Println("🎯 函数参数作用域:", param) } // 7️⃣ 访问全局变量的辅助函数 func getGlobalVar() string { return globalVar } ``` # 常量 ```go package main import ( "fmt" "reflect" "unsafe" ) func main() { // 1️⃣ 基本常量声明 const URL1 string = "www.baidu.com" fmt.Println("🌍 基本常量:", URL1) // 2️⃣ 多常量声明 const URL2, URL3 string = "www.baidu1.com", "www.baidu2.com" fmt.Println("🌍 多常量:", URL2, URL3) // 3️⃣ 常量枚举(iota) const ( A = iota // 0 B // 1 C // 2 ) fmt.Println("🔢 常量 iota:", A, B, C) // 4️⃣ `iota` 用法(位移计算) const ( Flag1 = 1 << iota // 1 (2^0) Flag2 // 2 (2^1) Flag3 // 4 (2^2) ) fmt.Println("🛠️ iota 位移:", Flag1, Flag2, Flag3) // 5️⃣ 变量可修改,但常量不能修改 var myVar int = 100 fmt.Println("🔄 变量修改前:", myVar) // 6️⃣ 变量地址修改(⚠️ 变量可以被 unsafe 修改,但常量不能) myVarPtr := unsafe.Pointer(&myVar) rv := reflect.NewAt(reflect.TypeOf(myVar), myVarPtr).Elem() // 修改值 rv.SetInt(200) fmt.Println("🔄 变量修改后:", myVar) // 7️⃣ 常量的内存地址(不会被修改) // ❌ 下面代码如果取消注释会报错:常量不能被修改 // const myConst int = 300 // fmt.Printf("🚫 常量内存地址: %p (常量不会被修改)\n", &myConst) // rvConst := reflect.NewAt(reflect.TypeOf(myConst), unsafe.Pointer(&myConst)).Elem() // rvConst.SetInt(500) // fmt.Println("🚫 常量修改后:", myConst) } ``` ## iota 特殊常量 ```go package main import "fmt" func main() { // 1️⃣ `iota` 基本递增 const ( a = iota // 0 b // 1 (继承 `a = iota`,iota 递增) c // 2 d = 0 // ❌ 这里手动赋值 d = 0,iota 仍然递增(跳过) e // 0 (继承 d = 0,而不是 iota) f = iota // 5 (iota 继续递增,从 `c = 2` 到 `iota = 5`) g // 6 h = iota // 7 (手动写 `iota`,但值仍然递增) ) fmt.Println("🔢 基本 iota:", a, b, c, d, e, f, g, h) // 0 1 2 0 0 5 6 7 // 2️⃣ `iota` 遇到手动赋值的影响 const ( i = iota // 0 j = 0 // ❌ 手动赋值 j = 0,但 iota 仍然递增 k = iota // 2 (iota 继续递增,从 `i = 0` 变为 `k = 2`) ) fmt.Println("🎯 iota 断开影响:", i, j, k) // 0 0 2 } ``` # 数据类型 ## 布尔类型 (bool) ```go package main import "fmt" func main() { // ✅ 布尔值只能是 true 或 false var b1 bool = true var b2 bool = false // 🔹 %t 格式化布尔值 fmt.Printf("b1: %t, b2: %t\n", b1, b2) // ✅ Go 规定:false = 0, true = 1 var num1, num2 int = 1, 2 if num1 < num2 { fmt.Println("✅ 1 小于 2") } // ⚠️ 布尔类型默认值是 `false` var b3 bool fmt.Println("🔹 bool默认值:", b3) // 输出 false } ``` - 布尔类型 `bool` 只能是 `true` 或 `false` - 默认值是 `false` - `if` 语句可以直接使用布尔表达式 ## 整数类型 (int, uint) ```go package main import "fmt" func main() { // ✅ 无符号整数类型(uint) var u8 uint8 = 255 fmt.Printf("uint8: %v\n", u8) // ✅ 有符号整数类型(int) var i8 int8 = -128 fmt.Printf("int8: %v\n", i8) } ``` | 类型 | 描述 | 取值范围 | | -------- | ---------- | ---------------------------------------------- | | `uint8` | 无符号 8 位整型 | `0` - `255` | | `uint16` | 无符号 16 位整型 | `0` - `65535` | | `uint32` | 无符号 32 位整型 | `0` - `4294967295` | | `uint64` | 无符号 64 位整型 | `0` - `18446744073709551615` | | `int8` | 有符号 8 位整型 | `-128` - `127` | | `int16` | 有符号 16 位整型 | `-32768` - `32767` | | `int32` | 有符号 32 位整型 | `-2147483648` - `2147483647` | | `int64` | 有符号 64 位整型 | `-9223372036854775808` - `9223372036854775807` | - **`int` 类型** 在 `32-bit` 和 `64-bit` 平台上的大小可能不同 - **`uint` 是无符号整数,不能表示负数** - **默认 `int` 是 `int64`(64-bit 机器)** ## 浮点类型 (float32, float64) ```go package main import "fmt" func main() { // ✅ 浮点类型(默认 `float64`) var f1 float64 = 3.141592653 var f2 float32 = 2.71 fmt.Printf("float64: %T, %.3f\n", f1, f1) // 保留3位小数 fmt.Printf("float32: %T, %.2f\n", f2, f2) // 保留2位小数 // ⚠️ 计算机存储浮点数时存在精度丢失 var num1 float32 = -123.0000901 var num2 float64 = -123.0000901 fmt.Println("float32:", num1) fmt.Println("float64:", num2) } ``` - `float64` **精度比 `float32` 高** - **浮点数计算可能会有精度损失** - **格式化输出 `%.2f` 控制小数位数** ## 特殊整数类型 (byte, rune, uintptr) ```go package main import ( "fmt" "unsafe" ) func main() { // ✅ `byte` 是 `uint8` 的别名(常用于存储字符) var b byte = 255 fmt.Printf("byte: %T, %v\n", b, b) // ✅ `rune` 是 `int32` 的别名(用于存储 Unicode 字符) var r rune = '魑' fmt.Printf("rune: %T, %v, %c\n", r, r, r) // ✅ `uintptr` 存储指针地址 var x int = 42 ptr := unsafe.Pointer(&x) // 强制转换 uintPtr := uintptr(ptr) fmt.Printf("Pointer: %v, Uintptr: %v\n", ptr, uintPtr) } ``` - `byte` **等价于 `uint8`**,用于 **存储 ASCII 字符** - `rune` **等价于 `int32`**,用于 **存储 Unicode 字符** - `uintptr` **用于存储指针地址** ## 字符串类型 (string) ```go package main import "fmt" func main() { // ✅ 字符串类型 var str string = "Hello, World!" fmt.Printf("string: %T, %s\n", str, str) // ✅ 单引号是字符(rune),双引号是字符串(string) v1 := 'A' // `rune`(int32) v2 := "A" // `string` fmt.Printf("rune: %T, %d\n", v1, v1) // 'A' 的 Unicode 编码值 fmt.Printf("string: %T, %s\n", v2, v2) // ✅ Unicode 字符 v3 := '魑' fmt.Printf("rune: %T, %d, %c\n", v3, v3, v3) } ``` - **单引号 `'A'` 是 `rune`(int32)** - **双引号 `"A"` 是 `string`** - **字符本质上是 `int32`(Unicode 码点)** ## 类型转换 ```go package main import "fmt" func main() { // ✅ 浮点数转整数(丢失小数部分) a := 5.9 b := int(a) fmt.Printf("浮点转整型: %v\n", b) // 输出 5 // ✅ 整数转浮点数 var c int = 10 var d float64 = float64(c) fmt.Printf("整数转浮点: %v\n", d) // 输出 10.000000 // ✅ `byte` 和 `rune` 互转 var ch rune = 'A' fmt.Printf("字符 'A' 转 int: %v\n", int(ch)) // 65 // ✅ `string` 转 `byte` str := "Go" byteArr := []byte(str) fmt.Printf("字符串转 byte: %v\n", byteArr) // [71 111] } ``` - **转换 `float` 为 `int` 会丢失小数部分** - **整型可以转换为 `float64`** - **字符 (`rune`) 本质是 `int32`,可以直接转整数** - **`string` 可以转换为 `byte[]`** # 运算符全 ## 算术运算符 | 运算符 | 描述 | 示例(a = 7, b = 3) | 结果 | | ---- | ------------- | ---------------- | ------------------- | | `+` | 加法 | `a + b` | `7 + 3 = 10` | | `-` | 减法 | `a - b` | `7 - 3 = 4` | | `*` | 乘法 | `a * b` | `7 * 3 = 21` | | `/` | 除法 | `a / b` | `7 / 3 = 2`(整数除法取整) | | `%` | 取模(求余数) | `a % b` | `7 % 3 = 1` | | `++` | 自增(不支持 `++a`) | `a++` | `a = a + 1` | | `--` | 自减(不支持 `--a`) | `a--` | `a = a - 1` | ```go package main import "fmt" func main() { a, b := 7, 3 fmt.Println("加法:", a+b) fmt.Println("减法:", a-b) fmt.Println("乘法:", a*b) fmt.Println("除法:", a/b) // 结果是 2,整数除法取整 fmt.Println("取模:", a%b) // 余数 1 // 自增 & 自减 a++ fmt.Println("自增:", a) // 8 a-- fmt.Println("自减:", a) // 7 } ``` ## 关系运算符 | 运算符 | 描述 | 示例(a = 21, b = 10) | 结果 | | ---- | ---- | ------------------ | ------- | | `>` | 大于 | `a > b` | `true` | | `<` | 小于 | `a < b` | `false` | | `>=` | 大于等于 | `a >= b` | `true` | | `<=` | 小于等于 | `a <= b` | `false` | | `==` | 等于 | `a == b` | `false` | | `!=` | 不等于 | `a != b` | `true` | ```go package main import "fmt" func main() { a, b := 21, 10 fmt.Println(a > b) // true fmt.Println(a >= b) // true fmt.Println(a < b) // false fmt.Println(a <= b) // false fmt.Println(a == b) // false fmt.Println(a != b) // true } ``` ## 逻辑运算符 ```go package main import "fmt" func main() { a, b := true, false fmt.Println("与 &&:", a && b) // false fmt.Println("或 ||:", a || b) // true fmt.Println("非 !:", !a) // false } ``` ## 位运算符 | 运算符 | 描述 | 示例(a = 60, b = 13) | 结果(二进制) | 结果(十进制) | | ---- | ---- | ------------------ | ------------------------ | ---------------- | | `&` | 按位与 | `a & b` | `0011 1100 & 0000 1101` | `0000 1100 = 12` | | ` | ` | 按位或 | `a | b` | | `^` | 按位异或 | `a ^ b` | `0011 1100 ^ 0000 1101` | `0011 0001 = 49` | | `&^` | 按位清空 | `a &^ b` | `0011 1100 &^ 0000 1101` | `0011 0000 = 48` | | `<<` | 左移 | `a << 2` | `1111 0000` | `240` | | `>>` | 右移 | `a >> 2` | `0000 1111` | `15` | ```go package main import "fmt" func main() { a, b := 60, 13 fmt.Println("按位与 &:", a&b) // 12 fmt.Println("按位或 |:", a|b) // 61 fmt.Println("按位异或 ^:", a^b) // 49 fmt.Println("位清空 &^:", a&^b) // 48 fmt.Println("左移 <<:", a<<2) // 240 fmt.Println("右移 >>:", a>>2) // 15 } ``` ## 赋值运算符 | 运算符 | 描述 | 示例 | | ---- | ----- | ---------------------- | | `=` | 赋值 | `a = 10` | | `+=` | 加后赋值 | `a += 5` → `a = a + 5` | | `-=` | 减后赋值 | `a -= 5` → `a = a - 5` | | `*=` | 乘后赋值 | `a *= 5` → `a = a * 5` | | `/=` | 除后赋值 | `a /= 5` → `a = a / 5` | | `%=` | 取模后赋值 | `a %= 5` → `a = a % 5` | ```go package main import "fmt" func main() { a := 10 a += 5 fmt.Println("a += 5:", a) // 15 a *= 2 fmt.Println("a *= 2:", a) // 30 } ``` ## 指针运算符 | 运算符 | 描述 | 示例 | | --- | ------------- | ------------ | | `&` | 取地址 | `ptr = &a` | | `*` | 解引用(获取指针指向的值) | `val = *ptr` | ```go package main import "fmt" func main() { a := 10 ptr := &a // 获取变量 a 的地址 fmt.Println("a 的地址:", ptr) fmt.Println("指针解引用:", *ptr) // 10 } ``` ## 运算符优先级 从 **高** 到 **低**: 1. `*` `/` `%` `<<` `>>` `&` `&^` 2. `+` `-` `|` `^` 3. `==` `!=` `<` `<=` `>` `>=` 4. `&&` 5. `||` # 流程控制 ## 顺序结构 **默认执行顺序**:代码从上到下依次执行,不需要特殊控制。 ```go package main import "fmt" func main() { fmt.Println("步骤 1") fmt.Println("步骤 2") fmt.Println("步骤 3") } ``` **结果** ``` 步骤 1 步骤 2 步骤 3 ``` ## 选择结构(if 语句) ### (1)基本 if 语句 ```go package main import "fmt" func main() { num := 15 if num > 10 { fmt.Println("num > 10") } fmt.Println("main 结束") } ``` ### (2)if-else 语句 ```go package main import "fmt" func main() { score := 90 if score == 100 { fmt.Println("满分") } else { fmt.Println("不是满分") } } ``` ### (3)if-else if-else 多条件判断 ```go package main import "fmt" func main() { var score int fmt.Println("请输入成绩:") fmt.Scan(&score) if score >= 90 && score <= 100 { fmt.Println("A") } else if score >= 80 { fmt.Println("B") } else if score >= 70 { fmt.Println("C") } else if score >= 60 { fmt.Println("D") } else if score < 0 || score > 100 { fmt.Println("输入不合法") } else { fmt.Println("不及格") } } ``` ## 选择结构(switch 语句) ### (1)基本 switch ```go package main import "fmt" func main() { score := 100 switch score { case 100, 95, 91: fmt.Println("A") case 90: fmt.Println("B") case 80, 70, 60: fmt.Println("C") default: fmt.Println("其他") } } ``` - `case` **支持多个匹配值**(如 `100, 95, 91`) - `default` **可选** ### (2)switch 省略条件 ```go package main import "fmt" func main() { switch { case false: fmt.Println("false") case true: fmt.Println("true") default: fmt.Println("其他") } } ``` - `switch` **默认匹配 `true`**,可以用作 `if-else if-else` 结构的替代。 ### (3)fallthrough 关键字 `fallthrough` 用于强制执行下一个 `case` 语句,即使条件不匹配。 ```go package main import "fmt" func main() { a := false switch a { case false: fmt.Println("1") fallthrough case true: fmt.Println("2") // 强制执行 } } ``` - **`fallthrough` 忽略 `case` 的匹配条件** - **避免滥用**,否则可能产生意外行为 ### (4)终止 fallthrough ```go package main import "fmt" func main() { a := false switch a { case false: fmt.Println("1") fallthrough case true: fmt.Println("2") if !a { break // 终止 `fallthrough` } fallthrough default: fmt.Println("3") } } ``` ## 循环结构(for 语句) ### (1)基本 for 语句 ```go package main import "fmt" func main() { for i := 0; i < 5; i++ { fmt.Println(i) } } ``` ### (2)变形 for 语句 省略初始值 & 结束条件 ```go package main import "fmt" func main() { i := 0 for i <= 5 { fmt.Println(i) i++ } } ``` 无限循环 ```go package main import "fmt" func main() { for { fmt.Println("死循环") } } ``` ## 终止循环 ### (1)break 语句 用于**终止**整个循环。 ```go package main import "fmt" func main() { for i := 1; i <= 10; i++ { if i == 5 { break } fmt.Println(i) } } ``` 当 `i == 5` 时,`break` 终止循环,输出 `1 2 3 4` ### (2)continue 语句 用于**跳过当前循环**,继续执行下一个循环。 ```go package main import "fmt" func main() { for i := 1; i <= 10; i++ { if i == 5 { continue // 跳过 5 } fmt.Println(i) } } ``` 输出 `1 2 3 4 6 7 8 9 10`(`5` 被跳过) ## goto 语句 用于**无条件跳转**,但容易造成代码混乱,不建议使用。 `goto` 只能跳转到**同一函数**内的标签。 ```go package main import "fmt" func main() { fmt.Println("开始") goto END // 跳转到 END fmt.Println("不会执行") // 这行代码被跳过 END: fmt.Println("结束") } ``` **输出** ``` 开始 结束 ```