18 KiB
18 KiB
注释
Go 语言的注释主要分成两类,分别是单行注释和多行注释。
package main
import "fmt"
/*
多行注释。
*/
func main() {
// 单行注释。
fmt.Printf("单行注释。")
/*
多行注释
*/
fmt.Println("多行注释。")
}
发现一个现象,写在函数上不会被格式化,在代码中会被退格格式化。
变量
声明
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
}
作用域
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
}
常量
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 特殊常量
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)
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)
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)
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)
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)
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 码点)
类型转换
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 |
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 |
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
}
逻辑运算符
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 |
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 |
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 |
package main
import "fmt"
func main() {
a := 10
ptr := &a // 获取变量 a 的地址
fmt.Println("a 的地址:", ptr)
fmt.Println("指针解引用:", *ptr) // 10
}
运算符优先级
从 高 到 低:
*/%<<>>&&^+-|^==!=<<=>>=&&||
流程控制
顺序结构
默认执行顺序:代码从上到下依次执行,不需要特殊控制。
package main
import "fmt"
func main() {
fmt.Println("步骤 1")
fmt.Println("步骤 2")
fmt.Println("步骤 3")
}
结果
步骤 1
步骤 2
步骤 3
选择结构(if 语句)
(1)基本 if 语句
package main
import "fmt"
func main() {
num := 15
if num > 10 {
fmt.Println("num > 10")
}
fmt.Println("main 结束")
}
(2)if-else 语句
package main
import "fmt"
func main() {
score := 90
if score == 100 {
fmt.Println("满分")
} else {
fmt.Println("不是满分")
}
}
(3)if-else if-else 多条件判断
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
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 省略条件
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 语句,即使条件不匹配。
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
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 语句
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
fmt.Println(i)
}
}
(2)变形 for 语句
省略初始值 & 结束条件
package main
import "fmt"
func main() {
i := 0
for i <= 5 {
fmt.Println(i)
i++
}
}
无限循环
package main
import "fmt"
func main() {
for {
fmt.Println("死循环")
}
}
终止循环
(1)break 语句
用于终止整个循环。
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 语句
用于跳过当前循环,继续执行下一个循环。
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 只能跳转到同一函数内的标签。
package main
import "fmt"
func main() {
fmt.Println("开始")
goto END // 跳转到 END
fmt.Println("不会执行") // 这行代码被跳过
END:
fmt.Println("结束")
}
输出
开始
结束