初始提交

This commit is contained in:
2025-08-24 01:01:26 +08:00
commit e51feb1296
35 changed files with 9348 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
/*
01-hello-world.go - Go 语言入门第一课
学习目标:
1. 了解 Go 程序的基本结构
2. 理解包package的概念
3. 学会使用 fmt 包进行输出
4. 掌握 main 函数的作用
知识点:
- package 声明
- import 导入
- main 函数
- fmt.Println 输出函数
*/
// 每个 Go 文件都必须以 package 声明开始
// main 包是特殊的包,表示这是一个可执行程序
package main
// import 用于导入其他包
// fmt 包提供了格式化输入输出的功能
import "fmt"
// main 函数是程序的入口点
// 当运行程序时,会自动执行 main 函数
func main() {
// fmt.Println 用于输出文本并自动换行
fmt.Println("Hello, World!")
fmt.Println("欢迎来到 Go 语言的世界!")
// 你也可以使用 fmt.Print不换行或 fmt.Printf格式化输出
fmt.Print("这是 ")
fmt.Print("同一行的输出\n") // \n 表示换行
// fmt.Printf 支持格式化输出,类似于 C 语言的 printf
name := "Go"
version := 1.21
fmt.Printf("我正在学习 %s 语言,版本是 %.2f\n", name, version)
// 多种输出方式的演示
demonstrateOutput()
}
// demonstrateOutput 演示不同的输出方式
func demonstrateOutput() {
fmt.Println("\n=== 输出方式演示 ===")
// 1. 基本输出
fmt.Println("1. fmt.Println - 输出并换行")
// 2. 不换行输出
fmt.Print("2. fmt.Print - ")
fmt.Print("不换行输出")
fmt.Print("\n") // 手动换行
// 3. 格式化输出
age := 25
height := 175.5
isStudent := true
fmt.Printf("3. fmt.Printf - 格式化输出:\n")
fmt.Printf(" 年龄: %d 岁\n", age) // %d 表示整数
fmt.Printf(" 身高: %.1f cm\n", height) // %.1f 表示保留1位小数的浮点数
fmt.Printf(" 是学生: %t\n", isStudent) // %t 表示布尔值
fmt.Printf(" 十六进制年龄: %x\n", age) // %x 表示十六进制
fmt.Printf(" 八进制年龄: %o\n", age) // %o 表示八进制
// 4. 通用格式符 %v
fmt.Printf("4. 通用格式符 %%v:\n")
fmt.Printf(" 年龄: %v, 身高: %v, 是学生: %v\n", age, height, isStudent)
// 5. 详细格式符 %+v 和 %#v主要用于结构体
person := struct {
Name string
Age int
}{"张三", 30}
fmt.Printf("5. 结构体输出:\n")
fmt.Printf(" %%v: %v\n", person) // 简单格式
fmt.Printf(" %%+v: %+v\n", person) // 包含字段名
fmt.Printf(" %%#v: %#v\n", person) // Go 语法格式
}
/*
运行这个程序:
1. 在终端中进入 01-basics 目录
2. 执行命令go run 01-hello-world.go
预期输出:
Hello, World!
欢迎来到 Go 语言的世界!
这是 同一行的输出
我正在学习 Go 语言,版本是 1.21
=== 输出方式演示 ===
1. fmt.Println - 输出并换行
2. fmt.Print - 不换行输出
3. fmt.Printf - 格式化输出:
年龄: 25 岁
身高: 175.5 cm
是学生: true
十六进制年龄: 19
八进制年龄: 31
4. 通用格式符 %v:
年龄: 25, 身高: 175.5, 是学生: true
5. 结构体输出:
%v: {张三 30}
%+v: {Name:张三 Age:30}
%#v: struct { Name string; Age int }{Name:"张三", Age:30}
学习要点:
1. Go 程序必须有 package 声明
2. main 包表示可执行程序
3. main 函数是程序入口
4. 使用 import 导入需要的包
5. fmt 包提供了丰富的输出功能
6. 注释使用 // 或
*/

View File

@@ -0,0 +1,258 @@
/*
02-variables.go - Go 语言变量详解
学习目标:
1. 掌握变量声明的多种方式
2. 理解 Go 的类型推断
3. 学会使用短变量声明
4. 了解变量的作用域
5. 掌握零值的概念
知识点:
- var 关键字声明
- 短变量声明 :=
- 类型推断
- 零值
- 变量作用域
- 多变量声明
*/
package main
import "fmt"
// 包级别变量声明(全局变量)
var globalVar = "我是全局变量"
var (
// 使用括号可以声明多个变量
packageVar1 = "包变量1"
packageVar2 = "包变量2"
packageVar3 int = 100
)
func main() {
fmt.Println("=== Go 语言变量详解 ===\n")
// 演示各种变量声明方式
demonstrateVariableDeclaration()
// 演示零值
demonstrateZeroValues()
// 演示类型推断
demonstrateTypeInference()
// 演示多变量声明
demonstrateMultipleDeclaration()
// 演示变量作用域
demonstrateScope()
// 演示变量赋值和修改
demonstrateAssignment()
}
// demonstrateVariableDeclaration 演示变量声明的不同方式
func demonstrateVariableDeclaration() {
fmt.Println("1. 变量声明方式:")
// 方式1: var 关键字 + 类型声明
var name string
name = "张三"
fmt.Printf(" 方式1 - var name string: %s\n", name)
// 方式2: var 关键字 + 类型声明 + 初始化
var age int = 25
fmt.Printf(" 方式2 - var age int = 25: %d\n", age)
// 方式3: var 关键字 + 类型推断
var city = "北京" // Go 会自动推断为 string 类型
fmt.Printf(" 方式3 - var city = \"北京\": %s\n", city)
// 方式4: 短变量声明(最常用)
height := 175.5 // 自动推断为 float64 类型
fmt.Printf(" 方式4 - height := 175.5: %.1f\n", height)
// 注意:短变量声明只能在函数内部使用
// 在包级别必须使用 var 关键字
fmt.Println()
}
// demonstrateZeroValues 演示 Go 的零值概念
func demonstrateZeroValues() {
fmt.Println("2. 零值演示:")
fmt.Println(" Go 中每种类型都有默认的零值")
// 声明变量但不初始化,会自动赋予零值
var intVar int
var floatVar float64
var boolVar bool
var stringVar string
var pointerVar *int
fmt.Printf(" int 零值: %d\n", intVar) // 0
fmt.Printf(" float64 零值: %f\n", floatVar) // 0.000000
fmt.Printf(" bool 零值: %t\n", boolVar) // false
fmt.Printf(" string 零值: '%s'\n", stringVar) // ""(空字符串)
fmt.Printf(" pointer 零值: %v\n", pointerVar) // <nil>
fmt.Println()
}
// demonstrateTypeInference 演示类型推断
func demonstrateTypeInference() {
fmt.Println("3. 类型推断演示:")
// Go 可以根据赋值自动推断类型
var a = 42 // 推断为 int
var b = 3.14 // 推断为 float64
var c = "Hello" // 推断为 string
var d = true // 推断为 bool
// 使用 %T 可以打印变量的类型
fmt.Printf(" a = %v, 类型: %T\n", a, a)
fmt.Printf(" b = %v, 类型: %T\n", b, b)
fmt.Printf(" c = %v, 类型: %T\n", c, c)
fmt.Printf(" d = %v, 类型: %T\n", d, d)
// 短变量声明也支持类型推断
x := 100 // int
y := 2.5 // float64
z := 'A' // rune (int32)
fmt.Printf(" x := 100, 类型: %T\n", x)
fmt.Printf(" y := 2.5, 类型: %T\n", y)
fmt.Printf(" z := 'A', 类型: %T, 值: %d\n", z, z)
fmt.Println()
}
// demonstrateMultipleDeclaration 演示多变量声明
func demonstrateMultipleDeclaration() {
fmt.Println("4. 多变量声明:")
// 方式1: 同时声明多个相同类型的变量
var x, y, z int = 1, 2, 3
fmt.Printf(" var x, y, z int = 1, 2, 3: %d, %d, %d\n", x, y, z)
// 方式2: 同时声明多个不同类型的变量
var name, age, height = "李四", 30, 180.0
fmt.Printf(" var name, age, height = ...: %s, %d, %.1f\n", name, age, height)
// 方式3: 使用短变量声明
a, b, c := "Go", 1.21, true
fmt.Printf(" a, b, c := ...: %s, %.2f, %t\n", a, b, c)
// 方式4: 使用括号组织多个变量声明
var (
firstName = "王"
lastName = "五"
fullName = firstName + lastName
)
fmt.Printf(" 组合声明: %s\n", fullName)
// 变量交换Go 的特色功能)
m, n := 10, 20
fmt.Printf(" 交换前: m=%d, n=%d\n", m, n)
m, n = n, m // 交换变量值
fmt.Printf(" 交换后: m=%d, n=%d\n", m, n)
fmt.Println()
}
// demonstrateScope 演示变量作用域
func demonstrateScope() {
fmt.Println("5. 变量作用域:")
// 访问全局变量
fmt.Printf(" 全局变量: %s\n", globalVar)
fmt.Printf(" 包变量: %s, %s, %d\n", packageVar1, packageVar2, packageVar3)
// 函数级别变量
funcVar := "函数变量"
fmt.Printf(" 函数变量: %s\n", funcVar)
// 块级别作用域
if true {
blockVar := "块变量"
fmt.Printf(" 块变量(在 if 块内): %s\n", blockVar)
// 可以访问外层变量
fmt.Printf(" 在块内访问函数变量: %s\n", funcVar)
}
// blockVar 在这里无法访问,会编译错误
// fmt.Println(blockVar) // 这行会报错
// for 循环的作用域
for i := 0; i < 3; i++ {
loopVar := fmt.Sprintf("循环变量_%d", i)
fmt.Printf(" %s\n", loopVar)
}
// i 和 loopVar 在这里都无法访问
fmt.Println()
}
// demonstrateAssignment 演示变量赋值和修改
func demonstrateAssignment() {
fmt.Println("6. 变量赋值和修改:")
// 基本赋值
var score int = 85
fmt.Printf(" 初始分数: %d\n", score)
// 修改变量值
score = 90
fmt.Printf(" 修改后分数: %d\n", score)
// 复合赋值运算符
score += 5 // 等同于 score = score + 5
fmt.Printf(" score += 5: %d\n", score)
score -= 3 // 等同于 score = score - 3
fmt.Printf(" score -= 3: %d\n", score)
score *= 2 // 等同于 score = score * 2
fmt.Printf(" score *= 2: %d\n", score)
score /= 4 // 等同于 score = score / 4
fmt.Printf(" score /= 4: %d\n", score)
score %= 10 // 等同于 score = score % 10
fmt.Printf(" score %%= 10: %d\n", score)
// 自增和自减运算符
fmt.Printf(" score++ 前: %d\n", score)
score++ // 等同于 score = score + 1
fmt.Printf(" score++ 后: %d\n", score)
score-- // 等同于 score = score - 1
fmt.Printf(" score-- 后: %d\n", score)
// 注意Go 中的 ++ 和 -- 是语句,不是表达式
// 不能写成 x = score++ 这样的形式
fmt.Println()
}
/*
运行这个程序:
go run 02-variables.go
学习要点:
1. Go 有多种变量声明方式,短变量声明 := 最常用
2. Go 支持类型推断,可以自动确定变量类型
3. 每种类型都有零值,未初始化的变量会自动赋予零值
4. 变量有作用域限制,块内变量无法在块外访问
5. Go 支持多变量同时声明和赋值
6. 复合赋值运算符可以简化代码
7. ++ 和 -- 在 Go 中是语句,不是表达式
常见错误:
1. 在包级别使用短变量声明 := (只能在函数内使用)
2. 访问超出作用域的变量
3. 将 ++ 或 -- 当作表达式使用
4. 忘记变量的零值概念
*/

View File

@@ -0,0 +1,302 @@
/*
03-constants.go - Go 语言常量详解
学习目标:
1. 理解常量的概念和作用
2. 掌握常量声明的方式
3. 学会使用 iota 枚举器
4. 了解类型化和无类型化常量
5. 掌握常量表达式的计算
知识点:
- const 关键字
- 常量组声明
- iota 枚举器
- 类型化常量 vs 无类型化常量
- 常量表达式
- 预定义常量
*/
package main
import "fmt"
// 包级别常量声明
const PI = 3.14159
const COMPANY_NAME = "Go 学习公司"
// 常量组声明
const (
// 基本常量
MAX_SIZE = 100
MIN_SIZE = 1
// 使用表达式的常量
BUFFER_SIZE = MAX_SIZE * 2
// 字符串常量
VERSION = "1.0.0"
AUTHOR = "Go 学习者"
)
// 使用 iota 的枚举常量
const (
// iota 从 0 开始,每行递增 1
MONDAY = iota // 0
TUESDAY // 1
WEDNESDAY // 2
THURSDAY // 3
FRIDAY // 4
SATURDAY // 5
SUNDAY // 6
)
// 更复杂的 iota 用法
const (
_ = iota // 0使用 _ 忽略第一个值
KB = 1 << (10 * iota) // 1 << (10 * 1) = 1024
MB // 1 << (10 * 2) = 1048576
GB // 1 << (10 * 3) = 1073741824
TB // 1 << (10 * 4) = 1099511627776
)
// 类型化常量
const (
MAX_INT int = 2147483647
MAX_FLOAT float64 = 1.7976931348623157e+308
IS_ENABLED bool = true
)
func main() {
fmt.Println("=== Go 语言常量详解 ===\n")
// 演示基本常量使用
demonstrateBasicConstants()
// 演示 iota 枚举器
demonstrateIota()
// 演示常量表达式
demonstrateConstantExpressions()
// 演示类型化和无类型化常量
demonstrateTypedConstants()
// 演示常量的特性
demonstrateConstantProperties()
}
// demonstrateBasicConstants 演示基本常量使用
func demonstrateBasicConstants() {
fmt.Println("1. 基本常量使用:")
// 使用包级别常量
fmt.Printf(" 圆周率: %f\n", PI)
fmt.Printf(" 公司名称: %s\n", COMPANY_NAME)
fmt.Printf(" 最大尺寸: %d\n", MAX_SIZE)
fmt.Printf(" 缓冲区大小: %d\n", BUFFER_SIZE)
// 函数内部常量声明
const LOCAL_CONST = "这是局部常量"
fmt.Printf(" 局部常量: %s\n", LOCAL_CONST)
// 常量组声明(函数内部)
const (
RED = "红色"
GREEN = "绿色"
BLUE = "蓝色"
)
fmt.Printf(" 颜色常量: %s, %s, %s\n", RED, GREEN, BLUE)
fmt.Println()
}
// demonstrateIota 演示 iota 枚举器
func demonstrateIota() {
fmt.Println("2. iota 枚举器:")
// 基本 iota 用法
fmt.Printf(" 星期枚举:\n")
fmt.Printf(" MONDAY: %d\n", MONDAY)
fmt.Printf(" TUESDAY: %d\n", TUESDAY)
fmt.Printf(" WEDNESDAY: %d\n", WEDNESDAY)
fmt.Printf(" THURSDAY: %d\n", THURSDAY)
fmt.Printf(" FRIDAY: %d\n", FRIDAY)
fmt.Printf(" SATURDAY: %d\n", SATURDAY)
fmt.Printf(" SUNDAY: %d\n", SUNDAY)
// 存储单位枚举
fmt.Printf(" 存储单位:\n")
fmt.Printf(" KB: %d 字节\n", KB)
fmt.Printf(" MB: %d 字节\n", MB)
fmt.Printf(" GB: %d 字节\n", GB)
fmt.Printf(" TB: %d 字节\n", TB)
// 更多 iota 示例
const (
A = iota * 2 // 0 * 2 = 0
B // 1 * 2 = 2
C // 2 * 2 = 4
D // 3 * 2 = 6
)
fmt.Printf(" iota 表达式: A=%d, B=%d, C=%d, D=%d\n", A, B, C, D)
// 跳过某些值
const (
E = iota + 1 // 0 + 1 = 1
F // 1 + 1 = 2
_ // 2 + 1 = 3 (跳过)
G // 3 + 1 = 4
)
fmt.Printf(" 跳过值: E=%d, F=%d, G=%d\n", E, F, G)
fmt.Println()
}
// demonstrateConstantExpressions 演示常量表达式
func demonstrateConstantExpressions() {
fmt.Println("3. 常量表达式:")
// 算术表达式
const (
A = 10
B = 20
SUM = A + B
PRODUCT = A * B
QUOTIENT = B / A
)
fmt.Printf(" 算术表达式:\n")
fmt.Printf(" A + B = %d\n", SUM)
fmt.Printf(" A * B = %d\n", PRODUCT)
fmt.Printf(" B / A = %d\n", QUOTIENT)
// 字符串表达式
const (
FIRST_NAME = "张"
LAST_NAME = "三"
FULL_NAME = FIRST_NAME + LAST_NAME
)
fmt.Printf(" 字符串表达式: %s\n", FULL_NAME)
// 布尔表达式
const (
X = 5
Y = 10
IS_GREATER = X > Y
IS_EQUAL = X == Y
)
fmt.Printf(" 布尔表达式:\n")
fmt.Printf(" %d > %d = %t\n", X, Y, IS_GREATER)
fmt.Printf(" %d == %d = %t\n", X, Y, IS_EQUAL)
fmt.Println()
}
// demonstrateTypedConstants 演示类型化和无类型化常量
func demonstrateTypedConstants() {
fmt.Println("4. 类型化和无类型化常量:")
// 无类型化常量(更灵活)
const UNTYPED_INT = 42
const UNTYPED_FLOAT = 3.14
const UNTYPED_STRING = "Hello"
// 类型化常量(类型固定)
const TYPED_INT int = 42
const TYPED_FLOAT float64 = 3.14
const TYPED_STRING string = "Hello"
fmt.Printf(" 无类型化常量:\n")
fmt.Printf(" UNTYPED_INT 可以赋值给不同的数值类型\n")
var i8 int8 = UNTYPED_INT // 可以
var i16 int16 = UNTYPED_INT // 可以
var i32 int32 = UNTYPED_INT // 可以
var i64 int64 = UNTYPED_INT // 可以
fmt.Printf(" int8: %d, int16: %d, int32: %d, int64: %d\n", i8, i16, i32, i64)
fmt.Printf(" 类型化常量:\n")
fmt.Printf(" TYPED_INT 只能赋值给相同类型\n")
var typedVar int = TYPED_INT // 可以,类型匹配
// var typedVar2 int32 = TYPED_INT // 编译错误,类型不匹配
fmt.Printf(" typedVar: %d\n", typedVar)
// 演示无类型化常量的精度
const HUGE = 1e1000 // 无类型化常量可以有很高的精度
fmt.Printf(" 高精度常量: 可以定义超出普通类型范围的常量\n")
fmt.Println()
}
// demonstrateConstantProperties 演示常量的特性
func demonstrateConstantProperties() {
fmt.Println("5. 常量的特性:")
// 常量在编译时确定
const COMPILE_TIME = 100 + 200
fmt.Printf(" 编译时计算: %d\n", COMPILE_TIME)
// 常量不能修改
const IMMUTABLE = "不可变"
fmt.Printf(" 不可变性: %s\n", IMMUTABLE)
// IMMUTABLE = "尝试修改" // 编译错误
// 常量可以用于数组长度
const ARRAY_SIZE = 5
var arr [ARRAY_SIZE]int
fmt.Printf(" 用作数组长度: 数组长度为 %d\n", len(arr))
// 预定义常量
fmt.Printf(" 预定义常量:\n")
fmt.Printf(" true: %t\n", true)
fmt.Printf(" false: %t\n", false)
// 常量的作用域
fmt.Printf(" 常量作用域:\n")
fmt.Printf(" 包级别常量在整个包中可见\n")
fmt.Printf(" 函数级别常量只在函数内可见\n")
// 在块作用域中定义常量
if true {
const BLOCK_CONST = "块常量"
fmt.Printf(" 块常量: %s\n", BLOCK_CONST)
}
// BLOCK_CONST 在这里不可访问
fmt.Println()
}
/*
运行这个程序:
go run 03-constants.go
学习要点:
1. 常量使用 const 关键字声明,一旦定义不能修改
2. 常量在编译时确定值,不能使用运行时才能确定的值
3. iota 是常量生成器,在 const 块中从 0 开始递增
4. 无类型化常量比类型化常量更灵活,可以赋值给兼容的类型
5. 常量可以用于需要编译时常量的地方,如数组长度
6. 常量表达式在编译时计算,支持算术、字符串、布尔运算
7. 常量有作用域限制,和变量类似
常见用途:
1. 定义配置参数(如缓冲区大小、超时时间)
2. 定义枚举值(如状态码、错误码)
3. 定义数学常数(如 PI、E
4. 定义字符串常量(如版本号、默认值)
注意事项:
1. 常量值必须在编译时确定
2. 不能将函数调用结果赋值给常量
3. 不能将变量赋值给常量
4. iota 只在 const 块中有效
*/

View File

@@ -0,0 +1,414 @@
/*
04-data-types.go - Go 语言数据类型详解
学习目标:
1. 掌握 Go 的基本数据类型
2. 理解不同数值类型的范围和用途
3. 学会字符串和字符的处理
4. 了解类型转换的方法
5. 掌握复合数据类型的基础
知识点:
- 整数类型 (int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64)
- 浮点类型 (float32, float64)
- 复数类型 (complex64, complex128)
- 布尔类型 (bool)
- 字符串类型 (string)
- 字符类型 (byte, rune)
- 类型转换
- 类型别名
*/
package main
import (
"fmt"
"math"
"unsafe"
)
func main() {
fmt.Println("=== Go 语言数据类型详解 ===\n")
// 演示整数类型
demonstrateIntegerTypes()
// 演示浮点类型
demonstrateFloatTypes()
// 演示复数类型
demonstrateComplexTypes()
// 演示布尔类型
demonstrateBooleanType()
// 演示字符串类型
demonstrateStringType()
// 演示字符类型
demonstrateCharacterTypes()
// 演示类型转换
demonstrateTypeConversion()
// 演示类型信息
demonstrateTypeInfo()
}
// demonstrateIntegerTypes 演示整数类型
func demonstrateIntegerTypes() {
fmt.Println("1. 整数类型:")
// 有符号整数
var i8 int8 = 127 // -128 到 127
var i16 int16 = 32767 // -32768 到 32767
var i32 int32 = 2147483647 // -2^31 到 2^31-1
var i64 int64 = 9223372036854775807 // -2^63 到 2^63-1
fmt.Printf(" 有符号整数:\n")
fmt.Printf(" int8: %d (大小: %d 字节)\n", i8, unsafe.Sizeof(i8))
fmt.Printf(" int16: %d (大小: %d 字节)\n", i16, unsafe.Sizeof(i16))
fmt.Printf(" int32: %d (大小: %d 字节)\n", i32, unsafe.Sizeof(i32))
fmt.Printf(" int64: %d (大小: %d 字节)\n", i64, unsafe.Sizeof(i64))
// 无符号整数
var ui8 uint8 = 255 // 0 到 255
var ui16 uint16 = 65535 // 0 到 65535
var ui32 uint32 = 4294967295 // 0 到 2^32-1
var ui64 uint64 = 18446744073709551615 // 0 到 2^64-1
fmt.Printf(" 无符号整数:\n")
fmt.Printf(" uint8: %d (大小: %d 字节)\n", ui8, unsafe.Sizeof(ui8))
fmt.Printf(" uint16: %d (大小: %d 字节)\n", ui16, unsafe.Sizeof(ui16))
fmt.Printf(" uint32: %d (大小: %d 字节)\n", ui32, unsafe.Sizeof(ui32))
fmt.Printf(" uint64: %d (大小: %d 字节)\n", ui64, unsafe.Sizeof(ui64))
// 平台相关的整数类型
var i int = 2147483647 // 32位系统上是int3264位系统上是int64
var ui uint = 4294967295 // 32位系统上是uint3264位系统上是uint64
var uiptr uintptr = 0x12345678 // 存储指针的整数类型
fmt.Printf(" 平台相关类型:\n")
fmt.Printf(" int: %d (大小: %d 字节)\n", i, unsafe.Sizeof(i))
fmt.Printf(" uint: %d (大小: %d 字节)\n", ui, unsafe.Sizeof(ui))
fmt.Printf(" uintptr: 0x%x (大小: %d 字节)\n", uiptr, unsafe.Sizeof(uiptr))
// 整数的不同表示法
fmt.Printf(" 整数的不同表示法:\n")
decimal := 42 // 十进制
binary := 0b101010 // 二进制 (Go 1.13+)
octal := 0o52 // 八进制 (Go 1.13+)
hexadecimal := 0x2A // 十六进制
fmt.Printf(" 十进制: %d\n", decimal)
fmt.Printf(" 二进制: %d (0b%b)\n", binary, binary)
fmt.Printf(" 八进制: %d (0o%o)\n", octal, octal)
fmt.Printf(" 十六进制: %d (0x%X)\n", hexadecimal, hexadecimal)
fmt.Println()
}
// demonstrateFloatTypes 演示浮点类型
func demonstrateFloatTypes() {
fmt.Println("2. 浮点类型:")
// float32 和 float64
var f32 float32 = 3.14159
var f64 float64 = 3.141592653589793
fmt.Printf(" 基本浮点类型:\n")
fmt.Printf(" float32: %.7f (大小: %d 字节)\n", f32, unsafe.Sizeof(f32))
fmt.Printf(" float64: %.15f (大小: %d 字节)\n", f64, unsafe.Sizeof(f64))
// 浮点数的特殊值
fmt.Printf(" 特殊浮点值:\n")
fmt.Printf(" 正无穷: %f\n", math.Inf(1))
fmt.Printf(" 负无穷: %f\n", math.Inf(-1))
fmt.Printf(" NaN: %f\n", math.NaN())
// 浮点数的科学计数法
scientific1 := 1.23e4 // 1.23 * 10^4 = 12300
scientific2 := 1.23e-4 // 1.23 * 10^-4 = 0.000123
fmt.Printf(" 科学计数法:\n")
fmt.Printf(" 1.23e4 = %f\n", scientific1)
fmt.Printf(" 1.23e-4 = %f\n", scientific2)
// 浮点数精度问题
fmt.Printf(" 精度问题演示:\n")
var a float64 = 0.1
var b float64 = 0.2
var c float64 = 0.3
fmt.Printf(" 0.1 + 0.2 = %.17f\n", a+b)
fmt.Printf(" 0.3 = %.17f\n", c)
fmt.Printf(" 0.1 + 0.2 == 0.3: %t\n", a+b == c)
fmt.Println()
}
// demonstrateComplexTypes 演示复数类型
func demonstrateComplexTypes() {
fmt.Println("3. 复数类型:")
// complex64 和 complex128
var c64 complex64 = 3 + 4i
var c128 complex128 = 5 + 6i
fmt.Printf(" 基本复数类型:\n")
fmt.Printf(" complex64: %v (大小: %d 字节)\n", c64, unsafe.Sizeof(c64))
fmt.Printf(" complex128: %v (大小: %d 字节)\n", c128, unsafe.Sizeof(c128))
// 复数的创建方式
c1 := 1 + 2i // 直接创建
c2 := complex(3, 4) // 使用 complex 函数
c3 := complex(float64(5), 6) // 指定类型
fmt.Printf(" 复数创建方式:\n")
fmt.Printf(" 直接创建: %v\n", c1)
fmt.Printf(" complex函数: %v\n", c2)
fmt.Printf(" 指定类型: %v\n", c3)
// 复数的实部和虚部
fmt.Printf(" 复数的实部和虚部:\n")
fmt.Printf(" %v 的实部: %.1f\n", c2, real(c2))
fmt.Printf(" %v 的虚部: %.1f\n", c2, imag(c2))
// 复数运算
sum := c1 + c2
product := c1 * c2
fmt.Printf(" 复数运算:\n")
fmt.Printf(" %v + %v = %v\n", c1, c2, sum)
fmt.Printf(" %v * %v = %v\n", c1, c2, product)
fmt.Println()
}
// demonstrateBooleanType 演示布尔类型
func demonstrateBooleanType() {
fmt.Println("4. 布尔类型:")
var b1 bool = true
var b2 bool = false
var b3 bool // 零值是 false
fmt.Printf(" 基本布尔值:\n")
fmt.Printf(" b1: %t (大小: %d 字节)\n", b1, unsafe.Sizeof(b1))
fmt.Printf(" b2: %t\n", b2)
fmt.Printf(" b3 (零值): %t\n", b3)
// 布尔运算
fmt.Printf(" 布尔运算:\n")
fmt.Printf(" true && false = %t\n", true && false)
fmt.Printf(" true || false = %t\n", true || false)
fmt.Printf(" !true = %t\n", !true)
fmt.Printf(" !false = %t\n", !false)
// 比较运算产生布尔值
x, y := 10, 20
fmt.Printf(" 比较运算:\n")
fmt.Printf(" %d == %d: %t\n", x, y, x == y)
fmt.Printf(" %d != %d: %t\n", x, y, x != y)
fmt.Printf(" %d < %d: %t\n", x, y, x < y)
fmt.Printf(" %d > %d: %t\n", x, y, x > y)
fmt.Printf(" %d <= %d: %t\n", x, y, x <= y)
fmt.Printf(" %d >= %d: %t\n", x, y, x >= y)
fmt.Println()
}
// demonstrateStringType 演示字符串类型
func demonstrateStringType() {
fmt.Println("5. 字符串类型:")
var s1 string = "Hello, World!"
var s2 string = "你好,世界!"
var s3 string // 零值是空字符串 ""
fmt.Printf(" 基本字符串:\n")
fmt.Printf(" s1: \"%s\" (长度: %d, 大小: %d 字节)\n", s1, len(s1), unsafe.Sizeof(s1))
fmt.Printf(" s2: \"%s\" (长度: %d)\n", s2, len(s2))
fmt.Printf(" s3 (零值): \"%s\"\n", s3)
// 字符串是不可变的
fmt.Printf(" 字符串特性:\n")
fmt.Printf(" 字符串是不可变的immutable\n")
fmt.Printf(" 字符串是 UTF-8 编码的\n")
// 字符串操作
fmt.Printf(" 字符串操作:\n")
concatenated := s1 + " " + s2
fmt.Printf(" 连接: \"%s\"\n", concatenated)
// 原始字符串字面量
rawString := `这是一个原始字符串
可以包含换行符
和 "双引号" 以及 \n 这样的字符`
fmt.Printf(" 原始字符串:\n")
fmt.Printf(" %s\n", rawString)
// 字符串转义序列
escaped := "制表符:\t换行符:\n引号:\"反斜杠:\\"
fmt.Printf(" 转义序列:\n")
fmt.Printf(" %s\n", escaped)
// 字符串索引和切片
fmt.Printf(" 字符串索引和切片:\n")
str := "Hello"
fmt.Printf(" str[0]: %c (字节值: %d)\n", str[0], str[0])
fmt.Printf(" str[1:4]: \"%s\"\n", str[1:4])
fmt.Printf(" str[:3]: \"%s\"\n", str[:3])
fmt.Printf(" str[2:]: \"%s\"\n", str[2:])
fmt.Println()
}
// demonstrateCharacterTypes 演示字符类型
func demonstrateCharacterTypes() {
fmt.Println("6. 字符类型:")
// byte 类型uint8 的别名)
var b byte = 'A'
fmt.Printf(" byte 类型:\n")
fmt.Printf(" 字符 'A': %c (ASCII值: %d, 大小: %d 字节)\n", b, b, unsafe.Sizeof(b))
// rune 类型int32 的别名,用于 Unicode 字符)
var r1 rune = 'A'
var r2 rune = '中'
var r3 rune = '🚀'
fmt.Printf(" rune 类型:\n")
fmt.Printf(" 字符 'A': %c (Unicode值: %d, 大小: %d 字节)\n", r1, r1, unsafe.Sizeof(r1))
fmt.Printf(" 字符 '中': %c (Unicode值: %d)\n", r2, r2)
fmt.Printf(" 字符 '🚀': %c (Unicode值: %d)\n", r3, r3)
// 字符串遍历
fmt.Printf(" 字符串遍历:\n")
str := "Hello世界"
fmt.Printf(" 按字节遍历:\n")
for i := 0; i < len(str); i++ {
fmt.Printf(" [%d]: %c (%d)\n", i, str[i], str[i])
}
fmt.Printf(" 按字符遍历 (range):\n")
for i, r := range str {
fmt.Printf(" [%d]: %c (%d)\n", i, r, r)
}
// Unicode 转义
fmt.Printf(" Unicode 转义:\n")
unicode1 := '\u4e2d' // 中
unicode2 := '\U0001F680' // 🚀
fmt.Printf(" \\u4e2d: %c\n", unicode1)
fmt.Printf(" \\U0001F680: %c\n", unicode2)
fmt.Println()
}
// demonstrateTypeConversion 演示类型转换
func demonstrateTypeConversion() {
fmt.Println("7. 类型转换:")
// 数值类型转换
var i int = 42
var f float64 = float64(i) // int 转 float64
var ui uint = uint(i) // int 转 uint
fmt.Printf(" 数值类型转换:\n")
fmt.Printf(" int %d -> float64 %.1f\n", i, f)
fmt.Printf(" int %d -> uint %d\n", i, ui)
// 注意Go 不支持隐式类型转换
var i32 int32 = 100
var i64 int64 = int64(i32) // 必须显式转换
fmt.Printf(" int32 %d -> int64 %d\n", i32, i64)
// 字符串和数值转换需要使用 strconv 包
// 这里只演示字符和数值的转换
var ch byte = 65
var chStr string = string(ch)
fmt.Printf(" 字符转换:\n")
fmt.Printf(" byte %d -> string \"%s\"\n", ch, chStr)
var r rune = 20013 // '中' 的 Unicode 值
var rStr string = string(r)
fmt.Printf(" rune %d -> string \"%s\"\n", r, rStr)
// 字符串转字节切片和字符切片
str := "Hello世界"
bytes := []byte(str)
runes := []rune(str)
fmt.Printf(" 字符串转换:\n")
fmt.Printf(" string -> []byte: %v\n", bytes)
fmt.Printf(" string -> []rune: %v\n", runes)
fmt.Printf(" []byte -> string: \"%s\"\n", string(bytes))
fmt.Printf(" []rune -> string: \"%s\"\n", string(runes))
fmt.Println()
}
// demonstrateTypeInfo 演示类型信息
func demonstrateTypeInfo() {
fmt.Println("8. 类型信息:")
// 使用 %T 打印类型信息
var i int = 42
var f float64 = 3.14
var s string = "Hello"
var b bool = true
var c complex128 = 1 + 2i
fmt.Printf(" 类型信息:\n")
fmt.Printf(" %v 的类型: %T\n", i, i)
fmt.Printf(" %v 的类型: %T\n", f, f)
fmt.Printf(" \"%v\" 的类型: %T\n", s, s)
fmt.Printf(" %v 的类型: %T\n", b, b)
fmt.Printf(" %v 的类型: %T\n", c, c)
// 类型别名
type MyInt int
type MyString string
var mi MyInt = 100
var ms MyString = "自定义类型"
fmt.Printf(" 自定义类型:\n")
fmt.Printf(" %v 的类型: %T\n", mi, mi)
fmt.Printf(" \"%v\" 的类型: %T\n", ms, ms)
// 类型别名和原类型的转换
var normalInt int = int(mi) // 需要显式转换
fmt.Printf(" MyInt -> int: %d\n", normalInt)
fmt.Println()
}
/*
运行这个程序:
go run 04-data-types.go
学习要点:
1. Go 有丰富的基本数据类型,包括整数、浮点、复数、布尔、字符串
2. 整数类型有有符号和无符号之分,大小从 8 位到 64 位
3. int 和 uint 的大小取决于平台32位或64位
4. 浮点数有精度限制,比较时要注意精度问题
5. 字符串是 UTF-8 编码的,不可变的
6. byte 用于 ASCII 字符rune 用于 Unicode 字符
7. Go 不支持隐式类型转换,必须显式转换
8. 可以定义类型别名,但需要显式转换
选择类型的建议:
1. 整数:一般使用 int需要特定大小时使用 int8/16/32/64
2. 浮点:一般使用 float64性能要求高时使用 float32
3. 字符ASCII 字符用 byteUnicode 字符用 rune
4. 字符串:使用 string需要修改时转换为 []byte 或 []rune
注意事项:
1. 不同类型之间不能直接运算,必须转换为相同类型
2. 浮点数比较要考虑精度问题
3. 字符串索引访问的是字节,不是字符
4. 使用 range 遍历字符串可以正确处理 Unicode 字符
*/

View File

@@ -0,0 +1,475 @@
/*
05-operators.go - Go 语言运算符详解
学习目标:
1. 掌握算术运算符的使用
2. 理解比较运算符的规则
3. 学会逻辑运算符的应用
4. 了解位运算符的用法
5. 掌握赋值运算符的使用
6. 理解运算符的优先级
知识点:
- 算术运算符 (+, -, *, /, %, ++, --)
- 比较运算符 (==, !=, <, <=, >, >=)
- 逻辑运算符 (&&, ||, !)
- 位运算符 (&, |, ^, <<, >>)
- 赋值运算符 (=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=)
- 其他运算符 (&, *, <-)
- 运算符优先级
*/
package main
import "fmt"
func main() {
fmt.Println("=== Go 语言运算符详解 ===\n")
// 演示算术运算符
demonstrateArithmeticOperators()
// 演示比较运算符
demonstrateComparisonOperators()
// 演示逻辑运算符
demonstrateLogicalOperators()
// 演示位运算符
demonstrateBitwiseOperators()
// 演示赋值运算符
demonstrateAssignmentOperators()
// 演示其他运算符
demonstrateOtherOperators()
// 演示运算符优先级
demonstrateOperatorPrecedence()
// 演示实际应用示例
demonstratePracticalExamples()
}
// demonstrateArithmeticOperators 演示算术运算符
func demonstrateArithmeticOperators() {
fmt.Println("1. 算术运算符:")
a, b := 15, 4
fmt.Printf(" 基本算术运算 (a=%d, b=%d):\n", a, b)
fmt.Printf(" a + b = %d + %d = %d\n", a, b, a+b)
fmt.Printf(" a - b = %d - %d = %d\n", a, b, a-b)
fmt.Printf(" a * b = %d * %d = %d\n", a, b, a*b)
fmt.Printf(" a / b = %d / %d = %d\n", a, b, a/b) // 整数除法
fmt.Printf(" a %% b = %d %% %d = %d\n", a, b, a%b) // 取余
// 浮点数除法
fa, fb := 15.0, 4.0
fmt.Printf(" 浮点数除法:\n")
fmt.Printf(" %.1f / %.1f = %.2f\n", fa, fb, fa/fb)
// 自增和自减运算符
fmt.Printf(" 自增和自减运算符:\n")
x := 10
fmt.Printf(" x = %d\n", x)
x++ // x = x + 1
fmt.Printf(" x++ 后: %d\n", x)
x-- // x = x - 1
fmt.Printf(" x-- 后: %d\n", x)
// 注意Go 中的 ++ 和 -- 是语句,不是表达式
fmt.Printf(" 注意: Go 中 ++ 和 -- 是语句,不能用在表达式中\n")
// y := x++ // 编译错误
// z := ++x // 编译错误Go 没有前置 ++
// 一元运算符
fmt.Printf(" 一元运算符:\n")
positive := +10
negative := -10
fmt.Printf(" +10 = %d\n", positive)
fmt.Printf(" -10 = %d\n", negative)
fmt.Println()
}
// demonstrateComparisonOperators 演示比较运算符
func demonstrateComparisonOperators() {
fmt.Println("2. 比较运算符:")
a, b := 10, 20
fmt.Printf(" 数值比较 (a=%d, b=%d):\n", a, b)
fmt.Printf(" a == b: %d == %d = %t\n", a, b, a == b)
fmt.Printf(" a != b: %d != %d = %t\n", a, b, a != b)
fmt.Printf(" a < b: %d < %d = %t\n", a, b, a < b)
fmt.Printf(" a <= b: %d <= %d = %t\n", a, b, a <= b)
fmt.Printf(" a > b: %d > %d = %t\n", a, b, a > b)
fmt.Printf(" a >= b: %d >= %d = %t\n", a, b, a >= b)
// 字符串比较
s1, s2 := "apple", "banana"
fmt.Printf(" 字符串比较 (s1=\"%s\", s2=\"%s\"):\n", s1, s2)
fmt.Printf(" s1 == s2: %t\n", s1 == s2)
fmt.Printf(" s1 < s2: %t (按字典序)\n", s1 < s2)
fmt.Printf(" s1 > s2: %t\n", s1 > s2)
// 布尔值比较
bool1, bool2 := true, false
fmt.Printf(" 布尔值比较:\n")
fmt.Printf(" true == false: %t\n", bool1 == bool2)
fmt.Printf(" true != false: %t\n", bool1 != bool2)
// 注意:不同类型不能直接比较
fmt.Printf(" 注意: 不同类型不能直接比较,需要类型转换\n")
var i int = 10
var f float64 = 10.0
// fmt.Println(i == f) // 编译错误
fmt.Printf(" int(10) == float64(10.0): %t\n", float64(i) == f)
fmt.Println()
}
// demonstrateLogicalOperators 演示逻辑运算符
func demonstrateLogicalOperators() {
fmt.Println("3. 逻辑运算符:")
a, b := true, false
fmt.Printf(" 基本逻辑运算 (a=%t, b=%t):\n", a, b)
fmt.Printf(" a && b: %t && %t = %t (逻辑与)\n", a, b, a && b)
fmt.Printf(" a || b: %t || %t = %t (逻辑或)\n", a, b, a || b)
fmt.Printf(" !a: !%t = %t (逻辑非)\n", a, !a)
fmt.Printf(" !b: !%t = %t\n", b, !b)
// 真值表
fmt.Printf(" 逻辑运算真值表:\n")
fmt.Printf(" A | B | A&&B | A||B | !A\n")
fmt.Printf(" ------|-------|-------|-------|------\n")
fmt.Printf(" true | true | %t | %t | %t\n", true && true, true || true, !true)
fmt.Printf(" true | false | %t| %t | %t\n", true && false, true || false, !true)
fmt.Printf(" false | true | %t| %t | %t\n", false && true, false || true, !false)
fmt.Printf(" false | false | %t| %t | %t\n", false && false, false || false, !false)
// 短路求值
fmt.Printf(" 短路求值演示:\n")
x, y := 5, 0
// && 短路:如果左边是 false右边不会执行
fmt.Printf(" 短路与: (x > 10) && (y != 0)\n")
result1 := (x > 10) && (y != 0)
fmt.Printf(" 结果: %t (右边条件不会被检查)\n", result1)
// || 短路:如果左边是 true右边不会执行
fmt.Printf(" 短路或: (x > 0) || (y != 0)\n")
result2 := (x > 0) || (y != 0)
fmt.Printf(" 结果: %t (右边条件不会被检查)\n", result2)
// 复合逻辑表达式
age := 25
hasLicense := true
hasInsurance := false
canDrive := age >= 18 && hasLicense && hasInsurance
fmt.Printf(" 复合条件判断:\n")
fmt.Printf(" 年龄: %d, 有驾照: %t, 有保险: %t\n", age, hasLicense, hasInsurance)
fmt.Printf(" 可以开车: %t\n", canDrive)
fmt.Println()
}
// demonstrateBitwiseOperators 演示位运算符
func demonstrateBitwiseOperators() {
fmt.Println("4. 位运算符:")
a, b := 12, 10 // 12 = 1100, 10 = 1010 (二进制)
fmt.Printf(" 位运算 (a=%d, b=%d):\n", a, b)
fmt.Printf(" a 的二进制: %08b\n", a)
fmt.Printf(" b 的二进制: %08b\n", b)
fmt.Printf(" a & b: %08b = %d (按位与)\n", a & b, a & b)
fmt.Printf(" a | b: %08b = %d (按位或)\n", a | b, a | b)
fmt.Printf(" a ^ b: %08b = %d (按位异或)\n", a ^ b, a ^ b)
fmt.Printf(" ^a: %08b = %d (按位取反)\n", ^a, ^a)
// 位移运算
fmt.Printf(" 位移运算:\n")
x := 8 // 1000 (二进制)
fmt.Printf(" x = %d (%08b)\n", x, x)
fmt.Printf(" x << 1: %08b = %d (左移1位)\n", x << 1, x << 1)
fmt.Printf(" x << 2: %08b = %d (左移2位)\n", x << 2, x << 2)
fmt.Printf(" x >> 1: %08b = %d (右移1位)\n", x >> 1, x >> 1)
fmt.Printf(" x >> 2: %08b = %d (右移2位)\n", x >> 2, x >> 2)
// 位运算的实际应用
fmt.Printf(" 位运算应用示例:\n")
// 检查奇偶性
num := 15
isEven := (num & 1) == 0
fmt.Printf(" %d 是偶数: %t (使用 n&1==0 检查)\n", num, isEven)
// 快速乘除法2的幂
fmt.Printf(" 快速乘除法:\n")
fmt.Printf(" %d * 4 = %d << 2 = %d\n", num, num, num << 2)
fmt.Printf(" %d / 4 = %d >> 2 = %d\n", num, num, num >> 2)
// 设置、清除、切换位
flags := 0
fmt.Printf(" 位标志操作:\n")
fmt.Printf(" 初始标志: %08b\n", flags)
flags |= (1 << 2) // 设置第2位
fmt.Printf(" 设置第2位: %08b\n", flags)
flags &^= (1 << 2) // 清除第2位
fmt.Printf(" 清除第2位: %08b\n", flags)
flags ^= (1 << 1) // 切换第1位
fmt.Printf(" 切换第1位: %08b\n", flags)
fmt.Println()
}
// demonstrateAssignmentOperators 演示赋值运算符
func demonstrateAssignmentOperators() {
fmt.Println("5. 赋值运算符:")
// 基本赋值
var x int = 10
fmt.Printf(" 基本赋值: x = %d\n", x)
// 复合赋值运算符
fmt.Printf(" 复合赋值运算符:\n")
x += 5 // x = x + 5
fmt.Printf(" x += 5: x = %d\n", x)
x -= 3 // x = x - 3
fmt.Printf(" x -= 3: x = %d\n", x)
x *= 2 // x = x * 2
fmt.Printf(" x *= 2: x = %d\n", x)
x /= 4 // x = x / 4
fmt.Printf(" x /= 4: x = %d\n", x)
x %= 3 // x = x % 3
fmt.Printf(" x %%= 3: x = %d\n", x)
// 位运算赋值
fmt.Printf(" 位运算赋值:\n")
y := 12 // 1100
fmt.Printf(" y = %d (%04b)\n", y, y)
y &= 10 // y = y & 10 (1010)
fmt.Printf(" y &= 10: y = %d (%04b)\n", y, y)
y |= 5 // y = y | 5 (0101)
fmt.Printf(" y |= 5: y = %d (%04b)\n", y, y)
y ^= 3 // y = y ^ 3 (0011)
fmt.Printf(" y ^= 3: y = %d (%04b)\n", y, y)
y <<= 1 // y = y << 1
fmt.Printf(" y <<= 1: y = %d (%04b)\n", y, y)
y >>= 2 // y = y >> 2
fmt.Printf(" y >>= 2: y = %d (%04b)\n", y, y)
// 多重赋值
fmt.Printf(" 多重赋值:\n")
a, b, c := 1, 2, 3
fmt.Printf(" a, b, c := 1, 2, 3: a=%d, b=%d, c=%d\n", a, b, c)
// 交换变量
a, b = b, a
fmt.Printf(" a, b = b, a: a=%d, b=%d (交换)\n", a, b)
fmt.Println()
}
// demonstrateOtherOperators 演示其他运算符
func demonstrateOtherOperators() {
fmt.Println("6. 其他运算符:")
// 地址运算符 &
x := 42
ptr := &x
fmt.Printf(" 地址运算符 &:\n")
fmt.Printf(" x = %d\n", x)
fmt.Printf(" &x = %p (x的地址)\n", ptr)
// 解引用运算符 *
fmt.Printf(" 解引用运算符 *:\n")
fmt.Printf(" *ptr = %d (ptr指向的值)\n", *ptr)
// 修改指针指向的值
*ptr = 100
fmt.Printf(" 修改 *ptr = 100 后, x = %d\n", x)
// 通道运算符 <- (这里只是语法演示,详细内容在并发章节)
fmt.Printf(" 通道运算符 <- (语法演示):\n")
ch := make(chan int, 1)
ch <- 42 // 发送值到通道
value := <-ch // 从通道接收值
fmt.Printf(" 通道发送和接收: %d\n", value)
fmt.Println()
}
// demonstrateOperatorPrecedence 演示运算符优先级
func demonstrateOperatorPrecedence() {
fmt.Println("7. 运算符优先级:")
// 算术运算符优先级
result1 := 2 + 3 * 4
result2 := (2 + 3) * 4
fmt.Printf(" 算术运算优先级:\n")
fmt.Printf(" 2 + 3 * 4 = %d (乘法优先)\n", result1)
fmt.Printf(" (2 + 3) * 4 = %d (括号改变优先级)\n", result2)
// 比较和逻辑运算符优先级
a, b, c := 5, 10, 15
result3 := a < b && b < c
result4 := a < b || b > c && c > a
fmt.Printf(" 比较和逻辑运算优先级:\n")
fmt.Printf(" %d < %d && %d < %d = %t\n", a, b, b, c, result3)
fmt.Printf(" %d < %d || %d > %d && %d > %d = %t\n", a, b, b, c, c, a, result4)
// 位运算符优先级
x := 6 // 110
y := 3 // 011
result5 := x & y | x ^ y
result6 := x & (y | x) ^ y
fmt.Printf(" 位运算优先级:\n")
fmt.Printf(" %d & %d | %d ^ %d = %d\n", x, y, x, y, result5)
fmt.Printf(" %d & (%d | %d) ^ %d = %d\n", x, y, x, y, result6)
// 运算符优先级表(从高到低)
fmt.Printf(" 运算符优先级表(从高到低):\n")
fmt.Printf(" 1. * / %% << >> & &^\n")
fmt.Printf(" 2. + - | ^\n")
fmt.Printf(" 3. == != < <= > >=\n")
fmt.Printf(" 4. &&\n")
fmt.Printf(" 5. ||\n")
fmt.Println()
}
// demonstratePracticalExamples 演示实际应用示例
func demonstratePracticalExamples() {
fmt.Println("8. 实际应用示例:")
// 示例1: 计算器功能
fmt.Printf(" 示例1 - 简单计算器:\n")
num1, num2 := 15.5, 4.2
operator := "+"
var result float64
switch operator {
case "+":
result = num1 + num2
case "-":
result = num1 - num2
case "*":
result = num1 * num2
case "/":
if num2 != 0 {
result = num1 / num2
} else {
fmt.Printf(" 错误: 除数不能为零\n")
return
}
}
fmt.Printf(" %.1f %s %.1f = %.2f\n", num1, operator, num2, result)
// 示例2: 判断闰年
fmt.Printf(" 示例2 - 判断闰年:\n")
year := 2024
isLeapYear := (year%4 == 0 && year%100 != 0) || (year%400 == 0)
fmt.Printf(" %d年是闰年: %t\n", year, isLeapYear)
// 示例3: 位掩码操作
fmt.Printf(" 示例3 - 权限系统 (位掩码):\n")
const (
READ = 1 << 0 // 001
WRITE = 1 << 1 // 010
EXECUTE = 1 << 2 // 100
)
// 设置权限
permissions := READ | WRITE // 011
fmt.Printf(" 初始权限: %03b (读:%t, 写:%t, 执行:%t)\n",
permissions,
permissions&READ != 0,
permissions&WRITE != 0,
permissions&EXECUTE != 0)
// 添加执行权限
permissions |= EXECUTE // 111
fmt.Printf(" 添加执行权限: %03b (读:%t, 写:%t, 执行:%t)\n",
permissions,
permissions&READ != 0,
permissions&WRITE != 0,
permissions&EXECUTE != 0)
// 移除写权限
permissions &^= WRITE // 101
fmt.Printf(" 移除写权限: %03b (读:%t, 写:%t, 执行:%t)\n",
permissions,
permissions&READ != 0,
permissions&WRITE != 0,
permissions&EXECUTE != 0)
// 示例4: 条件表达式模拟
fmt.Printf(" 示例4 - 条件表达式模拟:\n")
score := 85
var grade string
// Go 没有三元运算符,使用 if-else
if score >= 90 {
grade = "A"
} else if score >= 80 {
grade = "B"
} else if score >= 70 {
grade = "C"
} else if score >= 60 {
grade = "D"
} else {
grade = "F"
}
fmt.Printf(" 分数 %d 对应等级: %s\n", score, grade)
fmt.Println()
}
/*
运行这个程序:
go run 05-operators.go
学习要点:
1. Go 支持丰富的运算符,包括算术、比较、逻辑、位运算等
2. ++ 和 -- 在 Go 中是语句,不是表达式,不能用在赋值中
3. Go 不支持隐式类型转换,不同类型不能直接比较或运算
4. 逻辑运算符支持短路求值,可以提高效率和安全性
5. 位运算符在系统编程和性能优化中很有用
6. 复合赋值运算符可以简化代码
7. 运算符有优先级,使用括号可以改变优先级
8. Go 没有三元运算符,使用 if-else 代替
实际应用:
1. 算术运算符用于数学计算
2. 比较运算符用于条件判断
3. 逻辑运算符用于复合条件
4. 位运算符用于标志位操作、权限系统等
5. 赋值运算符用于变量更新
注意事项:
1. 除法运算要注意整数除法和浮点除法的区别
2. 取余运算的结果符号与被除数相同
3. 位运算时要注意数据类型的位数
4. 使用逻辑运算符时要注意短路求值的特性
5. 复杂表达式建议使用括号明确优先级
*/

View File

@@ -0,0 +1,23 @@
# 第一章:基础语法
本章将介绍 Go 语言的基础语法,包括程序结构、变量、常量、数据类型和运算符。
## 学习目标
- 理解 Go 程序的基本结构
- 掌握变量声明和初始化的方法
- 了解 Go 的基本数据类型
- 学会使用各种运算符
## 文件列表
- `01-hello-world.go` - Hello World 程序和基本结构
- `02-variables.go` - 变量声明和初始化
- `03-constants.go` - 常量定义和使用
- `04-data-types.go` - 基本数据类型
- `05-operators.go` - 运算符使用
## 运行示例
```bash
go run 01-hello-world.go
go run 02-variables.go
# ... 依此类推
```

View File

@@ -0,0 +1,485 @@
/*
01-if-else.go - Go 语言条件语句详解
学习目标:
1. 掌握 if 语句的基本用法
2. 理解 if-else 和 if-else if 结构
3. 学会在 if 语句中声明变量
4. 了解条件表达式的写法
5. 掌握嵌套条件语句
知识点:
- if 语句基本语法
- if-else 语句
- if-else if-else 链
- if 语句中的变量声明
- 条件表达式
- 嵌套 if 语句
- 实际应用场景
*/
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
fmt.Println("=== Go 语言条件语句详解 ===\n")
// 演示基本 if 语句
demonstrateBasicIf()
// 演示 if-else 语句
demonstrateIfElse()
// 演示 if-else if 链
demonstrateIfElseIf()
// 演示 if 语句中的变量声明
demonstrateIfWithDeclaration()
// 演示嵌套 if 语句
demonstrateNestedIf()
// 演示复杂条件表达式
demonstrateComplexConditions()
// 演示实际应用示例
demonstratePracticalExamples()
}
// demonstrateBasicIf 演示基本 if 语句
func demonstrateBasicIf() {
fmt.Println("1. 基本 if 语句:")
// 最简单的 if 语句
age := 18
if age >= 18 {
fmt.Printf(" 年龄 %d >= 18已成年\n", age)
}
// 条件为 false 的情况
score := 45
if score >= 60 {
fmt.Printf(" 分数 %d >= 60及格\n", score)
}
fmt.Printf(" 分数 %d < 60条件不满足if 块不执行\n", score)
// 布尔变量作为条件
isLoggedIn := true
if isLoggedIn {
fmt.Printf(" 用户已登录\n")
}
// 函数返回值作为条件
if isEven(10) {
fmt.Printf(" 10 是偶数\n")
}
// 注意Go 的 if 语句不需要括号,但需要大括号
fmt.Printf(" 注意: Go 的 if 条件不需要括号,但大括号是必需的\n")
fmt.Println()
}
// demonstrateIfElse 演示 if-else 语句
func demonstrateIfElse() {
fmt.Println("2. if-else 语句:")
// 基本 if-else
temperature := 25
if temperature > 30 {
fmt.Printf(" 温度 %d°C天气炎热\n", temperature)
} else {
fmt.Printf(" 温度 %d°C天气凉爽\n", temperature)
}
// 数值比较
a, b := 10, 20
if a > b {
fmt.Printf(" %d > %d\n", a, b)
} else {
fmt.Printf(" %d <= %d\n", a, b)
}
// 字符串比较
password := "123456"
if password == "admin123" {
fmt.Printf(" 密码正确\n")
} else {
fmt.Printf(" 密码错误\n")
}
// 布尔值判断
hasPermission := false
if hasPermission {
fmt.Printf(" 有权限访问\n")
} else {
fmt.Printf(" 没有权限访问\n")
}
fmt.Println()
}
// demonstrateIfElseIf 演示 if-else if 链
func demonstrateIfElseIf() {
fmt.Println("3. if-else if-else 链:")
// 成绩等级判断
score := 85
fmt.Printf(" 分数: %d\n", score)
if score >= 90 {
fmt.Printf(" 等级: A (优秀)\n")
} else if score >= 80 {
fmt.Printf(" 等级: B (良好)\n")
} else if score >= 70 {
fmt.Printf(" 等级: C (中等)\n")
} else if score >= 60 {
fmt.Printf(" 等级: D (及格)\n")
} else {
fmt.Printf(" 等级: F (不及格)\n")
}
// 年龄段分类
age := 25
fmt.Printf(" 年龄: %d\n", age)
if age < 13 {
fmt.Printf(" 年龄段: 儿童\n")
} else if age < 20 {
fmt.Printf(" 年龄段: 青少年\n")
} else if age < 60 {
fmt.Printf(" 年龄段: 成年人\n")
} else {
fmt.Printf(" 年龄段: 老年人\n")
}
// BMI 指数判断
weight, height := 70.0, 1.75
bmi := weight / (height * height)
fmt.Printf(" BMI: %.1f\n", bmi)
if bmi < 18.5 {
fmt.Printf(" 体重状况: 偏瘦\n")
} else if bmi < 24 {
fmt.Printf(" 体重状况: 正常\n")
} else if bmi < 28 {
fmt.Printf(" 体重状况: 偏胖\n")
} else {
fmt.Printf(" 体重状况: 肥胖\n")
}
fmt.Println()
}
// demonstrateIfWithDeclaration 演示 if 语句中的变量声明
func demonstrateIfWithDeclaration() {
fmt.Println("4. if 语句中的变量声明:")
// 在 if 语句中声明变量
if num := 42; num > 0 {
fmt.Printf(" 在 if 中声明: num = %d > 0\n", num)
// num 在这个 if 块中可用
}
// num 在这里不可用
// 实际应用:字符串转数字
str := "123"
if value, err := strconv.Atoi(str); err == nil {
fmt.Printf(" 字符串 \"%s\" 转换为数字: %d\n", str, value)
} else {
fmt.Printf(" 字符串 \"%s\" 转换失败: %v\n", str, err)
}
// 检查字符串长度
username := "admin"
if length := len(username); length >= 5 {
fmt.Printf(" 用户名 \"%s\" 长度 %d >= 5符合要求\n", username, length)
} else {
fmt.Printf(" 用户名 \"%s\" 长度 %d < 5太短\n", username, length)
}
// 计算并判断
if result := calculateDiscount(1000); result > 0 {
fmt.Printf(" 购买金额 1000折扣: %.2f\n", result)
} else {
fmt.Printf(" 购买金额 1000无折扣\n")
}
// 多个变量声明
if x, y := 10, 20; x+y > 25 {
fmt.Printf(" x=%d, y=%d, x+y=%d > 25\n", x, y, x+y)
}
fmt.Println()
}
// demonstrateNestedIf 演示嵌套 if 语句
func demonstrateNestedIf() {
fmt.Println("5. 嵌套 if 语句:")
// 用户登录验证
username := "admin"
password := "123456"
isActive := true
fmt.Printf(" 用户登录验证:\n")
if username == "admin" {
fmt.Printf(" 用户名正确\n")
if password == "123456" {
fmt.Printf(" 密码正确\n")
if isActive {
fmt.Printf(" 账户状态: 活跃\n")
fmt.Printf(" 登录成功!\n")
} else {
fmt.Printf(" 账户状态: 已禁用\n")
fmt.Printf(" 登录失败: 账户被禁用\n")
}
} else {
fmt.Printf(" 密码错误\n")
fmt.Printf(" 登录失败: 密码不正确\n")
}
} else {
fmt.Printf(" 用户名错误\n")
fmt.Printf(" 登录失败: 用户不存在\n")
}
// 数值范围判断
number := 15
fmt.Printf(" 数值范围判断 (number = %d):\n", number)
if number > 0 {
fmt.Printf(" 数值为正数\n")
if number < 10 {
fmt.Printf(" 数值 < 10属于个位数\n")
} else if number < 100 {
fmt.Printf(" 数值 < 100属于两位数\n")
} else {
fmt.Printf(" 数值 >= 100属于三位数或更多\n")
}
} else if number < 0 {
fmt.Printf(" 数值为负数\n")
} else {
fmt.Printf(" 数值为零\n")
}
fmt.Println()
}
// demonstrateComplexConditions 演示复杂条件表达式
func demonstrateComplexConditions() {
fmt.Println("6. 复杂条件表达式:")
// 逻辑与条件
age := 25
hasLicense := true
hasInsurance := true
if age >= 18 && hasLicense && hasInsurance {
fmt.Printf(" 年龄: %d, 有驾照: %t, 有保险: %t\n", age, hasLicense, hasInsurance)
fmt.Printf(" 可以开车\n")
}
// 逻辑或条件
isWeekend := false
isHoliday := true
if isWeekend || isHoliday {
fmt.Printf(" 周末: %t, 假日: %t\n", isWeekend, isHoliday)
fmt.Printf(" 今天不用上班\n")
}
// 复合条件
temperature := 28
humidity := 70
if (temperature > 25 && humidity > 60) || temperature > 35 {
fmt.Printf(" 温度: %d°C, 湿度: %d%%\n", temperature, humidity)
fmt.Printf(" 天气闷热,建议开空调\n")
}
// 字符串条件
email := "user@example.com"
if strings.Contains(email, "@") && strings.Contains(email, ".") {
fmt.Printf(" 邮箱 \"%s\" 格式基本正确\n", email)
}
// 数值范围条件
score := 75
if score >= 0 && score <= 100 {
fmt.Printf(" 分数 %d 在有效范围内\n", score)
if score >= 60 {
fmt.Printf(" 及格\n")
} else {
fmt.Printf(" 不及格\n")
}
} else {
fmt.Printf(" 分数 %d 超出有效范围\n", score)
}
fmt.Println()
}
// demonstratePracticalExamples 演示实际应用示例
func demonstratePracticalExamples() {
fmt.Println("7. 实际应用示例:")
// 示例1: 银行账户操作
fmt.Printf(" 示例1 - 银行账户操作:\n")
balance := 1000.0
withdrawAmount := 500.0
if withdrawAmount > 0 {
if withdrawAmount <= balance {
balance -= withdrawAmount
fmt.Printf(" 取款成功,取款金额: %.2f,余额: %.2f\n", withdrawAmount, balance)
} else {
fmt.Printf(" 取款失败,余额不足。余额: %.2f,尝试取款: %.2f\n", balance, withdrawAmount)
}
} else {
fmt.Printf(" 取款失败金额必须大于0\n")
}
// 示例2: 文件权限检查
fmt.Printf(" 示例2 - 文件权限检查:\n")
const (
READ = 1 << 0 // 001
WRITE = 1 << 1 // 010
EXECUTE = 1 << 2 // 100
)
permissions := READ | WRITE // 011
operation := "write"
if operation == "read" {
if permissions&READ != 0 {
fmt.Printf(" 允许读取文件\n")
} else {
fmt.Printf(" 没有读取权限\n")
}
} else if operation == "write" {
if permissions&WRITE != 0 {
fmt.Printf(" 允许写入文件\n")
} else {
fmt.Printf(" 没有写入权限\n")
}
} else if operation == "execute" {
if permissions&EXECUTE != 0 {
fmt.Printf(" 允许执行文件\n")
} else {
fmt.Printf(" 没有执行权限\n")
}
}
// 示例3: 购物折扣计算
fmt.Printf(" 示例3 - 购物折扣计算:\n")
purchaseAmount := 800.0
customerLevel := "gold"
isFirstPurchase := false
var discount float64
var discountReason string
if customerLevel == "platinum" {
discount = 0.2
discountReason = "白金会员"
} else if customerLevel == "gold" {
discount = 0.15
discountReason = "黄金会员"
} else if customerLevel == "silver" {
discount = 0.1
discountReason = "银牌会员"
} else {
discount = 0.05
discountReason = "普通会员"
}
// 首次购买额外折扣
if isFirstPurchase {
discount += 0.05
discountReason += " + 首次购买"
}
// 大额购买额外折扣
if purchaseAmount >= 1000 {
discount += 0.05
discountReason += " + 大额购买"
}
finalAmount := purchaseAmount * (1 - discount)
fmt.Printf(" 购买金额: %.2f\n", purchaseAmount)
fmt.Printf(" 客户等级: %s\n", customerLevel)
fmt.Printf(" 首次购买: %t\n", isFirstPurchase)
fmt.Printf(" 折扣原因: %s\n", discountReason)
fmt.Printf(" 折扣率: %.1f%%\n", discount*100)
fmt.Printf(" 最终金额: %.2f\n", finalAmount)
// 示例4: 时间段判断
fmt.Printf(" 示例4 - 时间段判断:\n")
hour := 14
var timeOfDay string
var greeting string
if hour >= 5 && hour < 12 {
timeOfDay = "上午"
greeting = "早上好"
} else if hour >= 12 && hour < 18 {
timeOfDay = "下午"
greeting = "下午好"
} else if hour >= 18 && hour < 22 {
timeOfDay = "晚上"
greeting = "晚上好"
} else {
timeOfDay = "深夜"
greeting = "夜深了"
}
fmt.Printf(" 当前时间: %d:00\n", hour)
fmt.Printf(" 时间段: %s\n", timeOfDay)
fmt.Printf(" 问候语: %s\n", greeting)
fmt.Println()
}
// 辅助函数
func isEven(n int) bool {
return n%2 == 0
}
func calculateDiscount(amount float64) float64 {
if amount >= 1000 {
return amount * 0.1 // 10% 折扣
} else if amount >= 500 {
return amount * 0.05 // 5% 折扣
}
return 0 // 无折扣
}
/*
运行这个程序:
go run 01-if-else.go
学习要点:
1. if 语句的条件不需要括号,但大括号是必需的
2. 可以在 if 语句中声明变量,作用域仅限于 if-else 块
3. if-else if-else 链可以处理多个条件分支
4. 支持复杂的条件表达式,使用 &&、|| 等逻辑运算符
5. 嵌套 if 语句可以处理复杂的逻辑判断
6. Go 没有三元运算符,使用 if-else 代替
最佳实践:
1. 条件表达式要清晰易懂
2. 避免过深的嵌套,考虑提前返回或使用函数分解
3. 复杂条件可以提取为变量或函数
4. 使用有意义的变量名和注释
5. 考虑使用 switch 语句替代长的 if-else if 链
常见应用场景:
1. 用户输入验证
2. 权限检查
3. 数值范围判断
4. 状态判断
5. 错误处理
6. 业务逻辑分支
*/

View File

@@ -0,0 +1,600 @@
/*
02-switch.go - Go 语言 switch 语句详解
学习目标:
1. 掌握 switch 语句的基本用法
2. 理解 Go switch 的特殊特性
3. 学会使用 fallthrough 关键字
4. 了解类型 switch 的用法
5. 掌握无表达式 switch 的使用
知识点:
- switch 基本语法
- case 多值匹配
- fallthrough 关键字
- 类型 switch
- 无表达式 switch
- switch 中的变量声明
- 实际应用场景
*/
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
fmt.Println("=== Go 语言 switch 语句详解 ===\n")
// 演示基本 switch 语句
demonstrateBasicSwitch()
// 演示多值 case
demonstrateMultiValueCase()
// 演示 fallthrough
demonstrateFallthrough()
// 演示无表达式 switch
demonstrateExpressionlessSwitch()
// 演示类型 switch
demonstrateTypeSwitch()
// 演示 switch 中的变量声明
demonstrateSwitchWithDeclaration()
// 演示实际应用示例
demonstratePracticalExamples()
}
// demonstrateBasicSwitch 演示基本 switch 语句
func demonstrateBasicSwitch() {
fmt.Println("1. 基本 switch 语句:")
// 基本用法
day := 3
fmt.Printf(" 今天是星期 %d: ", day)
switch day {
case 1:
fmt.Printf("星期一\n")
case 2:
fmt.Printf("星期二\n")
case 3:
fmt.Printf("星期三\n")
case 4:
fmt.Printf("星期四\n")
case 5:
fmt.Printf("星期五\n")
case 6:
fmt.Printf("星期六\n")
case 7:
fmt.Printf("星期日\n")
default:
fmt.Printf("无效的日期\n")
}
// 字符串匹配
grade := "B"
fmt.Printf(" 成绩等级 %s: ", grade)
switch grade {
case "A":
fmt.Printf("优秀 (90-100分)\n")
case "B":
fmt.Printf("良好 (80-89分)\n")
case "C":
fmt.Printf("中等 (70-79分)\n")
case "D":
fmt.Printf("及格 (60-69分)\n")
case "F":
fmt.Printf("不及格 (0-59分)\n")
default:
fmt.Printf("无效等级\n")
}
// 字符匹配
char := 'a'
fmt.Printf(" 字符 '%c' 是: ", char)
switch char {
case 'a', 'e', 'i', 'o', 'u':
fmt.Printf("元音字母\n")
default:
fmt.Printf("辅音字母或其他字符\n")
}
// Go switch 的特点:自动 break
fmt.Printf(" Go switch 特点: 每个 case 自动 break不会继续执行下一个 case\n")
fmt.Println()
}
// demonstrateMultiValueCase 演示多值 case
func demonstrateMultiValueCase() {
fmt.Println("2. 多值 case:")
// 数字分组
number := 4
fmt.Printf(" 数字 %d 属于: ", number)
switch number {
case 1, 3, 5, 7, 9:
fmt.Printf("奇数\n")
case 2, 4, 6, 8, 10:
fmt.Printf("偶数\n")
case 0:
fmt.Printf("零\n")
default:
fmt.Printf("其他数字\n")
}
// 月份分组
month := 7
fmt.Printf(" %d月属于: ", month)
switch month {
case 12, 1, 2:
fmt.Printf("冬季\n")
case 3, 4, 5:
fmt.Printf("春季\n")
case 6, 7, 8:
fmt.Printf("夏季\n")
case 9, 10, 11:
fmt.Printf("秋季\n")
default:
fmt.Printf("无效月份\n")
}
// 工作日分组
weekday := "Saturday"
fmt.Printf(" %s 是: ", weekday)
switch weekday {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
fmt.Printf("工作日\n")
case "Saturday", "Sunday":
fmt.Printf("周末\n")
default:
fmt.Printf("无效日期\n")
}
// HTTP 状态码分组
statusCode := 404
fmt.Printf(" HTTP 状态码 %d: ", statusCode)
switch statusCode {
case 200, 201, 202, 204:
fmt.Printf("成功响应\n")
case 301, 302, 304:
fmt.Printf("重定向\n")
case 400, 401, 403, 404:
fmt.Printf("客户端错误\n")
case 500, 501, 502, 503:
fmt.Printf("服务器错误\n")
default:
fmt.Printf("其他状态码\n")
}
fmt.Println()
}
// demonstrateFallthrough 演示 fallthrough 关键字
func demonstrateFallthrough() {
fmt.Println("3. fallthrough 关键字:")
fmt.Printf(" fallthrough 让程序继续执行下一个 case\n")
score := 85
fmt.Printf(" 分数 %d 的评价:\n", score)
switch {
case score >= 90:
fmt.Printf(" 优秀\n")
fallthrough
case score >= 80:
fmt.Printf(" 良好\n")
fallthrough
case score >= 70:
fmt.Printf(" 中等\n")
fallthrough
case score >= 60:
fmt.Printf(" 及格\n")
default:
fmt.Printf(" 不及格\n")
}
// 另一个 fallthrough 示例
level := 2
fmt.Printf(" 用户等级 %d 的权限:\n", level)
switch level {
case 3:
fmt.Printf(" - 管理员权限\n")
fallthrough
case 2:
fmt.Printf(" - 编辑权限\n")
fallthrough
case 1:
fmt.Printf(" - 查看权限\n")
case 0:
fmt.Printf(" - 无权限\n")
}
// 注意事项
fmt.Printf(" 注意: fallthrough 只能在 case 的最后一行使用\n")
fmt.Printf(" 注意: fallthrough 会无条件执行下一个 case\n")
fmt.Println()
}
// demonstrateExpressionlessSwitch 演示无表达式 switch
func demonstrateExpressionlessSwitch() {
fmt.Println("4. 无表达式 switch:")
fmt.Printf(" 无表达式 switch 相当于 switch true可以替代长的 if-else if 链\n")
// 年龄分组
age := 25
fmt.Printf(" 年龄 %d 岁: ", age)
switch {
case age < 13:
fmt.Printf("儿童\n")
case age < 20:
fmt.Printf("青少年\n")
case age < 60:
fmt.Printf("成年人\n")
default:
fmt.Printf("老年人\n")
}
// 温度判断
temperature := 28
fmt.Printf(" 温度 %d°C: ", temperature)
switch {
case temperature < 0:
fmt.Printf("冰点以下\n")
case temperature < 10:
fmt.Printf("寒冷\n")
case temperature < 20:
fmt.Printf("凉爽\n")
case temperature < 30:
fmt.Printf("温暖\n")
default:
fmt.Printf("炎热\n")
}
// 复杂条件
hour := 14
isWeekend := false
fmt.Printf(" 时间 %d:00, 周末: %t - ", hour, isWeekend)
switch {
case hour < 6:
fmt.Printf("深夜时间\n")
case hour < 12 && !isWeekend:
fmt.Printf("工作上午\n")
case hour < 12 && isWeekend:
fmt.Printf("周末上午\n")
case hour < 18 && !isWeekend:
fmt.Printf("工作下午\n")
case hour < 18 && isWeekend:
fmt.Printf("周末下午\n")
case hour < 22:
fmt.Printf("晚上时间\n")
default:
fmt.Printf("夜晚时间\n")
}
// 数值范围判断
value := 75
fmt.Printf(" 数值 %d: ", value)
switch {
case value < 0:
fmt.Printf("负数\n")
case value == 0:
fmt.Printf("零\n")
case value <= 50:
fmt.Printf("小数值 (1-50)\n")
case value <= 100:
fmt.Printf("中等数值 (51-100)\n")
default:
fmt.Printf("大数值 (>100)\n")
}
fmt.Println()
}
// demonstrateTypeSwitch 演示类型 switch
func demonstrateTypeSwitch() {
fmt.Println("5. 类型 switch:")
fmt.Printf(" 类型 switch 用于判断接口变量的实际类型\n")
// 定义不同类型的变量
values := []interface{}{
42,
"hello",
3.14,
true,
[]int{1, 2, 3},
map[string]int{"a": 1},
nil,
}
for i, v := range values {
fmt.Printf(" 值 %d: %v - ", i+1, v)
switch t := v.(type) {
case nil:
fmt.Printf("nil 类型\n")
case bool:
fmt.Printf("布尔类型: %t\n", t)
case int:
fmt.Printf("整数类型: %d\n", t)
case string:
fmt.Printf("字符串类型: \"%s\" (长度: %d)\n", t, len(t))
case float64:
fmt.Printf("浮点类型: %.2f\n", t)
case []int:
fmt.Printf("整数切片: %v (长度: %d)\n", t, len(t))
case map[string]int:
fmt.Printf("字符串到整数的映射: %v\n", t)
default:
fmt.Printf("未知类型: %T\n", t)
}
}
// 类型 switch 的另一种用法
fmt.Printf(" 处理不同类型的数据:\n")
processValue(42)
processValue("Go语言")
processValue(3.14159)
processValue([]string{"a", "b", "c"})
fmt.Println()
}
// demonstrateSwitchWithDeclaration 演示 switch 中的变量声明
func demonstrateSwitchWithDeclaration() {
fmt.Println("6. switch 中的变量声明:")
// 在 switch 中声明变量
fmt.Printf(" 在 switch 中声明变量:\n")
switch num := rand.Intn(10); {
case num < 3:
fmt.Printf(" 随机数 %d < 3小数值\n", num)
case num < 7:
fmt.Printf(" 随机数 %d 在 3-6 之间,中等数值\n", num)
default:
fmt.Printf(" 随机数 %d >= 7大数值\n", num)
}
// 计算并判断
switch result := calculateGrade(85); result {
case "A":
fmt.Printf(" 成绩优秀: %s\n", result)
case "B":
fmt.Printf(" 成绩良好: %s\n", result)
case "C":
fmt.Printf(" 成绩中等: %s\n", result)
default:
fmt.Printf(" 成绩: %s\n", result)
}
// 字符串处理
switch length := len("Hello, World!"); {
case length < 5:
fmt.Printf(" 字符串长度 %d较短\n", length)
case length < 10:
fmt.Printf(" 字符串长度 %d中等\n", length)
default:
fmt.Printf(" 字符串长度 %d较长\n", length)
}
fmt.Println()
}
// demonstratePracticalExamples 演示实际应用示例
func demonstratePracticalExamples() {
fmt.Println("7. 实际应用示例:")
// 示例1: HTTP 请求处理
fmt.Printf(" 示例1 - HTTP 请求处理:\n")
method := "POST"
path := "/api/users"
switch method {
case "GET":
fmt.Printf(" 处理 GET 请求: 获取资源 %s\n", path)
case "POST":
fmt.Printf(" 处理 POST 请求: 创建资源 %s\n", path)
case "PUT":
fmt.Printf(" 处理 PUT 请求: 更新资源 %s\n", path)
case "DELETE":
fmt.Printf(" 处理 DELETE 请求: 删除资源 %s\n", path)
default:
fmt.Printf(" 不支持的 HTTP 方法: %s\n", method)
}
// 示例2: 文件扩展名处理
fmt.Printf(" 示例2 - 文件类型判断:\n")
filename := "document.pdf"
var fileType string
switch {
case hasExtension(filename, ".txt", ".md", ".doc", ".docx"):
fileType = "文档文件"
case hasExtension(filename, ".jpg", ".png", ".gif", ".bmp"):
fileType = "图片文件"
case hasExtension(filename, ".mp4", ".avi", ".mov", ".wmv"):
fileType = "视频文件"
case hasExtension(filename, ".mp3", ".wav", ".flac", ".aac"):
fileType = "音频文件"
case hasExtension(filename, ".pdf"):
fileType = "PDF文件"
case hasExtension(filename, ".zip", ".rar", ".7z", ".tar"):
fileType = "压缩文件"
default:
fileType = "未知文件类型"
}
fmt.Printf(" 文件 \"%s\" 是 %s\n", filename, fileType)
// 示例3: 游戏状态机
fmt.Printf(" 示例3 - 游戏状态处理:\n")
gameState := "playing"
playerHealth := 30
switch gameState {
case "menu":
fmt.Printf(" 显示主菜单\n")
case "playing":
fmt.Printf(" 游戏进行中\n")
switch {
case playerHealth <= 0:
fmt.Printf(" 玩家死亡,游戏结束\n")
case playerHealth < 20:
fmt.Printf(" 玩家生命值低 (%d),危险状态\n", playerHealth)
case playerHealth < 50:
fmt.Printf(" 玩家生命值中等 (%d),注意安全\n", playerHealth)
default:
fmt.Printf(" 玩家状态良好 (%d)\n", playerHealth)
}
case "paused":
fmt.Printf(" 游戏暂停\n")
case "gameover":
fmt.Printf(" 游戏结束\n")
default:
fmt.Printf(" 未知游戏状态: %s\n", gameState)
}
// 示例4: 错误码处理
fmt.Printf(" 示例4 - 错误码处理:\n")
errorCode := 1001
switch errorCode {
case 0:
fmt.Printf(" 操作成功\n")
case 1000, 1001, 1002:
fmt.Printf(" 用户相关错误 (错误码: %d)\n", errorCode)
switch errorCode {
case 1000:
fmt.Printf(" 用户不存在\n")
case 1001:
fmt.Printf(" 密码错误\n")
case 1002:
fmt.Printf(" 账户被锁定\n")
}
case 2000, 2001, 2002:
fmt.Printf(" 权限相关错误 (错误码: %d)\n", errorCode)
case 3000, 3001, 3002:
fmt.Printf(" 数据相关错误 (错误码: %d)\n", errorCode)
default:
fmt.Printf(" 未知错误 (错误码: %d)\n", errorCode)
}
// 示例5: 配置解析
fmt.Printf(" 示例5 - 配置解析:\n")
config := map[string]interface{}{
"debug": true,
"port": 8080,
"database": "mysql",
"timeout": 30.5,
}
for key, value := range config {
fmt.Printf(" 配置项 %s: ", key)
switch v := value.(type) {
case bool:
if v {
fmt.Printf("启用\n")
} else {
fmt.Printf("禁用\n")
}
case int:
fmt.Printf("数值 %d\n", v)
case float64:
fmt.Printf("浮点数 %.1f\n", v)
case string:
fmt.Printf("字符串 \"%s\"\n", v)
default:
fmt.Printf("未知类型 %T\n", v)
}
}
fmt.Println()
}
// 辅助函数
func processValue(v interface{}) {
switch val := v.(type) {
case int:
fmt.Printf(" 处理整数: %d平方: %d\n", val, val*val)
case string:
fmt.Printf(" 处理字符串: \"%s\",长度: %d\n", val, len(val))
case float64:
fmt.Printf(" 处理浮点数: %.3f,四舍五入: %.0f\n", val, val)
case []string:
fmt.Printf(" 处理字符串切片: %v元素个数: %d\n", val, len(val))
default:
fmt.Printf(" 无法处理的类型: %T\n", val)
}
}
func calculateGrade(score int) string {
switch {
case score >= 90:
return "A"
case score >= 80:
return "B"
case score >= 70:
return "C"
case score >= 60:
return "D"
default:
return "F"
}
}
func hasExtension(filename string, extensions ...string) bool {
for _, ext := range extensions {
if len(filename) >= len(ext) &&
filename[len(filename)-len(ext):] == ext {
return true
}
}
return false
}
func init() {
rand.Seed(time.Now().UnixNano())
}
/*
运行这个程序:
go run 02-switch.go
学习要点:
1. Go 的 switch 语句自动 break不需要显式写 break
2. case 可以包含多个值,用逗号分隔
3. fallthrough 关键字可以让程序继续执行下一个 case
4. 无表达式 switch 相当于 switch true可以替代长的 if-else if 链
5. 类型 switch 用于判断接口变量的实际类型
6. 可以在 switch 语句中声明变量
Go switch 的优势:
1. 比长的 if-else if 链更清晰
2. 自动 break 避免了忘记 break 的错误
3. 支持多值 case代码更简洁
4. 类型 switch 提供了强大的类型判断能力
5. 无表达式 switch 提供了灵活的条件判断
使用建议:
1. 当有多个固定值需要判断时,优先使用 switch
2. 当条件复杂时,使用无表达式 switch
3. 处理接口类型时,使用类型 switch
4. 谨慎使用 fallthrough确保逻辑正确
5. 合理使用 default 分支处理异常情况
常见应用场景:
1. 状态机实现
2. 错误码处理
3. 文件类型判断
4. HTTP 请求路由
5. 配置解析
6. 类型判断和处理
*/

View File

@@ -0,0 +1,633 @@
/*
03-for-loops.go - Go 语言 for 循环详解
学习目标:
1. 掌握 for 循环的各种形式
2. 理解 break 和 continue 的使用
3. 学会使用标签控制嵌套循环
4. 了解无限循环的写法
5. 掌握循环的实际应用场景
知识点:
- 传统 for 循环
- while 风格的 for 循环
- 无限循环
- break 和 continue
- 标签 (label)
- 嵌套循环
- 循环优化技巧
*/
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
fmt.Println("=== Go 语言 for 循环详解 ===\n")
// 演示传统 for 循环
demonstrateTraditionalFor()
// 演示 while 风格的 for 循环
demonstrateWhileStyleFor()
// 演示无限循环
demonstrateInfiniteLoop()
// 演示 break 和 continue
demonstrateBreakContinue()
// 演示嵌套循环和标签
demonstrateNestedLoopsAndLabels()
// 演示循环的实际应用
demonstratePracticalExamples()
// 演示循环优化技巧
demonstrateOptimizationTips()
}
// demonstrateTraditionalFor 演示传统 for 循环
func demonstrateTraditionalFor() {
fmt.Println("1. 传统 for 循环:")
// 基本的 for 循环
fmt.Printf(" 基本 for 循环 (0-4):\n")
for i := 0; i < 5; i++ {
fmt.Printf(" i = %d\n", i)
}
// 倒序循环
fmt.Printf(" 倒序循环 (5-1):\n")
for i := 5; i > 0; i-- {
fmt.Printf(" i = %d\n", i)
}
// 步长为 2 的循环
fmt.Printf(" 步长为 2 的循环:\n")
for i := 0; i <= 10; i += 2 {
fmt.Printf(" i = %d\n", i)
}
// 多个变量的循环
fmt.Printf(" 多变量循环:\n")
for i, j := 0, 10; i < j; i, j = i+1, j-1 {
fmt.Printf(" i = %d, j = %d\n", i, j)
}
// 计算累加和
sum := 0
for i := 1; i <= 10; i++ {
sum += i
}
fmt.Printf(" 1到10的累加和: %d\n", sum)
// 计算阶乘
factorial := 1
n := 5
for i := 1; i <= n; i++ {
factorial *= i
}
fmt.Printf(" %d的阶乘: %d\n", n, factorial)
fmt.Println()
}
// demonstrateWhileStyleFor 演示 while 风格的 for 循环
func demonstrateWhileStyleFor() {
fmt.Println("2. while 风格的 for 循环:")
fmt.Printf(" Go 没有 while 关键字,使用 for 代替\n")
// 模拟 while 循环
fmt.Printf(" 模拟 while 循环:\n")
count := 0
for count < 5 {
fmt.Printf(" count = %d\n", count)
count++
}
// 条件判断循环
fmt.Printf(" 条件判断循环 (猜数字):\n")
target := 7
guess := 1
attempts := 0
for guess != target {
attempts++
fmt.Printf(" 第 %d 次猜测: %d", attempts, guess)
if guess < target {
fmt.Printf(" (太小了)\n")
guess += 2
} else {
fmt.Printf(" (太大了)\n")
guess--
}
}
fmt.Printf(" 恭喜!第 %d 次猜中了: %d\n", attempts+1, guess)
// 读取用户输入直到满足条件
fmt.Printf(" 模拟输入验证:\n")
password := ""
attempts = 0
correctPassword := "123456"
// 模拟用户输入
inputs := []string{"111", "222", "123456"}
for password != correctPassword && attempts < 3 {
password = inputs[attempts] // 模拟用户输入
attempts++
fmt.Printf(" 第 %d 次输入密码: %s", attempts, password)
if password == correctPassword {
fmt.Printf(" (正确)\n")
} else {
fmt.Printf(" (错误)\n")
}
}
if password == correctPassword {
fmt.Printf(" 登录成功!\n")
} else {
fmt.Printf(" 登录失败,超过最大尝试次数\n")
}
fmt.Println()
}
// demonstrateInfiniteLoop 演示无限循环
func demonstrateInfiniteLoop() {
fmt.Println("3. 无限循环:")
fmt.Printf(" 无限循环的写法: for { ... }\n")
fmt.Printf(" 通常配合 break 使用\n")
// 无限循环示例1: 服务器主循环模拟
fmt.Printf(" 示例1 - 服务器主循环模拟:\n")
requestCount := 0
for {
requestCount++
fmt.Printf(" 处理第 %d 个请求\n", requestCount)
// 模拟处理请求
if requestCount >= 3 {
fmt.Printf(" 服务器关闭\n")
break
}
}
// 无限循环示例2: 菜单系统
fmt.Printf(" 示例2 - 菜单系统模拟:\n")
menuOptions := []string{"查看余额", "转账", "退出"}
choice := 0
for {
fmt.Printf(" 请选择操作:\n")
for i, option := range menuOptions {
fmt.Printf(" %d. %s\n", i+1, option)
}
// 模拟用户选择
choice = (choice % 3) + 1
fmt.Printf(" 用户选择: %d\n", choice)
switch choice {
case 1:
fmt.Printf(" 当前余额: 1000元\n")
case 2:
fmt.Printf(" 转账功能暂未开放\n")
case 3:
fmt.Printf(" 谢谢使用,再见!\n")
return // 或者使用 break
}
// 为了演示,只循环一次
break
}
fmt.Println()
}
// demonstrateBreakContinue 演示 break 和 continue
func demonstrateBreakContinue() {
fmt.Println("4. break 和 continue:")
// break 示例
fmt.Printf(" break - 跳出循环:\n")
for i := 0; i < 10; i++ {
if i == 5 {
fmt.Printf(" 遇到 %d跳出循环\n", i)
break
}
fmt.Printf(" i = %d\n", i)
}
// continue 示例
fmt.Printf(" continue - 跳过当前迭代:\n")
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // 跳过偶数
}
fmt.Printf(" 奇数: %d\n", i)
}
// 实际应用:处理数据时跳过无效值
fmt.Printf(" 实际应用 - 处理数据跳过无效值:\n")
data := []int{1, -2, 3, 0, 5, -6, 7, 8, 0, 9}
sum := 0
validCount := 0
for i, value := range data {
if value <= 0 {
fmt.Printf(" 跳过无效值 data[%d] = %d\n", i, value)
continue
}
sum += value
validCount++
fmt.Printf(" 处理有效值 data[%d] = %d\n", i, value)
}
fmt.Printf(" 有效数据个数: %d总和: %d平均值: %.2f\n",
validCount, sum, float64(sum)/float64(validCount))
// 查找第一个满足条件的元素
fmt.Printf(" 查找第一个大于 50 的数:\n")
numbers := []int{10, 25, 30, 55, 60, 75}
found := false
for i, num := range numbers {
fmt.Printf(" 检查 numbers[%d] = %d\n", i, num)
if num > 50 {
fmt.Printf(" 找到第一个大于 50 的数: %d\n", num)
found = true
break
}
}
if !found {
fmt.Printf(" 没有找到大于 50 的数\n")
}
fmt.Println()
}
// demonstrateNestedLoopsAndLabels 演示嵌套循环和标签
func demonstrateNestedLoopsAndLabels() {
fmt.Println("5. 嵌套循环和标签:")
// 基本嵌套循环
fmt.Printf(" 基本嵌套循环 - 乘法表:\n")
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
fmt.Printf(" %d × %d = %d\n", i, j, i*j)
}
}
// 使用标签控制嵌套循环
fmt.Printf(" 使用标签控制嵌套循环:\n")
outer:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
fmt.Printf(" i=%d, j=%d\n", i, j)
if i == 2 && j == 2 {
fmt.Printf(" 在 i=2, j=2 时跳出外层循环\n")
break outer
}
}
}
// 标签 continue 示例
fmt.Printf(" 标签 continue 示例:\n")
outerContinue:
for i := 1; i <= 3; i++ {
fmt.Printf(" 外层循环 i = %d\n", i)
for j := 1; j <= 3; j++ {
if i == 2 && j == 2 {
fmt.Printf(" 在 i=2, j=2 时跳过外层循环的当前迭代\n")
continue outerContinue
}
fmt.Printf(" 内层循环 j = %d\n", j)
}
fmt.Printf(" 外层循环 i = %d 结束\n", i)
}
// 矩阵搜索示例
fmt.Printf(" 矩阵搜索示例:\n")
matrix := [][]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
target := 5
found := false
search:
for i := 0; i < len(matrix); i++ {
for j := 0; j < len(matrix[i]); j++ {
fmt.Printf(" 检查 matrix[%d][%d] = %d\n", i, j, matrix[i][j])
if matrix[i][j] == target {
fmt.Printf(" 找到目标值 %d 在位置 [%d][%d]\n", target, i, j)
found = true
break search
}
}
}
if !found {
fmt.Printf(" 未找到目标值 %d\n", target)
}
fmt.Println()
}
// demonstratePracticalExamples 演示循环的实际应用
func demonstratePracticalExamples() {
fmt.Println("6. 循环的实际应用:")
// 示例1: 数组/切片处理
fmt.Printf(" 示例1 - 数组处理:\n")
scores := []int{85, 92, 78, 96, 88, 73, 91}
// 计算平均分
total := 0
for _, score := range scores {
total += score
}
average := float64(total) / float64(len(scores))
fmt.Printf(" 平均分: %.2f\n", average)
// 找出最高分和最低分
maxScore, minScore := scores[0], scores[0]
for _, score := range scores {
if score > maxScore {
maxScore = score
}
if score < minScore {
minScore = score
}
}
fmt.Printf(" 最高分: %d最低分: %d\n", maxScore, minScore)
// 统计及格人数
passCount := 0
for _, score := range scores {
if score >= 80 {
passCount++
}
}
fmt.Printf(" 及格人数: %d/%d\n", passCount, len(scores))
// 示例2: 字符串处理
fmt.Printf(" 示例2 - 字符串处理:\n")
text := "Hello, 世界! 123"
// 统计字符类型
letters, digits, others := 0, 0, 0
for _, char := range text {
switch {
case (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || char > 127:
letters++
case char >= '0' && char <= '9':
digits++
default:
others++
}
}
fmt.Printf(" 字符串: \"%s\"\n", text)
fmt.Printf(" 字母: %d数字: %d其他: %d\n", letters, digits, others)
// 示例3: 数学计算
fmt.Printf(" 示例3 - 数学计算 (斐波那契数列):\n")
n := 10
fmt.Printf(" 前 %d 个斐波那契数:\n", n)
a, b := 0, 1
for i := 0; i < n; i++ {
fmt.Printf(" F(%d) = %d\n", i, a)
a, b = b, a+b
}
// 示例4: 模拟游戏
fmt.Printf(" 示例4 - 简单猜数字游戏:\n")
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(10) + 1
maxAttempts := 3
// 模拟玩家猜测
guesses := []int{5, 8, secretNumber}
for attempt := 1; attempt <= maxAttempts; attempt++ {
guess := guesses[attempt-1] // 模拟用户输入
fmt.Printf(" 第 %d 次猜测: %d", attempt, guess)
if guess == secretNumber {
fmt.Printf(" - 恭喜你猜对了!\n")
break
} else if guess < secretNumber {
fmt.Printf(" - 太小了\n")
} else {
fmt.Printf(" - 太大了\n")
}
if attempt == maxAttempts {
fmt.Printf(" 游戏结束!正确答案是: %d\n", secretNumber)
}
}
// 示例5: 数据验证
fmt.Printf(" 示例5 - 批量数据验证:\n")
emails := []string{
"user@example.com",
"invalid-email",
"test@domain.org",
"@invalid.com",
"valid@test.net",
}
validEmails := 0
for i, email := range emails {
isValid := validateEmail(email)
fmt.Printf(" 邮箱 %d: %-20s - ", i+1, email)
if isValid {
fmt.Printf("有效\n")
validEmails++
} else {
fmt.Printf("无效\n")
}
}
fmt.Printf(" 有效邮箱数量: %d/%d\n", validEmails, len(emails))
fmt.Println()
}
// demonstrateOptimizationTips 演示循环优化技巧
func demonstrateOptimizationTips() {
fmt.Println("7. 循环优化技巧:")
// 技巧1: 减少重复计算
fmt.Printf(" 技巧1 - 减少重复计算:\n")
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 不好的写法:每次都计算 len(data)
fmt.Printf(" 不推荐的写法 (每次计算长度):\n")
for i := 0; i < len(data); i++ {
// len(data) 在每次迭代时都会被调用
fmt.Printf(" data[%d] = %d\n", i, data[i])
if i >= 2 { // 为了演示,只显示前几个
break
}
}
// 好的写法:预先计算长度
fmt.Printf(" 推荐的写法 (预先计算长度):\n")
length := len(data)
for i := 0; i < length; i++ {
fmt.Printf(" data[%d] = %d\n", i, data[i])
if i >= 2 {
break
}
}
// 技巧2: 使用 range 遍历
fmt.Printf(" 技巧2 - 使用 range 遍历 (更简洁):\n")
for i, value := range data {
fmt.Printf(" data[%d] = %d\n", i, value)
if i >= 2 {
break
}
}
// 技巧3: 提前退出
fmt.Printf(" 技巧3 - 提前退出优化:\n")
numbers := []int{2, 4, 6, 7, 8, 10, 12}
// 查找第一个奇数
for i, num := range numbers {
fmt.Printf(" 检查 numbers[%d] = %d", i, num)
if num%2 == 1 {
fmt.Printf(" - 找到第一个奇数: %d\n", num)
break // 找到后立即退出,不继续遍历
}
fmt.Printf(" - 偶数,继续查找\n")
}
// 技巧4: 批量处理
fmt.Printf(" 技巧4 - 批量处理:\n")
largeData := make([]int, 20)
for i := range largeData {
largeData[i] = i + 1
}
batchSize := 5
fmt.Printf(" 批量处理数据 (批次大小: %d):\n", batchSize)
for i := 0; i < len(largeData); i += batchSize {
end := i + batchSize
if end > len(largeData) {
end = len(largeData)
}
batch := largeData[i:end]
fmt.Printf(" 处理批次 %d-%d: %v\n", i, end-1, batch)
// 模拟批量处理
batchSum := 0
for _, value := range batch {
batchSum += value
}
fmt.Printf(" 批次总和: %d\n", batchSum)
}
// 技巧5: 避免不必要的操作
fmt.Printf(" 技巧5 - 避免不必要的操作:\n")
matrix2 := [][]int{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
}
// 只处理对角线元素
fmt.Printf(" 只处理矩阵对角线元素:\n")
for i := 0; i < len(matrix2) && i < len(matrix2[0]); i++ {
fmt.Printf(" 对角线元素 [%d][%d] = %d\n", i, i, matrix2[i][i])
}
fmt.Println()
}
// 辅助函数
func validateEmail(email string) bool {
// 简单的邮箱验证(实际应用中应该使用正则表达式)
if len(email) < 5 {
return false
}
hasAt := false
hasDot := false
atPos := -1
for i, char := range email {
if char == '@' {
if hasAt || i == 0 || i == len(email)-1 {
return false
}
hasAt = true
atPos = i
} else if char == '.' && hasAt && i > atPos+1 && i < len(email)-1 {
hasDot = true
}
}
return hasAt && hasDot
}
/*
运行这个程序:
go run 03-for-loops.go
学习要点:
1. Go 只有 for 循环,没有 while 和 do-while
2. for 循环有三种形式传统形式、while 形式、无限循环形式
3. break 用于跳出循环continue 用于跳过当前迭代
4. 标签可以用来控制嵌套循环的跳转
5. range 关键字提供了遍历数组、切片、字符串等的便捷方式
for 循环的三种形式:
1. for init; condition; post { ... } // 传统形式
2. for condition { ... } // while 形式
3. for { ... } // 无限循环
循环控制:
1. break: 跳出当前循环
2. continue: 跳过当前迭代,继续下一次迭代
3. 标签: 可以跳出或跳过指定的外层循环
优化建议:
1. 减少循环内的重复计算
2. 使用 range 遍历集合类型
3. 适当使用 break 提前退出
4. 考虑批量处理大量数据
5. 避免不必要的嵌套循环
常见应用场景:
1. 数组/切片遍历和处理
2. 数值计算(累加、阶乘等)
3. 字符串处理
4. 数据验证和过滤
5. 算法实现
6. 游戏循环
7. 服务器主循环
注意事项:
1. 避免无限循环(除非有明确的退出条件)
2. 注意循环变量的作用域
3. 在嵌套循环中正确使用标签
4. 考虑循环的时间复杂度
5. 合理使用 break 和 continue
*/

View File

@@ -0,0 +1,698 @@
/*
04-range.go - Go 语言 range 关键字详解
学习目标:
1. 掌握 range 的基本用法
2. 理解 range 在不同数据类型上的应用
3. 学会处理 range 返回的索引和值
4. 了解 range 的性能特点
5. 掌握 range 的实际应用场景
知识点:
- range 遍历数组和切片
- range 遍历字符串
- range 遍历映射 (map)
- range 遍历通道 (channel)
- range 的值拷贝特性
- 忽略索引或值的技巧
- range 的性能考虑
*/
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
fmt.Println("=== Go 语言 range 关键字详解 ===\n")
// 演示 range 遍历数组和切片
demonstrateRangeArraySlice()
// 演示 range 遍历字符串
demonstrateRangeString()
// 演示 range 遍历映射
demonstrateRangeMap()
// 演示 range 遍历通道
demonstrateRangeChannel()
// 演示 range 的值拷贝特性
demonstrateRangeValueCopy()
// 演示忽略索引或值
demonstrateIgnoreIndexValue()
// 演示 range 的实际应用
demonstratePracticalExamples()
// 演示 range 的性能考虑
demonstratePerformanceConsiderations()
}
// demonstrateRangeArraySlice 演示 range 遍历数组和切片
func demonstrateRangeArraySlice() {
fmt.Println("1. range 遍历数组和切片:")
// 遍历数组
fmt.Printf(" 遍历数组:\n")
arr := [5]int{10, 20, 30, 40, 50}
for index, value := range arr {
fmt.Printf(" arr[%d] = %d\n", index, value)
}
// 遍历切片
fmt.Printf(" 遍历切片:\n")
slice := []string{"Go", "Python", "Java", "JavaScript"}
for i, lang := range slice {
fmt.Printf(" 语言 %d: %s\n", i+1, lang)
}
// 遍历空切片
fmt.Printf(" 遍历空切片:\n")
var emptySlice []int
count := 0
for range emptySlice {
count++
}
fmt.Printf(" 空切片遍历次数: %d\n", count)
// 遍历 nil 切片
fmt.Printf(" 遍历 nil 切片:\n")
var nilSlice []int = nil
count = 0
for range nilSlice {
count++
}
fmt.Printf(" nil 切片遍历次数: %d\n", count)
// 多维切片遍历
fmt.Printf(" 遍历二维切片:\n")
matrix := [][]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
for i, row := range matrix {
for j, value := range row {
fmt.Printf(" matrix[%d][%d] = %d\n", i, j, value)
}
}
fmt.Println()
}
// demonstrateRangeString 演示 range 遍历字符串
func demonstrateRangeString() {
fmt.Println("2. range 遍历字符串:")
// 基本字符串遍历
fmt.Printf(" 遍历 ASCII 字符串:\n")
str1 := "Hello"
for index, char := range str1 {
fmt.Printf(" str1[%d] = '%c' (Unicode: %d)\n", index, char, char)
}
// 遍历包含中文的字符串
fmt.Printf(" 遍历包含中文的字符串:\n")
str2 := "Hello世界"
for index, char := range str2 {
fmt.Printf(" 位置 %d: '%c' (Unicode: %d)\n", index, char, char)
}
// 注意index 是字节位置,不是字符位置
fmt.Printf(" 注意: range 返回的索引是字节位置,不是字符位置\n")
// 字符串长度对比
fmt.Printf(" 字符串长度对比:\n")
fmt.Printf(" 字节长度 len(\"%s\"): %d\n", str2, len(str2))
fmt.Printf(" 字符长度 utf8.RuneCountInString(\"%s\"): %d\n",
str2, utf8.RuneCountInString(str2))
// 遍历字符串的字节
fmt.Printf(" 按字节遍历字符串:\n")
for i := 0; i < len(str2); i++ {
fmt.Printf(" 字节 %d: %d ('%c')\n", i, str2[i], str2[i])
if i >= 7 { // 限制输出
fmt.Printf(" ...\n")
break
}
}
// 统计字符类型
fmt.Printf(" 统计字符类型:\n")
text := "Hello, 世界! 123"
ascii, unicode, digit, other := 0, 0, 0, 0
for _, char := range text {
switch {
case char >= 'A' && char <= 'Z' || char >= 'a' && char <= 'z':
ascii++
case char >= '0' && char <= '9':
digit++
case char > 127:
unicode++
default:
other++
}
}
fmt.Printf(" 文本: \"%s\"\n", text)
fmt.Printf(" ASCII字母: %d, Unicode字符: %d, 数字: %d, 其他: %d\n",
ascii, unicode, digit, other)
fmt.Println()
}
// demonstrateRangeMap 演示 range 遍历映射
func demonstrateRangeMap() {
fmt.Println("3. range 遍历映射 (map):")
// 基本映射遍历
fmt.Printf(" 遍历基本映射:\n")
scores := map[string]int{
"Alice": 95,
"Bob": 87,
"Charlie": 92,
"David": 78,
}
for name, score := range scores {
fmt.Printf(" %s: %d分\n", name, score)
}
// 注意:映射遍历顺序是随机的
fmt.Printf(" 注意: 映射的遍历顺序是随机的\n")
// 遍历复杂映射
fmt.Printf(" 遍历复杂映射:\n")
students := map[string]map[string]interface{}{
"student1": {
"name": "张三",
"age": 20,
"grade": "A",
},
"student2": {
"name": "李四",
"age": 21,
"grade": "B",
},
}
for id, info := range students {
fmt.Printf(" 学生ID: %s\n", id)
for key, value := range info {
fmt.Printf(" %s: %v\n", key, value)
}
}
// 统计映射信息
fmt.Printf(" 统计映射信息:\n")
wordCount := map[string]int{
"go": 10,
"python": 8,
"java": 15,
"rust": 5,
}
totalWords := 0
maxCount := 0
mostPopular := ""
for word, count := range wordCount {
totalWords += count
if count > maxCount {
maxCount = count
mostPopular = word
}
}
fmt.Printf(" 词汇统计: %v\n", wordCount)
fmt.Printf(" 总词数: %d\n", totalWords)
fmt.Printf(" 最受欢迎的词: %s (%d次)\n", mostPopular, maxCount)
// 遍历空映射
fmt.Printf(" 遍历空映射:\n")
emptyMap := make(map[string]int)
count := 0
for range emptyMap {
count++
}
fmt.Printf(" 空映射遍历次数: %d\n", count)
fmt.Println()
}
// demonstrateRangeChannel 演示 range 遍历通道
func demonstrateRangeChannel() {
fmt.Println("4. range 遍历通道 (channel):")
fmt.Printf(" 基本通道遍历:\n")
// 创建一个通道并发送数据
ch := make(chan int, 5)
// 发送数据到通道
for i := 1; i <= 5; i++ {
ch <- i * 10
}
close(ch) // 关闭通道range 才能正常结束
// 使用 range 遍历通道
for value := range ch {
fmt.Printf(" 从通道接收: %d\n", value)
}
// 字符串通道示例
fmt.Printf(" 字符串通道遍历:\n")
strCh := make(chan string, 3)
messages := []string{"Hello", "World", "Go"}
for _, msg := range messages {
strCh <- msg
}
close(strCh)
for message := range strCh {
fmt.Printf(" 消息: %s\n", message)
}
// 注意如果通道没有关闭range 会一直等待
fmt.Printf(" 注意: 通道必须关闭,否则 range 会一直等待\n")
fmt.Println()
}
// demonstrateRangeValueCopy 演示 range 的值拷贝特性
func demonstrateRangeValueCopy() {
fmt.Println("5. range 的值拷贝特性:")
fmt.Printf(" range 会拷贝值,修改拷贝不会影响原始数据:\n")
// 结构体切片示例
type Person struct {
Name string
Age int
}
people := []Person{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35},
}
fmt.Printf(" 原始数据:\n")
for i, person := range people {
fmt.Printf(" people[%d]: %+v\n", i, person)
}
// 尝试修改 range 返回的值(不会影响原始数据)
fmt.Printf(" 尝试修改 range 返回的值:\n")
for i, person := range people {
person.Age += 10 // 这不会修改原始数据
fmt.Printf(" 修改后的拷贝 people[%d]: %+v\n", i, person)
}
fmt.Printf(" 原始数据(未改变):\n")
for i, person := range people {
fmt.Printf(" people[%d]: %+v\n", i, person)
}
// 正确的修改方式:使用索引
fmt.Printf(" 正确的修改方式(使用索引):\n")
for i := range people {
people[i].Age += 5
}
for i, person := range people {
fmt.Printf(" people[%d]: %+v\n", i, person)
}
// 指针切片的情况
fmt.Printf(" 指针切片的情况:\n")
ptrPeople := []*Person{
{"David", 28},
{"Eve", 32},
}
// 通过指针修改(会影响原始数据)
for _, personPtr := range ptrPeople {
personPtr.Age += 2
}
for i, personPtr := range ptrPeople {
fmt.Printf(" ptrPeople[%d]: %+v\n", i, *personPtr)
}
fmt.Println()
}
// demonstrateIgnoreIndexValue 演示忽略索引或值
func demonstrateIgnoreIndexValue() {
fmt.Println("6. 忽略索引或值:")
// 只需要值,忽略索引
fmt.Printf(" 只需要值,忽略索引(使用 _ :\n")
numbers := []int{1, 4, 9, 16, 25}
sum := 0
for _, value := range numbers {
sum += value
}
fmt.Printf(" 数组 %v 的和: %d\n", numbers, sum)
// 只需要索引,忽略值
fmt.Printf(" 只需要索引,忽略值:\n")
items := []string{"apple", "banana", "cherry", "date"}
for index := range items {
fmt.Printf(" 索引 %d\n", index)
}
// 既不需要索引也不需要值(只是计数)
fmt.Printf(" 只计算元素个数:\n")
data := []float64{1.1, 2.2, 3.3, 4.4, 5.5}
count := 0
for range data {
count++
}
fmt.Printf(" 元素个数: %d\n", count)
// 映射中忽略键或值
fmt.Printf(" 映射中忽略键或值:\n")
grades := map[string]int{
"Math": 90,
"English": 85,
"Science": 92,
}
// 只要值
fmt.Printf(" 所有分数: ")
for _, score := range grades {
fmt.Printf("%d ", score)
}
fmt.Printf("\n")
// 只要键
fmt.Printf(" 所有科目: ")
for subject := range grades {
fmt.Printf("%s ", subject)
}
fmt.Printf("\n")
fmt.Println()
}
// demonstratePracticalExamples 演示 range 的实际应用
func demonstratePracticalExamples() {
fmt.Println("7. range 的实际应用:")
// 示例1: 数据统计
fmt.Printf(" 示例1 - 销售数据统计:\n")
sales := map[string][]int{
"Q1": {100, 120, 110, 130},
"Q2": {140, 135, 150, 145},
"Q3": {160, 155, 170, 165},
"Q4": {180, 175, 190, 185},
}
yearTotal := 0
for quarter, monthlySales := range sales {
quarterTotal := 0
for _, monthSale := range monthlySales {
quarterTotal += monthSale
}
yearTotal += quarterTotal
fmt.Printf(" %s 季度总销售额: %d\n", quarter, quarterTotal)
}
fmt.Printf(" 全年总销售额: %d\n", yearTotal)
// 示例2: 配置文件处理
fmt.Printf(" 示例2 - 配置文件处理:\n")
config := map[string]interface{}{
"server_port": 8080,
"debug_mode": true,
"database_url": "localhost:5432",
"max_connections": 100,
"timeout": 30.5,
}
for key, value := range config {
fmt.Printf(" 配置项 %s: ", key)
switch v := value.(type) {
case int:
fmt.Printf("%d (整数)\n", v)
case bool:
fmt.Printf("%t (布尔值)\n", v)
case string:
fmt.Printf("\"%s\" (字符串)\n", v)
case float64:
fmt.Printf("%.1f (浮点数)\n", v)
default:
fmt.Printf("%v (未知类型)\n", v)
}
}
// 示例3: 文本处理
fmt.Printf(" 示例3 - 单词频率统计:\n")
text := "go is great go is simple go is fast"
words := []string{"go", "is", "great", "go", "is", "simple", "go", "is", "fast"}
wordFreq := make(map[string]int)
for _, word := range words {
wordFreq[word]++
}
fmt.Printf(" 文本: \"%s\"\n", text)
fmt.Printf(" 词频统计:\n")
for word, freq := range wordFreq {
fmt.Printf(" \"%s\": %d次\n", word, freq)
}
// 示例4: 数据验证
fmt.Printf(" 示例4 - 用户数据验证:\n")
users := []map[string]string{
{"name": "Alice", "email": "alice@example.com", "age": "25"},
{"name": "", "email": "bob@test.com", "age": "30"},
{"name": "Charlie", "email": "invalid-email", "age": "abc"},
{"name": "David", "email": "david@domain.org", "age": "28"},
}
validUsers := 0
for i, user := range users {
fmt.Printf(" 用户 %d: ", i+1)
isValid := true
// 验证姓名
if user["name"] == "" {
fmt.Printf("姓名为空 ")
isValid = false
}
// 验证邮箱(简单验证)
email := user["email"]
if !contains(email, "@") || !contains(email, ".") {
fmt.Printf("邮箱无效 ")
isValid = false
}
// 验证年龄
age := user["age"]
if !isNumeric(age) {
fmt.Printf("年龄无效 ")
isValid = false
}
if isValid {
fmt.Printf("✓ 有效用户\n")
validUsers++
} else {
fmt.Printf("✗ 无效用户\n")
}
}
fmt.Printf(" 有效用户数: %d/%d\n", validUsers, len(users))
// 示例5: 矩阵操作
fmt.Printf(" 示例5 - 矩阵转置:\n")
matrix := [][]int{
{1, 2, 3},
{4, 5, 6},
}
fmt.Printf(" 原矩阵:\n")
for i, row := range matrix {
fmt.Printf(" 行 %d: %v\n", i, row)
}
// 创建转置矩阵
if len(matrix) > 0 {
transposed := make([][]int, len(matrix[0]))
for i := range transposed {
transposed[i] = make([]int, len(matrix))
}
for i, row := range matrix {
for j, value := range row {
transposed[j][i] = value
}
}
fmt.Printf(" 转置矩阵:\n")
for i, row := range transposed {
fmt.Printf(" 行 %d: %v\n", i, row)
}
}
fmt.Println()
}
// demonstratePerformanceConsiderations 演示 range 的性能考虑
func demonstratePerformanceConsiderations() {
fmt.Println("8. range 的性能考虑:")
// 大切片的遍历
fmt.Printf(" 大切片的遍历性能:\n")
largeSlice := make([]int, 1000)
for i := range largeSlice {
largeSlice[i] = i
}
// 使用 range推荐
sum1 := 0
for _, value := range largeSlice {
sum1 += value
if sum1 > 100 { // 提前退出演示
break
}
}
fmt.Printf(" 使用 range 遍历(推荐): 部分和 = %d\n", sum1)
// 使用传统 for 循环
sum2 := 0
for i := 0; i < len(largeSlice); i++ {
sum2 += largeSlice[i]
if sum2 > 100 {
break
}
}
fmt.Printf(" 使用传统 for 循环: 部分和 = %d\n", sum2)
// 字符串遍历的性能
fmt.Printf(" 字符串遍历的性能考虑:\n")
longString := "这是一个包含中文字符的长字符串,用于演示遍历性能"
// 使用 range处理 Unicode 正确)
charCount1 := 0
for range longString {
charCount1++
}
fmt.Printf(" 使用 range 统计字符数: %d\n", charCount1)
// 使用 len字节数不是字符数
byteCount := len(longString)
fmt.Printf(" 使用 len 统计字节数: %d\n", byteCount)
// 使用 utf8.RuneCountInString正确的字符数
charCount2 := utf8.RuneCountInString(longString)
fmt.Printf(" 使用 utf8.RuneCountInString 统计字符数: %d\n", charCount2)
// 映射遍历的注意事项
fmt.Printf(" 映射遍历的注意事项:\n")
largeMap := make(map[int]string)
for i := 0; i < 10; i++ {
largeMap[i] = fmt.Sprintf("value_%d", i)
}
fmt.Printf(" 映射大小: %d\n", len(largeMap))
fmt.Printf(" 映射遍历顺序是随机的,每次运行可能不同\n")
// 显示前几个元素
count := 0
for key, value := range largeMap {
fmt.Printf(" %d: %s\n", key, value)
count++
if count >= 3 {
fmt.Printf(" ...\n")
break
}
}
fmt.Println()
}
// 辅助函数
func contains(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
func isNumeric(s string) bool {
if len(s) == 0 {
return false
}
for _, char := range s {
if char < '0' || char > '9' {
return false
}
}
return true
}
/*
运行这个程序:
go run 04-range.go
学习要点:
1. range 是 Go 中遍历集合类型的标准方式
2. range 可以用于数组、切片、字符串、映射和通道
3. range 返回索引/键和值,可以用 _ 忽略不需要的部分
4. range 会拷贝值,修改拷贝不会影响原始数据
5. 字符串的 range 遍历按 Unicode 字符,索引是字节位置
range 的语法:
- for index, value := range collection { ... }
- for index := range collection { ... } // 只要索引/键
- for _, value := range collection { ... } // 只要值
- for range collection { ... } // 只计数
不同类型的 range
1. 数组/切片: 返回索引和值
2. 字符串: 返回字节位置和 Unicode 字符
3. 映射: 返回键和值(顺序随机)
4. 通道: 返回接收到的值(通道需要关闭)
性能考虑:
1. range 通常比传统 for 循环更高效和安全
2. 字符串的 range 正确处理 Unicode 字符
3. 大集合的遍历考虑提前退出
4. 映射遍历顺序是随机的
最佳实践:
1. 优先使用 range 遍历集合
2. 使用 _ 忽略不需要的返回值
3. 注意 range 的值拷贝特性
4. 字符串处理时考虑 Unicode 字符
5. 通道遍历前确保通道会被关闭
常见应用场景:
1. 数据处理和统计
2. 配置文件解析
3. 文本分析
4. 数据验证
5. 矩阵操作
6. 集合操作
*/

View File

@@ -0,0 +1,15 @@
# 第二章:控制流程
本章将学习 Go 语言的控制流程语句,包括条件判断、分支选择和循环结构。
## 学习目标
- 掌握条件语句的使用
- 理解 switch 语句的特点
- 学会使用各种形式的 for 循环
- 了解 range 关键字的用法
## 文件列表
- `01-if-else.go` - 条件判断语句
- `02-switch.go` - 分支选择语句
- `03-for-loops.go` - 循环语句
- `04-range.go` - 范围遍历

View File

@@ -0,0 +1,722 @@
/*
01-basic-functions.go - Go 语言基础函数详解
学习目标:
1. 掌握函数的基本语法和定义
2. 理解函数参数和返回值
3. 学会函数的调用方式
4. 了解函数的作用域规则
5. 掌握函数的实际应用
知识点:
- 函数定义语法
- 参数传递(值传递)
- 返回值
- 函数调用
- 函数作为值
- 匿名函数
- 递归函数
- 函数作用域
*/
package main
import (
"fmt"
"math"
"strings"
)
func main() {
fmt.Println("=== Go 语言基础函数详解 ===\n")
// 演示基本函数定义和调用
demonstrateBasicFunctions()
// 演示函数参数
demonstrateFunctionParameters()
// 演示函数返回值
demonstrateFunctionReturns()
// 演示函数作为值
demonstrateFunctionAsValue()
// 演示匿名函数
demonstrateAnonymousFunctions()
// 演示递归函数
demonstrateRecursiveFunctions()
// 演示函数作用域
demonstrateFunctionScope()
// 演示实际应用示例
demonstratePracticalExamples()
}
// demonstrateBasicFunctions 演示基本函数定义和调用
func demonstrateBasicFunctions() {
fmt.Println("1. 基本函数定义和调用:")
// 调用无参数无返回值的函数
fmt.Printf(" 调用无参数无返回值的函数:\n")
sayHello()
// 调用有参数无返回值的函数
fmt.Printf(" 调用有参数无返回值的函数:\n")
greetPerson("Alice")
greetPerson("Bob")
// 调用有参数有返回值的函数
fmt.Printf(" 调用有参数有返回值的函数:\n")
result := add(10, 20)
fmt.Printf(" add(10, 20) = %d\n", result)
// 直接在表达式中使用函数调用
fmt.Printf(" add(5, 7) * 2 = %d\n", add(5, 7)*2)
// 函数调用作为参数
fmt.Printf(" add(add(1, 2), add(3, 4)) = %d\n", add(add(1, 2), add(3, 4)))
fmt.Println()
}
// demonstrateFunctionParameters 演示函数参数
func demonstrateFunctionParameters() {
fmt.Println("2. 函数参数:")
// 单个参数
fmt.Printf(" 单个参数:\n")
square := calculateSquare(5)
fmt.Printf(" calculateSquare(5) = %d\n", square)
// 多个参数
fmt.Printf(" 多个参数:\n")
area := calculateRectangleArea(4, 6)
fmt.Printf(" calculateRectangleArea(4, 6) = %d\n", area)
// 相同类型的多个参数
fmt.Printf(" 相同类型的多个参数:\n")
max := findMax(15, 8, 23, 4, 19)
fmt.Printf(" findMax(15, 8, 23, 4, 19) = %d\n", max)
// 不同类型的参数
fmt.Printf(" 不同类型的参数:\n")
info := formatPersonInfo("Charlie", 25, 175.5)
fmt.Printf(" %s\n", info)
// 参数是值传递
fmt.Printf(" 参数是值传递(不会修改原变量):\n")
x := 10
fmt.Printf(" 修改前: x = %d\n", x)
tryToModify(x)
fmt.Printf(" 修改后: x = %d (未改变)\n", x)
// 传递切片(引用类型)
fmt.Printf(" 传递切片(引用类型):\n")
numbers := []int{1, 2, 3, 4, 5}
fmt.Printf(" 修改前: %v\n", numbers)
modifySlice(numbers)
fmt.Printf(" 修改后: %v (已改变)\n", numbers)
fmt.Println()
}
// demonstrateFunctionReturns 演示函数返回值
func demonstrateFunctionReturns() {
fmt.Println("3. 函数返回值:")
// 单个返回值
fmt.Printf(" 单个返回值:\n")
length := getStringLength("Hello, World!")
fmt.Printf(" 字符串长度: %d\n", length)
// 多个返回值
fmt.Printf(" 多个返回值:\n")
quotient, remainder := divide(17, 5)
fmt.Printf(" 17 ÷ 5 = %d 余 %d\n", quotient, remainder)
// 命名返回值
fmt.Printf(" 命名返回值:\n")
min, max := findMinMax([]int{3, 7, 1, 9, 4, 6})
fmt.Printf(" 数组 [3, 7, 1, 9, 4, 6] 的最小值: %d, 最大值: %d\n", min, max)
// 忽略某些返回值
fmt.Printf(" 忽略某些返回值:\n")
_, rem := divide(20, 3)
fmt.Printf(" 20 ÷ 3 的余数: %d\n", rem)
// 返回函数
fmt.Printf(" 返回函数:\n")
multiplier := getMultiplier(3)
result := multiplier(10)
fmt.Printf(" 3倍数函数应用于10: %d\n", result)
fmt.Println()
}
// demonstrateFunctionAsValue 演示函数作为值
func demonstrateFunctionAsValue() {
fmt.Println("4. 函数作为值:")
// 将函数赋值给变量
fmt.Printf(" 将函数赋值给变量:\n")
var operation func(int, int) int
operation = add
fmt.Printf(" operation = add; operation(5, 3) = %d\n", operation(5, 3))
operation = multiply
fmt.Printf(" operation = multiply; operation(5, 3) = %d\n", operation(5, 3))
// 函数作为参数
fmt.Printf(" 函数作为参数:\n")
numbers := []int{1, 2, 3, 4, 5}
result1 := applyOperation(numbers, double)
fmt.Printf(" 应用 double 函数: %v -> %v\n", numbers, result1)
result2 := applyOperation(numbers, square)
fmt.Printf(" 应用 square 函数: %v -> %v\n", numbers, result2)
// 函数切片
fmt.Printf(" 函数切片:\n")
operations := []func(int, int) int{add, subtract, multiply}
operationNames := []string{"加法", "减法", "乘法"}
a, b := 12, 4
for i, op := range operations {
result := op(a, b)
fmt.Printf(" %s: %d %s %d = %d\n", operationNames[i], a, getOperatorSymbol(i), b, result)
}
fmt.Println()
}
// demonstrateAnonymousFunctions 演示匿名函数
func demonstrateAnonymousFunctions() {
fmt.Println("5. 匿名函数:")
// 基本匿名函数
fmt.Printf(" 基本匿名函数:\n")
result := func(x, y int) int {
return x*x + y*y
}(3, 4)
fmt.Printf(" 匿名函数计算 3² + 4² = %d\n", result)
// 将匿名函数赋值给变量
fmt.Printf(" 将匿名函数赋值给变量:\n")
isEven := func(n int) bool {
return n%2 == 0
}
for i := 1; i <= 5; i++ {
fmt.Printf(" %d 是偶数: %t\n", i, isEven(i))
}
// 匿名函数作为参数
fmt.Printf(" 匿名函数作为参数:\n")
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evenNumbers := filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Printf(" 偶数: %v\n", evenNumbers)
largeNumbers := filter(numbers, func(n int) bool {
return n > 5
})
fmt.Printf(" 大于5的数: %v\n", largeNumbers)
// 匿名函数闭包
fmt.Printf(" 匿名函数闭包:\n")
counter := func() func() int {
count := 0
return func() int {
count++
return count
}
}()
fmt.Printf(" 计数器调用1: %d\n", counter())
fmt.Printf(" 计数器调用2: %d\n", counter())
fmt.Printf(" 计数器调用3: %d\n", counter())
fmt.Println()
}
// demonstrateRecursiveFunctions 演示递归函数
func demonstrateRecursiveFunctions() {
fmt.Println("6. 递归函数:")
// 阶乘函数
fmt.Printf(" 阶乘函数:\n")
for i := 0; i <= 5; i++ {
fact := factorial(i)
fmt.Printf(" %d! = %d\n", i, fact)
}
// 斐波那契数列
fmt.Printf(" 斐波那契数列:\n")
fmt.Printf(" 前10个斐波那契数: ")
for i := 0; i < 10; i++ {
fmt.Printf("%d ", fibonacci(i))
}
fmt.Printf("\n")
// 二分查找
fmt.Printf(" 二分查找:\n")
sortedArray := []int{1, 3, 5, 7, 9, 11, 13, 15, 17, 19}
target := 7
index := binarySearch(sortedArray, target, 0, len(sortedArray)-1)
if index != -1 {
fmt.Printf(" 在数组 %v 中找到 %d索引: %d\n", sortedArray, target, index)
} else {
fmt.Printf(" 在数组 %v 中未找到 %d\n", sortedArray, target)
}
// 计算数字各位数之和
fmt.Printf(" 计算数字各位数之和:\n")
number := 12345
digitSum := sumOfDigits(number)
fmt.Printf(" %d 的各位数之和: %d\n", number, digitSum)
fmt.Println()
}
// demonstrateFunctionScope 演示函数作用域
func demonstrateFunctionScope() {
fmt.Println("7. 函数作用域:")
// 全局变量
fmt.Printf(" 全局变量: globalVar = %s\n", globalVar)
// 局部变量
fmt.Printf(" 局部变量:\n")
localVar := "这是局部变量"
fmt.Printf(" localVar = %s\n", localVar)
// 函数内部的作用域
fmt.Printf(" 函数内部的作用域:\n")
testScope()
// 参数作用域
fmt.Printf(" 参数作用域:\n")
testParameterScope("参数值")
// 变量遮蔽
fmt.Printf(" 变量遮蔽:\n")
testVariableShadowing()
fmt.Println()
}
// demonstratePracticalExamples 演示实际应用示例
func demonstratePracticalExamples() {
fmt.Println("8. 实际应用示例:")
// 示例1: 数据处理函数
fmt.Printf(" 示例1 - 学生成绩处理:\n")
scores := []int{85, 92, 78, 96, 88, 73, 91, 87}
avg := calculateAverage(scores)
fmt.Printf(" 平均分: %.2f\n", avg)
grade := getLetterGrade(avg)
fmt.Printf(" 等级: %s\n", grade)
passCount := countPassingScores(scores, 80)
fmt.Printf(" 80分以上人数: %d/%d\n", passCount, len(scores))
// 示例2: 字符串处理函数
fmt.Printf(" 示例2 - 文本处理:\n")
text := "Hello, World! This is a test."
wordCount := countWords(text)
fmt.Printf(" 文本: \"%s\"\n", text)
fmt.Printf(" 单词数: %d\n", wordCount)
reversed := reverseString(text)
fmt.Printf(" 反转: \"%s\"\n", reversed)
isPalindrome := checkPalindrome("racecar")
fmt.Printf(" \"racecar\" 是回文: %t\n", isPalindrome)
// 示例3: 数学计算函数
fmt.Printf(" 示例3 - 几何计算:\n")
circleArea := calculateCircleArea(5.0)
fmt.Printf(" 半径5的圆面积: %.2f\n", circleArea)
triangleArea := calculateTriangleArea(3.0, 4.0, 5.0)
fmt.Printf(" 边长3,4,5的三角形面积: %.2f\n", triangleArea)
distance := calculateDistance(0, 0, 3, 4)
fmt.Printf(" 点(0,0)到点(3,4)的距离: %.2f\n", distance)
// 示例4: 数据验证函数
fmt.Printf(" 示例4 - 数据验证:\n")
emails := []string{
"user@example.com",
"invalid-email",
"test@domain.org",
}
for _, email := range emails {
isValid := validateEmail(email)
fmt.Printf(" 邮箱 \"%s\" 有效: %t\n", email, isValid)
}
phone := "138-1234-5678"
isValidPhone := validatePhoneNumber(phone)
fmt.Printf(" 电话 \"%s\" 有效: %t\n", phone, isValidPhone)
fmt.Println()
}
// ========== 函数定义 ==========
// 全局变量
var globalVar = "全局变量"
// 无参数无返回值的函数
func sayHello() {
fmt.Printf(" Hello, World!\n")
}
// 有参数无返回值的函数
func greetPerson(name string) {
fmt.Printf(" Hello, %s!\n", name)
}
// 有参数有返回值的函数
func add(a, b int) int {
return a + b
}
// 单个参数函数
func calculateSquare(n int) int {
return n * n
}
// 多个参数函数
func calculateRectangleArea(width, height int) int {
return width * height
}
// 相同类型多个参数函数
func findMax(numbers ...int) int {
if len(numbers) == 0 {
return 0
}
max := numbers[0]
for _, num := range numbers {
if num > max {
max = num
}
}
return max
}
// 不同类型参数函数
func formatPersonInfo(name string, age int, height float64) string {
return fmt.Sprintf("姓名: %s, 年龄: %d, 身高: %.1fcm", name, age, height)
}
// 尝试修改参数(值传递)
func tryToModify(x int) {
x = 100
fmt.Printf(" 函数内部: x = %d\n", x)
}
// 修改切片
func modifySlice(slice []int) {
if len(slice) > 0 {
slice[0] = 999
}
}
// 单个返回值函数
func getStringLength(s string) int {
return len(s)
}
// 多个返回值函数
func divide(a, b int) (int, int) {
return a / b, a % b
}
// 命名返回值函数
func findMinMax(numbers []int) (min, max int) {
if len(numbers) == 0 {
return 0, 0
}
min, max = numbers[0], numbers[0]
for _, num := range numbers {
if num < min {
min = num
}
if num > max {
max = num
}
}
return // 自动返回命名的返回值
}
// 返回函数的函数
func getMultiplier(factor int) func(int) int {
return func(x int) int {
return x * factor
}
}
// 基本运算函数
func multiply(a, b int) int {
return a * b
}
func subtract(a, b int) int {
return a - b
}
// 应用操作函数
func applyOperation(numbers []int, operation func(int) int) []int {
result := make([]int, len(numbers))
for i, num := range numbers {
result[i] = operation(num)
}
return result
}
// 操作函数
func double(x int) int {
return x * 2
}
func square(x int) int {
return x * x
}
// 获取运算符符号
func getOperatorSymbol(index int) string {
symbols := []string{"+", "-", "×"}
if index < len(symbols) {
return symbols[index]
}
return "?"
}
// 过滤函数
func filter(numbers []int, predicate func(int) bool) []int {
var result []int
for _, num := range numbers {
if predicate(num) {
result = append(result, num)
}
}
return result
}
// 递归函数:阶乘
func factorial(n int) int {
if n <= 1 {
return 1
}
return n * factorial(n-1)
}
// 递归函数:斐波那契
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
// 递归函数:二分查找
func binarySearch(arr []int, target, left, right int) int {
if left > right {
return -1
}
mid := (left + right) / 2
if arr[mid] == target {
return mid
} else if arr[mid] > target {
return binarySearch(arr, target, left, mid-1)
} else {
return binarySearch(arr, target, mid+1, right)
}
}
// 递归函数:数字各位数之和
func sumOfDigits(n int) int {
if n < 10 {
return n
}
return n%10 + sumOfDigits(n/10)
}
// 作用域测试函数
func testScope() {
innerVar := "函数内部变量"
fmt.Printf(" innerVar = %s\n", innerVar)
if true {
blockVar := "块级变量"
fmt.Printf(" blockVar = %s\n", blockVar)
}
// blockVar 在这里不可访问
}
func testParameterScope(param string) {
fmt.Printf(" 参数 param = %s\n", param)
param = "修改后的参数"
fmt.Printf(" 修改后 param = %s\n", param)
}
func testVariableShadowing() {
x := "外层变量"
fmt.Printf(" 外层 x = %s\n", x)
if true {
x := "内层变量" // 遮蔽外层变量
fmt.Printf(" 内层 x = %s\n", x)
}
fmt.Printf(" 外层 x = %s (未被修改)\n", x)
}
// 实际应用函数
func calculateAverage(scores []int) float64 {
if len(scores) == 0 {
return 0
}
sum := 0
for _, score := range scores {
sum += score
}
return float64(sum) / float64(len(scores))
}
func getLetterGrade(average float64) string {
switch {
case average >= 90:
return "A"
case average >= 80:
return "B"
case average >= 70:
return "C"
case average >= 60:
return "D"
default:
return "F"
}
}
func countPassingScores(scores []int, threshold int) int {
count := 0
for _, score := range scores {
if score >= threshold {
count++
}
}
return count
}
func countWords(text string) int {
words := strings.Fields(text)
return len(words)
}
func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func checkPalindrome(s string) bool {
s = strings.ToLower(s)
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
if s[i] != s[j] {
return false
}
}
return true
}
func calculateCircleArea(radius float64) float64 {
return math.Pi * radius * radius
}
func calculateTriangleArea(a, b, c float64) float64 {
// 使用海伦公式
s := (a + b + c) / 2
return math.Sqrt(s * (s - a) * (s - b) * (s - c))
}
func calculateDistance(x1, y1, x2, y2 float64) float64 {
dx := x2 - x1
dy := y2 - y1
return math.Sqrt(dx*dx + dy*dy)
}
func validateEmail(email string) bool {
return strings.Contains(email, "@") && strings.Contains(email, ".")
}
func validatePhoneNumber(phone string) bool {
// 简单验证:包含数字和连字符
return strings.Contains(phone, "-") && len(phone) >= 10
}
/*
运行这个程序:
go run 01-basic-functions.go
学习要点:
1. 函数是 Go 程序的基本构建块
2. 函数定义语法func 函数名(参数列表) 返回类型 { 函数体 }
3. Go 支持多返回值,这是其特色功能之一
4. 参数传递是值传递,但引用类型(切片、映射等)传递的是引用
5. 函数可以作为值传递和赋值
6. 支持匿名函数和闭包
7. 递归函数需要有明确的终止条件
函数的组成部分:
1. func 关键字
2. 函数名
3. 参数列表(可选)
4. 返回类型(可选)
5. 函数体
函数特性:
1. 支持多返回值
2. 支持命名返回值
3. 函数是一等公民(可以作为值)
4. 支持匿名函数和闭包
5. 支持递归调用
最佳实践:
1. 函数名应该清晰表达功能
2. 保持函数简短和专注
3. 合理使用多返回值
4. 适当使用命名返回值提高可读性
5. 避免过深的递归调用
6. 考虑函数的副作用
常见应用场景:
1. 代码复用和模块化
2. 数据处理和计算
3. 输入验证和格式化
4. 算法实现
5. 业务逻辑封装
6. 工具函数库
*/

View File

@@ -0,0 +1,774 @@
/*
02-multiple-returns.go - Go 语言多返回值详解
学习目标:
1. 掌握多返回值的语法和用法
2. 理解命名返回值的优势
3. 学会错误处理的惯用模式
4. 了解多返回值的实际应用场景
5. 掌握返回值的最佳实践
知识点:
- 多返回值语法
- 命名返回值
- 错误处理模式
- 返回值解构
- 忽略返回值
- 多返回值的性能考虑
- 实际应用场景
*/
package main
import (
"errors"
"fmt"
"math"
"strconv"
"strings"
"time"
)
func main() {
fmt.Println("=== Go 语言多返回值详解 ===\n")
// 演示基本多返回值
demonstrateBasicMultipleReturns()
// 演示命名返回值
demonstrateNamedReturns()
// 演示错误处理模式
demonstrateErrorHandling()
// 演示返回值解构和忽略
demonstrateReturnValueHandling()
// 演示多返回值的实际应用
demonstratePracticalApplications()
// 演示多返回值的高级用法
demonstrateAdvancedUsage()
// 演示性能考虑
demonstratePerformanceConsiderations()
}
// demonstrateBasicMultipleReturns 演示基本多返回值
func demonstrateBasicMultipleReturns() {
fmt.Println("1. 基本多返回值:")
// 两个返回值
fmt.Printf(" 两个返回值:\n")
quotient, remainder := divmod(17, 5)
fmt.Printf(" 17 ÷ 5 = %d 余 %d\n", quotient, remainder)
// 三个返回值
fmt.Printf(" 三个返回值:\n")
min, max, avg := analyzeNumbers([]int{3, 7, 1, 9, 4, 6})
fmt.Printf(" 数组 [3, 7, 1, 9, 4, 6] - 最小值: %d, 最大值: %d, 平均值: %.2f\n", min, max, avg)
// 不同类型的返回值
fmt.Printf(" 不同类型的返回值:\n")
name, age, height, isStudent := getPersonInfo()
fmt.Printf(" 个人信息 - 姓名: %s, 年龄: %d, 身高: %.1fcm, 学生: %t\n",
name, age, height, isStudent)
// 返回值和错误
fmt.Printf(" 返回值和错误:\n")
result, err := safeDivide(10, 2)
if err != nil {
fmt.Printf(" 错误: %v\n", err)
} else {
fmt.Printf(" 10 ÷ 2 = %.2f\n", result)
}
result, err = safeDivide(10, 0)
if err != nil {
fmt.Printf(" 错误: %v\n", err)
} else {
fmt.Printf(" 10 ÷ 0 = %.2f\n", result)
}
fmt.Println()
}
// demonstrateNamedReturns 演示命名返回值
func demonstrateNamedReturns() {
fmt.Println("2. 命名返回值:")
// 基本命名返回值
fmt.Printf(" 基本命名返回值:\n")
area, perimeter := calculateRectangle(5, 3)
fmt.Printf(" 矩形 5×3 - 面积: %d, 周长: %d\n", area, perimeter)
// 命名返回值的提前返回
fmt.Printf(" 命名返回值的提前返回:\n")
score, grade, pass := evaluateScore(85)
fmt.Printf(" 分数 85 - 等级: %s, 是否及格: %t\n", grade, pass)
score, grade, pass = evaluateScore(45)
fmt.Printf(" 分数 45 - 等级: %s, 是否及格: %t\n", grade, pass)
// 复杂的命名返回值
fmt.Printf(" 复杂的命名返回值:\n")
valid, reason, suggestions := validatePassword("123")
fmt.Printf(" 密码 \"123\" - 有效: %t, 原因: %s\n", valid, reason)
if len(suggestions) > 0 {
fmt.Printf(" 建议: %v\n", suggestions)
}
valid, reason, suggestions = validatePassword("SecurePass123!")
fmt.Printf(" 密码 \"SecurePass123!\" - 有效: %t, 原因: %s\n", valid, reason)
fmt.Println()
}
// demonstrateErrorHandling 演示错误处理模式
func demonstrateErrorHandling() {
fmt.Println("3. 错误处理模式:")
// 标准错误处理模式
fmt.Printf(" 标准错误处理模式:\n")
// 字符串转整数
value, err := parseInteger("123")
if err != nil {
fmt.Printf(" 解析错误: %v\n", err)
} else {
fmt.Printf(" 解析成功: %d\n", value)
}
value, err = parseInteger("abc")
if err != nil {
fmt.Printf(" 解析错误: %v\n", err)
} else {
fmt.Printf(" 解析成功: %d\n", value)
}
// 文件操作模拟
fmt.Printf(" 文件操作模拟:\n")
content, err := readFile("config.txt")
if err != nil {
fmt.Printf(" 读取文件错误: %v\n", err)
} else {
fmt.Printf(" 文件内容: %s\n", content)
}
// 网络请求模拟
fmt.Printf(" 网络请求模拟:\n")
data, statusCode, err := httpGet("https://api.example.com/users")
if err != nil {
fmt.Printf(" 请求错误: %v\n", err)
} else {
fmt.Printf(" 状态码: %d, 数据长度: %d\n", statusCode, len(data))
}
// 多层错误处理
fmt.Printf(" 多层错误处理:\n")
result, err := processUserData("user123")
if err != nil {
fmt.Printf(" 处理用户数据错误: %v\n", err)
} else {
fmt.Printf(" 处理结果: %s\n", result)
}
fmt.Println()
}
// demonstrateReturnValueHandling 演示返回值解构和忽略
func demonstrateReturnValueHandling() {
fmt.Println("4. 返回值解构和忽略:")
// 接收所有返回值
fmt.Printf(" 接收所有返回值:\n")
x, y, z := getCoordinates()
fmt.Printf(" 坐标: (%d, %d, %d)\n", x, y, z)
// 忽略某些返回值
fmt.Printf(" 忽略某些返回值:\n")
_, _, avgZ := getCoordinates()
fmt.Printf(" 只关心 Z 坐标: %d\n", avgZ)
// 只检查错误
fmt.Printf(" 只检查错误:\n")
_, err := safeDivide(10, 2)
if err != nil {
fmt.Printf(" 操作失败: %v\n", err)
} else {
fmt.Printf(" 操作成功\n")
}
// 链式调用
fmt.Printf(" 链式调用:\n")
result, err := processChain("input")
if err != nil {
fmt.Printf(" 链式处理错误: %v\n", err)
} else {
fmt.Printf(" 链式处理结果: %s\n", result)
}
// 多重赋值
fmt.Printf(" 多重赋值:\n")
a, b := 10, 20
fmt.Printf(" 交换前: a=%d, b=%d\n", a, b)
a, b = swap(a, b)
fmt.Printf(" 交换后: a=%d, b=%d\n", a, b)
fmt.Println()
}
// demonstratePracticalApplications 演示多返回值的实际应用
func demonstratePracticalApplications() {
fmt.Println("5. 多返回值的实际应用:")
// 应用1: 数据库查询模拟
fmt.Printf(" 应用1 - 数据库查询模拟:\n")
user, found, err := findUserByID(123)
if err != nil {
fmt.Printf(" 查询错误: %v\n", err)
} else if !found {
fmt.Printf(" 用户不存在\n")
} else {
fmt.Printf(" 找到用户: %+v\n", user)
}
// 应用2: 缓存操作
fmt.Printf(" 应用2 - 缓存操作:\n")
value, hit, err := getFromCache("user:123")
if err != nil {
fmt.Printf(" 缓存错误: %v\n", err)
} else if hit {
fmt.Printf(" 缓存命中: %s\n", value)
} else {
fmt.Printf(" 缓存未命中\n")
}
// 应用3: 配置解析
fmt.Printf(" 应用3 - 配置解析:\n")
config, warnings, err := parseConfig("app.conf")
if err != nil {
fmt.Printf(" 配置解析错误: %v\n", err)
} else {
fmt.Printf(" 配置加载成功: %+v\n", config)
if len(warnings) > 0 {
fmt.Printf(" 警告: %v\n", warnings)
}
}
// 应用4: 数据验证
fmt.Printf(" 应用4 - 数据验证:\n")
userData := map[string]string{
"name": "Alice",
"email": "alice@example.com",
"age": "25",
}
valid, errors := validateUserData(userData)
fmt.Printf(" 用户数据验证 - 有效: %t\n", valid)
if len(errors) > 0 {
fmt.Printf(" 验证错误: %v\n", errors)
}
// 应用5: 统计分析
fmt.Printf(" 应用5 - 统计分析:\n")
data := []float64{1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0}
mean, median, stddev := calculateStatistics(data)
fmt.Printf(" 数据: %v\n", data)
fmt.Printf(" 统计结果 - 平均值: %.2f, 中位数: %.2f, 标准差: %.2f\n",
mean, median, stddev)
fmt.Println()
}
// demonstrateAdvancedUsage 演示多返回值的高级用法
func demonstrateAdvancedUsage() {
fmt.Println("6. 多返回值的高级用法:")
// 返回函数
fmt.Printf(" 返回函数:\n")
add, multiply := getMathOperations()
fmt.Printf(" add(5, 3) = %d\n", add(5, 3))
fmt.Printf(" multiply(5, 3) = %d\n", multiply(5, 3))
// 返回接口
fmt.Printf(" 返回接口:\n")
reader, writer := getIOOperations()
data := []byte("Hello, World!")
n, err := writer.Write(data)
if err != nil {
fmt.Printf(" 写入错误: %v\n", err)
} else {
fmt.Printf(" 写入 %d 字节\n", n)
}
buffer := make([]byte, 13)
n, err = reader.Read(buffer)
if err != nil {
fmt.Printf(" 读取错误: %v\n", err)
} else {
fmt.Printf(" 读取 %d 字节: %s\n", n, string(buffer[:n]))
}
// 返回通道
fmt.Printf(" 返回通道:\n")
input, output := createPipeline()
// 发送数据
go func() {
for i := 1; i <= 3; i++ {
input <- i
}
close(input)
}()
// 接收处理后的数据
for result := range output {
fmt.Printf(" 处理结果: %d\n", result)
}
fmt.Println()
}
// demonstratePerformanceConsiderations 演示性能考虑
func demonstratePerformanceConsiderations() {
fmt.Println("7. 性能考虑:")
// 返回值的内存分配
fmt.Printf(" 返回值的内存分配:\n")
// 返回值拷贝 vs 返回指针
largeData := make([]int, 1000)
for i := range largeData {
largeData[i] = i
}
// 返回拷贝(可能影响性能)
copied, size := copyLargeData(largeData)
fmt.Printf(" 返回拷贝 - 大小: %d, 第一个元素: %d\n", size, copied[0])
// 返回指针(更高效)
ptr, size := referenceLargeData(largeData)
fmt.Printf(" 返回指针 - 大小: %d, 第一个元素: %d\n", size, (*ptr)[0])
// 多返回值 vs 结构体
fmt.Printf(" 多返回值 vs 结构体:\n")
// 使用多返回值
name, age, email := getUserInfo1()
fmt.Printf(" 多返回值: %s, %d, %s\n", name, age, email)
// 使用结构体
user := getUserInfo2()
fmt.Printf(" 结构体: %s, %d, %s\n", user.Name, user.Age, user.Email)
// 错误处理的性能
fmt.Printf(" 错误处理的性能:\n")
// 正常情况
start := time.Now()
for i := 0; i < 1000; i++ {
_, err := fastOperation(i)
if err != nil {
// 处理错误
}
}
duration := time.Since(start)
fmt.Printf(" 1000次正常操作耗时: %v\n", duration)
fmt.Println()
}
// ========== 函数定义 ==========
// 基本多返回值函数
func divmod(a, b int) (int, int) {
return a / b, a % b
}
func analyzeNumbers(numbers []int) (int, int, float64) {
if len(numbers) == 0 {
return 0, 0, 0
}
min, max := numbers[0], numbers[0]
sum := 0
for _, num := range numbers {
if num < min {
min = num
}
if num > max {
max = num
}
sum += num
}
avg := float64(sum) / float64(len(numbers))
return min, max, avg
}
func getPersonInfo() (string, int, float64, bool) {
return "Alice", 25, 165.5, true
}
func safeDivide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除数不能为零")
}
return a / b, nil
}
// 命名返回值函数
func calculateRectangle(width, height int) (area, perimeter int) {
area = width * height
perimeter = 2 * (width + height)
return // 自动返回命名的返回值
}
func evaluateScore(score int) (originalScore int, grade string, pass bool) {
originalScore = score
if score < 0 || score > 100 {
grade = "无效"
return // 提前返回
}
switch {
case score >= 90:
grade = "A"
case score >= 80:
grade = "B"
case score >= 70:
grade = "C"
case score >= 60:
grade = "D"
default:
grade = "F"
}
pass = score >= 60
return
}
func validatePassword(password string) (valid bool, reason string, suggestions []string) {
if len(password) < 8 {
reason = "密码长度不足8位"
suggestions = append(suggestions, "增加密码长度")
return
}
hasUpper := strings.ContainsAny(password, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
hasLower := strings.ContainsAny(password, "abcdefghijklmnopqrstuvwxyz")
hasDigit := strings.ContainsAny(password, "0123456789")
hasSpecial := strings.ContainsAny(password, "!@#$%^&*")
if !hasUpper {
suggestions = append(suggestions, "添加大写字母")
}
if !hasLower {
suggestions = append(suggestions, "添加小写字母")
}
if !hasDigit {
suggestions = append(suggestions, "添加数字")
}
if !hasSpecial {
suggestions = append(suggestions, "添加特殊字符")
}
if hasUpper && hasLower && hasDigit && hasSpecial {
valid = true
reason = "密码强度良好"
} else {
reason = "密码强度不足"
}
return
}
// 错误处理函数
func parseInteger(s string) (int, error) {
value, err := strconv.Atoi(s)
if err != nil {
return 0, fmt.Errorf("无法解析整数 '%s': %w", s, err)
}
return value, nil
}
func readFile(filename string) (string, error) {
// 模拟文件读取
if filename == "config.txt" {
return "server_port=8080\ndebug=true", nil
}
return "", fmt.Errorf("文件 '%s' 不存在", filename)
}
func httpGet(url string) ([]byte, int, error) {
// 模拟HTTP请求
if strings.Contains(url, "example.com") {
return []byte(`{"users": [{"id": 1, "name": "Alice"}]}`), 200, nil
}
return nil, 0, errors.New("网络连接失败")
}
func processUserData(userID string) (string, error) {
// 模拟多层处理
if userID == "" {
return "", errors.New("用户ID不能为空")
}
// 模拟数据库查询
if userID == "user123" {
return "用户数据处理完成", nil
}
return "", fmt.Errorf("用户 '%s' 不存在", userID)
}
// 返回值处理函数
func getCoordinates() (int, int, int) {
return 10, 20, 30
}
func processChain(input string) (string, error) {
if input == "" {
return "", errors.New("输入不能为空")
}
// 模拟处理链
step1 := strings.ToUpper(input)
step2 := step1 + "_PROCESSED"
return step2, nil
}
func swap(a, b int) (int, int) {
return b, a
}
// 实际应用函数
type User struct {
ID int
Name string
Email string
}
func findUserByID(id int) (User, bool, error) {
// 模拟数据库查询
if id <= 0 {
return User{}, false, errors.New("无效的用户ID")
}
if id == 123 {
return User{ID: 123, Name: "Alice", Email: "alice@example.com"}, true, nil
}
return User{}, false, nil
}
func getFromCache(key string) (string, bool, error) {
// 模拟缓存操作
cache := map[string]string{
"user:123": "Alice",
"user:456": "Bob",
}
if value, exists := cache[key]; exists {
return value, true, nil
}
return "", false, nil
}
type Config struct {
Port int
Debug bool
Timeout int
}
func parseConfig(filename string) (Config, []string, error) {
// 模拟配置解析
config := Config{Port: 8080, Debug: true, Timeout: 30}
warnings := []string{"使用默认超时值"}
if filename == "app.conf" {
return config, warnings, nil
}
return Config{}, nil, fmt.Errorf("配置文件 '%s' 不存在", filename)
}
func validateUserData(data map[string]string) (bool, []string) {
var errors []string
if name := data["name"]; name == "" {
errors = append(errors, "姓名不能为空")
}
if email := data["email"]; !strings.Contains(email, "@") {
errors = append(errors, "邮箱格式无效")
}
if ageStr := data["age"]; ageStr != "" {
if age, err := strconv.Atoi(ageStr); err != nil || age < 0 || age > 150 {
errors = append(errors, "年龄无效")
}
}
return len(errors) == 0, errors
}
func calculateStatistics(data []float64) (mean, median, stddev float64) {
if len(data) == 0 {
return 0, 0, 0
}
// 计算平均值
sum := 0.0
for _, v := range data {
sum += v
}
mean = sum / float64(len(data))
// 计算中位数(简化版)
median = data[len(data)/2]
// 计算标准差
variance := 0.0
for _, v := range data {
variance += (v - mean) * (v - mean)
}
stddev = math.Sqrt(variance / float64(len(data)))
return
}
// 高级用法函数
func getMathOperations() (func(int, int) int, func(int, int) int) {
add := func(a, b int) int { return a + b }
multiply := func(a, b int) int { return a * b }
return add, multiply
}
type MockReader struct {
data []byte
pos int
}
func (r *MockReader) Read(p []byte) (n int, error) {
if r.pos >= len(r.data) {
return 0, errors.New("EOF")
}
n = copy(p, r.data[r.pos:])
r.pos += n
return n, nil
}
type MockWriter struct {
data []byte
}
func (w *MockWriter) Write(p []byte) (n int, error) {
w.data = append(w.data, p...)
return len(p), nil
}
func getIOOperations() (*MockReader, *MockWriter) {
reader := &MockReader{data: []byte("Hello, World!")}
writer := &MockWriter{}
return reader, writer
}
func createPipeline() (chan<- int, <-chan int) {
input := make(chan int)
output := make(chan int)
go func() {
defer close(output)
for value := range input {
output <- value * 2 // 处理数据
}
}()
return input, output
}
// 性能考虑函数
func copyLargeData(data []int) ([]int, int) {
copied := make([]int, len(data))
copy(copied, data)
return copied, len(copied)
}
func referenceLargeData(data []int) (*[]int, int) {
return &data, len(data)
}
func getUserInfo1() (string, int, string) {
return "Alice", 25, "alice@example.com"
}
type UserInfo struct {
Name string
Age int
Email string
}
func getUserInfo2() UserInfo {
return UserInfo{Name: "Alice", Age: 25, Email: "alice@example.com"}
}
func fastOperation(n int) (int, error) {
if n < 0 {
return 0, errors.New("负数")
}
return n * 2, nil
}
/*
运行这个程序:
go run 02-multiple-returns.go
学习要点:
1. Go 支持多返回值,这是其独特且强大的特性
2. 多返回值常用于返回结果和错误信息
3. 命名返回值可以提高代码可读性,支持提前返回
4. 可以使用 _ 忽略不需要的返回值
5. 多返回值是 Go 错误处理的基础
多返回值的优势:
1. 避免使用指针参数传递多个结果
2. 使错误处理更加明确和一致
3. 提高代码的可读性和维护性
4. 支持函数式编程风格
常见模式:
1. (result, error) - 标准错误处理模式
2. (value, ok) - 检查操作是否成功
3. (value, found, error) - 查询操作模式
4. 命名返回值 - 提高可读性
最佳实践:
1. 错误通常作为最后一个返回值
2. 使用命名返回值提高复杂函数的可读性
3. 适当使用 _ 忽略不需要的返回值
4. 保持返回值数量合理通常不超过3-4个
5. 考虑使用结构体替代过多的返回值
性能考虑:
1. 多返回值通常比传递指针参数更高效
2. 大对象考虑返回指针而不是值拷贝
3. 命名返回值可能有轻微的性能开销
4. 错误处理的性能影响通常可以忽略
应用场景:
1. 错误处理
2. 数据库查询
3. 网络操作
4. 文件操作
5. 数据验证
6. 统计计算
7. 缓存操作
*/

View File

@@ -0,0 +1,757 @@
/*
03-variadic-functions.go - Go 语言可变参数函数详解
学习目标:
1. 掌握可变参数函数的语法
2. 理解可变参数的传递机制
3. 学会可变参数的实际应用
4. 了解可变参数的限制和注意事项
5. 掌握可变参数的最佳实践
知识点:
- 可变参数语法 (...type)
- 可变参数的传递和展开
- 空参数和单参数处理
- 可变参数与切片的关系
- 可变参数的类型限制
- 实际应用场景
*/
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("=== Go 语言可变参数函数详解 ===\n")
// 演示基本可变参数函数
demonstrateBasicVariadicFunctions()
// 演示可变参数的传递
demonstrateVariadicParameterPassing()
// 演示可变参数与其他参数的组合
demonstrateVariadicWithOtherParams()
// 演示可变参数的类型处理
demonstrateVariadicTypeHandling()
// 演示可变参数的实际应用
demonstratePracticalApplications()
// 演示可变参数的高级用法
demonstrateAdvancedVariadicUsage()
// 演示可变参数的限制和注意事项
demonstrateVariadicLimitations()
}
// demonstrateBasicVariadicFunctions 演示基本可变参数函数
func demonstrateBasicVariadicFunctions() {
fmt.Println("1. 基本可变参数函数:")
// 数字求和
fmt.Printf(" 数字求和:\n")
fmt.Printf(" sum() = %d\n", sum())
fmt.Printf(" sum(1) = %d\n", sum(1))
fmt.Printf(" sum(1, 2, 3) = %d\n", sum(1, 2, 3))
fmt.Printf(" sum(1, 2, 3, 4, 5) = %d\n", sum(1, 2, 3, 4, 5))
// 字符串连接
fmt.Printf(" 字符串连接:\n")
fmt.Printf(" concat() = \"%s\"\n", concat())
fmt.Printf(" concat(\"Hello\") = \"%s\"\n", concat("Hello"))
fmt.Printf(" concat(\"Hello\", \" \", \"World\") = \"%s\"\n",
concat("Hello", " ", "World"))
fmt.Printf(" concat(\"Go\", \" is\", \" awesome\", \"!\") = \"%s\"\n",
concat("Go", " is", " awesome", "!"))
// 找最大值
fmt.Printf(" 找最大值:\n")
fmt.Printf(" max(1) = %d\n", max(1))
fmt.Printf(" max(3, 1, 4, 1, 5) = %d\n", max(3, 1, 4, 1, 5))
fmt.Printf(" max(10, 5, 8, 3, 9, 2, 7) = %d\n", max(10, 5, 8, 3, 9, 2, 7))
fmt.Println()
}
// demonstrateVariadicParameterPassing 演示可变参数的传递
func demonstrateVariadicParameterPassing() {
fmt.Println("2. 可变参数的传递:")
// 直接传递多个参数
fmt.Printf(" 直接传递多个参数:\n")
result1 := multiply(2, 3, 4, 5)
fmt.Printf(" multiply(2, 3, 4, 5) = %d\n", result1)
// 传递切片(需要展开)
fmt.Printf(" 传递切片(使用 ... 展开):\n")
numbers := []int{2, 3, 4, 5}
result2 := multiply(numbers...)
fmt.Printf(" numbers := %v\n", numbers)
fmt.Printf(" multiply(numbers...) = %d\n", result2)
// 混合传递
fmt.Printf(" 混合传递:\n")
result3 := multiply(1, 2)
moreNumbers := []int{3, 4, 5}
result4 := multiply(append([]int{1, 2}, moreNumbers...)...)
fmt.Printf(" multiply(1, 2) = %d\n", result3)
fmt.Printf(" 混合传递结果 = %d\n", result4)
// 空切片传递
fmt.Printf(" 空切片传递:\n")
var emptySlice []int
result5 := multiply(emptySlice...)
fmt.Printf(" multiply(emptySlice...) = %d\n", result5)
// 传递给其他可变参数函数
fmt.Printf(" 传递给其他可变参数函数:\n")
numbers2 := []int{10, 20, 30}
avg := average(numbers2...)
fmt.Printf(" average(%v) = %.2f\n", numbers2, avg)
fmt.Println()
}
// demonstrateVariadicWithOtherParams 演示可变参数与其他参数的组合
func demonstrateVariadicWithOtherParams() {
fmt.Println("3. 可变参数与其他参数的组合:")
// 固定参数 + 可变参数
fmt.Printf(" 固定参数 + 可变参数:\n")
result1 := formatMessage("INFO", "User login", "successful", "from IP 192.168.1.1")
fmt.Printf(" %s\n", result1)
result2 := formatMessage("ERROR", "Database connection failed")
fmt.Printf(" %s\n", result2)
// 多个固定参数 + 可变参数
fmt.Printf(" 多个固定参数 + 可变参数:\n")
result3 := calculateWithOperation("add", 1, 2, 3, 4, 5)
fmt.Printf(" calculateWithOperation(\"add\", 1, 2, 3, 4, 5) = %.2f\n", result3)
result4 := calculateWithOperation("multiply", 2, 3, 4)
fmt.Printf(" calculateWithOperation(\"multiply\", 2, 3, 4) = %.2f\n", result4)
result5 := calculateWithOperation("average", 10, 20, 30, 40, 50)
fmt.Printf(" calculateWithOperation(\"average\", 10, 20, 30, 40, 50) = %.2f\n", result5)
// 带默认值的可变参数函数
fmt.Printf(" 带默认值的可变参数函数:\n")
config1 := createConfig("myapp")
fmt.Printf(" createConfig(\"myapp\") = %+v\n", config1)
config2 := createConfig("myapp", "debug=true", "port=8080", "timeout=30")
fmt.Printf(" createConfig with options = %+v\n", config2)
fmt.Println()
}
// demonstrateVariadicTypeHandling 演示可变参数的类型处理
func demonstrateVariadicTypeHandling() {
fmt.Println("4. 可变参数的类型处理:")
// 不同类型的可变参数
fmt.Printf(" 字符串可变参数:\n")
joined := joinStrings(", ", "apple", "banana", "cherry", "date")
fmt.Printf(" joinStrings(\", \", \"apple\", \"banana\", \"cherry\", \"date\") = \"%s\"\n", joined)
// 接口类型的可变参数
fmt.Printf(" 接口类型的可变参数:\n")
printValues("混合类型:", 42, "hello", 3.14, true, []int{1, 2, 3})
// 结构体类型的可变参数
fmt.Printf(" 结构体类型的可变参数:\n")
person1 := Person{Name: "Alice", Age: 25}
person2 := Person{Name: "Bob", Age: 30}
person3 := Person{Name: "Charlie", Age: 35}
avgAge := calculateAverageAge(person1, person2, person3)
fmt.Printf(" 平均年龄: %.1f\n", avgAge)
// 函数类型的可变参数
fmt.Printf(" 函数类型的可变参数:\n")
add := func(a, b int) int { return a + b }
multiply := func(a, b int) int { return a * b }
subtract := func(a, b int) int { return a - b }
results := applyOperations(10, 5, add, multiply, subtract)
fmt.Printf(" applyOperations(10, 5, add, multiply, subtract) = %v\n", results)
fmt.Println()
}
// demonstratePracticalApplications 演示可变参数的实际应用
func demonstratePracticalApplications() {
fmt.Println("5. 可变参数的实际应用:")
// 应用1: 日志记录
fmt.Printf(" 应用1 - 日志记录:\n")
logInfo("用户登录", "用户ID", 123, "IP地址", "192.168.1.1")
logError("数据库连接失败", "错误码", 1001, "重试次数", 3)
logDebug("缓存命中", "键", "user:123", "值", "Alice")
// 应用2: SQL 查询构建
fmt.Printf(" 应用2 - SQL 查询构建:\n")
query1 := buildSelectQuery("users", "name", "email", "age")
fmt.Printf(" %s\n", query1)
query2 := buildSelectQuery("products", "id", "name", "price", "category", "stock")
fmt.Printf(" %s\n", query2)
// 应用3: HTTP 路由注册
fmt.Printf(" 应用3 - HTTP 路由注册:\n")
registerRoute("GET", "/users", authMiddleware, loggingMiddleware, getUsersHandler)
registerRoute("POST", "/users", authMiddleware, validateMiddleware, createUserHandler)
// 应用4: 数据验证
fmt.Printf(" 应用4 - 数据验证:\n")
userData := map[string]interface{}{
"name": "Alice",
"email": "alice@example.com",
"age": 25,
}
errors := validateData(userData,
validateRequired("name"),
validateEmail("email"),
validateRange("age", 0, 150),
)
if len(errors) == 0 {
fmt.Printf(" 数据验证通过\n")
} else {
fmt.Printf(" 验证错误: %v\n", errors)
}
// 应用5: 配置合并
fmt.Printf(" 应用5 - 配置合并:\n")
defaultConfig := Config{Port: 8080, Debug: false, Timeout: 30}
userConfig := Config{Debug: true, MaxConnections: 100}
envConfig := Config{Port: 9090, Timeout: 60}
finalConfig := mergeConfigs(defaultConfig, userConfig, envConfig)
fmt.Printf(" 最终配置: %+v\n", finalConfig)
fmt.Println()
}
// demonstrateAdvancedVariadicUsage 演示可变参数的高级用法
func demonstrateAdvancedVariadicUsage() {
fmt.Println("6. 可变参数的高级用法:")
// 可变参数的递归处理
fmt.Printf(" 可变参数的递归处理:\n")
result1 := recursiveSum(1, 2, 3, 4, 5)
fmt.Printf(" recursiveSum(1, 2, 3, 4, 5) = %d\n", result1)
// 可变参数的函数式处理
fmt.Printf(" 可变参数的函数式处理:\n")
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evenSum := reduceInts(filterInts(numbers, isEven)...)
fmt.Printf(" 偶数之和: %d\n", evenSum)
oddProduct := reduceInts(filterInts(numbers, isOdd)...)
fmt.Printf(" 奇数之和: %d\n", oddProduct)
// 可变参数的管道处理
fmt.Printf(" 可变参数的管道处理:\n")
pipeline := createPipeline(
func(x int) int { return x * 2 }, // 乘以2
func(x int) int { return x + 1 }, // 加1
func(x int) int { return x * x }, // 平方
)
for i := 1; i <= 3; i++ {
result := pipeline(i)
fmt.Printf(" pipeline(%d) = %d\n", i, result)
}
// 可变参数的选项模式
fmt.Printf(" 可变参数的选项模式:\n")
server1 := createServer("localhost",
withPort(8080),
withTimeout(30),
withDebug(true),
)
fmt.Printf(" 服务器1: %+v\n", server1)
server2 := createServer("0.0.0.0",
withPort(9090),
withMaxConnections(1000),
)
fmt.Printf(" 服务器2: %+v\n", server2)
fmt.Println()
}
// demonstrateVariadicLimitations 演示可变参数的限制和注意事项
func demonstrateVariadicLimitations() {
fmt.Println("7. 可变参数的限制和注意事项:")
// 限制1: 可变参数必须是最后一个参数
fmt.Printf(" 限制1: 可变参数必须是最后一个参数\n")
fmt.Printf(" ✓ func example(a int, b ...string) - 正确\n")
fmt.Printf(" ✗ func example(a ...int, b string) - 错误\n")
// 限制2: 一个函数只能有一个可变参数
fmt.Printf(" 限制2: 一个函数只能有一个可变参数\n")
fmt.Printf(" ✗ func example(a ...int, b ...string) - 错误\n")
// 注意事项1: 可变参数是切片
fmt.Printf(" 注意事项1: 可变参数在函数内部是切片\n")
inspectVariadicParam(1, 2, 3, 4, 5)
// 注意事项2: 修改可变参数会影响原始切片
fmt.Printf(" 注意事项2: 修改可变参数可能影响原始数据\n")
originalSlice := []int{1, 2, 3, 4, 5}
fmt.Printf(" 修改前: %v\n", originalSlice)
modifyVariadicParam(originalSlice...)
fmt.Printf(" 修改后: %v\n", originalSlice)
// 注意事项3: 性能考虑
fmt.Printf(" 注意事项3: 性能考虑\n")
fmt.Printf(" - 传递大量参数时,切片展开可能有性能开销\n")
fmt.Printf(" - 考虑直接传递切片而不是可变参数\n")
// 注意事项4: 类型安全
fmt.Printf(" 注意事项4: 类型安全\n")
fmt.Printf(" - 可变参数必须是相同类型\n")
fmt.Printf(" - 使用 interface{} 可以接受不同类型,但失去类型安全\n")
// 最佳实践
fmt.Printf(" 最佳实践:\n")
fmt.Printf(" 1. 优先考虑切片参数而不是可变参数\n")
fmt.Printf(" 2. 可变参数适用于调用时参数数量不确定的场景\n")
fmt.Printf(" 3. 注意可变参数的性能影响\n")
fmt.Printf(" 4. 使用选项模式处理复杂的可选参数\n")
fmt.Println()
}
// ========== 函数定义 ==========
// 基本可变参数函数
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
func concat(strings ...string) string {
result := ""
for _, str := range strings {
result += str
}
return result
}
func max(numbers ...int) int {
if len(numbers) == 0 {
return 0
}
maximum := numbers[0]
for _, num := range numbers {
if num > maximum {
maximum = num
}
}
return maximum
}
func multiply(numbers ...int) int {
if len(numbers) == 0 {
return 0
}
result := 1
for _, num := range numbers {
result *= num
}
return result
}
func average(numbers ...int) float64 {
if len(numbers) == 0 {
return 0
}
total := sum(numbers...)
return float64(total) / float64(len(numbers))
}
// 固定参数 + 可变参数
func formatMessage(level string, messages ...string) string {
timestamp := "2024-01-01 12:00:00"
allMessages := strings.Join(messages, " ")
return fmt.Sprintf("[%s] %s: %s", timestamp, level, allMessages)
}
func calculateWithOperation(operation string, numbers ...int) float64 {
if len(numbers) == 0 {
return 0
}
switch operation {
case "add":
return float64(sum(numbers...))
case "multiply":
return float64(multiply(numbers...))
case "average":
return average(numbers...)
default:
return 0
}
}
type AppConfig struct {
Name string
Options map[string]string
}
func createConfig(name string, options ...string) AppConfig {
config := AppConfig{
Name: name,
Options: make(map[string]string),
}
for _, option := range options {
parts := strings.SplitN(option, "=", 2)
if len(parts) == 2 {
config.Options[parts[0]] = parts[1]
}
}
return config
}
// 类型处理函数
func joinStrings(separator string, strings ...string) string {
return strings.Join(strings, separator)
}
func printValues(prefix string, values ...interface{}) {
fmt.Printf(" %s ", prefix)
for i, value := range values {
if i > 0 {
fmt.Printf(", ")
}
fmt.Printf("%v", value)
}
fmt.Printf("\n")
}
type Person struct {
Name string
Age int
}
func calculateAverageAge(people ...Person) float64 {
if len(people) == 0 {
return 0
}
totalAge := 0
for _, person := range people {
totalAge += person.Age
}
return float64(totalAge) / float64(len(people))
}
func applyOperations(a, b int, operations ...func(int, int) int) []int {
results := make([]int, len(operations))
for i, op := range operations {
results[i] = op(a, b)
}
return results
}
// 实际应用函数
func logInfo(message string, keyValues ...interface{}) {
fmt.Printf(" [INFO] %s", message)
for i := 0; i < len(keyValues); i += 2 {
if i+1 < len(keyValues) {
fmt.Printf(" %v=%v", keyValues[i], keyValues[i+1])
}
}
fmt.Printf("\n")
}
func logError(message string, keyValues ...interface{}) {
fmt.Printf(" [ERROR] %s", message)
for i := 0; i < len(keyValues); i += 2 {
if i+1 < len(keyValues) {
fmt.Printf(" %v=%v", keyValues[i], keyValues[i+1])
}
}
fmt.Printf("\n")
}
func logDebug(message string, keyValues ...interface{}) {
fmt.Printf(" [DEBUG] %s", message)
for i := 0; i < len(keyValues); i += 2 {
if i+1 < len(keyValues) {
fmt.Printf(" %v=%v", keyValues[i], keyValues[i+1])
}
}
fmt.Printf("\n")
}
func buildSelectQuery(table string, columns ...string) string {
if len(columns) == 0 {
return fmt.Sprintf("SELECT * FROM %s", table)
}
return fmt.Sprintf("SELECT %s FROM %s", strings.Join(columns, ", "), table)
}
// 模拟中间件和处理器
func authMiddleware() { fmt.Printf(" - 认证中间件\n") }
func loggingMiddleware() { fmt.Printf(" - 日志中间件\n") }
func validateMiddleware() { fmt.Printf(" - 验证中间件\n") }
func getUsersHandler() { fmt.Printf(" - 获取用户处理器\n") }
func createUserHandler() { fmt.Printf(" - 创建用户处理器\n") }
func registerRoute(method, path string, handlers ...func()) {
fmt.Printf(" 注册路由: %s %s\n", method, path)
for _, handler := range handlers {
handler()
}
}
// 验证函数类型
type ValidationFunc func(map[string]interface{}) []string
func validateRequired(field string) ValidationFunc {
return func(data map[string]interface{}) []string {
if _, exists := data[field]; !exists {
return []string{fmt.Sprintf("字段 %s 是必需的", field)}
}
return nil
}
}
func validateEmail(field string) ValidationFunc {
return func(data map[string]interface{}) []string {
if email, ok := data[field].(string); ok {
if !strings.Contains(email, "@") {
return []string{fmt.Sprintf("字段 %s 不是有效的邮箱", field)}
}
}
return nil
}
}
func validateRange(field string, min, max int) ValidationFunc {
return func(data map[string]interface{}) []string {
if value, ok := data[field].(int); ok {
if value < min || value > max {
return []string{fmt.Sprintf("字段 %s 必须在 %d-%d 范围内", field, min, max)}
}
}
return nil
}
}
func validateData(data map[string]interface{}, validators ...ValidationFunc) []string {
var allErrors []string
for _, validator := range validators {
if errors := validator(data); errors != nil {
allErrors = append(allErrors, errors...)
}
}
return allErrors
}
// 配置合并
type Config struct {
Port int
Debug bool
Timeout int
MaxConnections int
}
func mergeConfigs(configs ...Config) Config {
result := Config{}
for _, config := range configs {
if config.Port != 0 {
result.Port = config.Port
}
if config.Debug {
result.Debug = config.Debug
}
if config.Timeout != 0 {
result.Timeout = config.Timeout
}
if config.MaxConnections != 0 {
result.MaxConnections = config.MaxConnections
}
}
return result
}
// 高级用法函数
func recursiveSum(numbers ...int) int {
if len(numbers) == 0 {
return 0
}
if len(numbers) == 1 {
return numbers[0]
}
return numbers[0] + recursiveSum(numbers[1:]...)
}
func filterInts(numbers []int, predicate func(int) bool) []int {
var result []int
for _, num := range numbers {
if predicate(num) {
result = append(result, num)
}
}
return result
}
func reduceInts(numbers ...int) int {
return sum(numbers...)
}
func isEven(n int) bool { return n%2 == 0 }
func isOdd(n int) bool { return n%2 == 1 }
func createPipeline(functions ...func(int) int) func(int) int {
return func(input int) int {
result := input
for _, fn := range functions {
result = fn(result)
}
return result
}
}
// 选项模式
type Server struct {
Host string
Port int
Timeout int
Debug bool
MaxConnections int
}
type ServerOption func(*Server)
func withPort(port int) ServerOption {
return func(s *Server) {
s.Port = port
}
}
func withTimeout(timeout int) ServerOption {
return func(s *Server) {
s.Timeout = timeout
}
}
func withDebug(debug bool) ServerOption {
return func(s *Server) {
s.Debug = debug
}
}
func withMaxConnections(max int) ServerOption {
return func(s *Server) {
s.MaxConnections = max
}
}
func createServer(host string, options ...ServerOption) Server {
server := Server{
Host: host,
Port: 80,
Timeout: 10,
Debug: false,
}
for _, option := range options {
option(&server)
}
return server
}
// 限制和注意事项函数
func inspectVariadicParam(numbers ...int) {
fmt.Printf(" 可变参数类型: %T\n", numbers)
fmt.Printf(" 可变参数长度: %d\n", len(numbers))
fmt.Printf(" 可变参数容量: %d\n", cap(numbers))
fmt.Printf(" 可变参数值: %v\n", numbers)
}
func modifyVariadicParam(numbers ...int) {
if len(numbers) > 0 {
numbers[0] = 999 // 修改第一个元素
}
}
/*
运行这个程序:
go run 03-variadic-functions.go
学习要点:
1. 可变参数使用 ...type 语法,必须是函数的最后一个参数
2. 可变参数在函数内部是切片类型
3. 传递切片给可变参数函数需要使用 ... 展开操作符
4. 一个函数只能有一个可变参数
5. 可变参数提供了灵活的函数调用方式
可变参数的语法:
- 定义: func name(params ...type) { ... }
- 调用: name(arg1, arg2, arg3) 或 name(slice...)
- 内部: params 是 []type 类型的切片
常见应用场景:
1. 数学运算函数(求和、求积等)
2. 字符串处理函数
3. 日志记录函数
4. 配置和选项处理
5. 中间件和处理器链
6. 数据验证
7. SQL 查询构建
最佳实践:
1. 优先考虑切片参数,可变参数适用于调用便利性
2. 使用选项模式处理复杂的可选参数
3. 注意可变参数的性能影响
4. 保持函数签名的简洁性
5. 合理使用接口类型的可变参数
限制和注意事项:
1. 可变参数必须是最后一个参数
2. 一个函数只能有一个可变参数
3. 可变参数是切片,修改会影响原始数据
4. 大量参数时考虑性能影响
5. 类型必须相同(除非使用 interface{}
高级用法:
1. 函数式编程风格
2. 选项模式
3. 中间件模式
4. 管道处理
5. 递归处理
6. 配置合并
性能考虑:
1. 切片展开有一定开销
2. 大量参数时考虑直接传递切片
3. 避免在热点代码中过度使用
4. 考虑内存分配的影响
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,869 @@
/*
05-methods.go - Go 语言方法详解
学习目标:
1. 理解方法与函数的区别
2. 掌握方法的定义和调用
3. 学会值接收者和指针接收者的使用
4. 了解方法集的概念
5. 掌握方法的实际应用
知识点:
- 方法定义语法
- 值接收者 vs 指针接收者
- 方法集和接口实现
- 方法的继承和组合
- 方法的实际应用场景
*/
package main
import (
"fmt"
)
func main() {
fmt.Println("=== Go 语言方法详解 ===\n")
// 演示基本方法定义和调用
demonstrateBasicMethods()
// 演示值接收者和指针接收者
demonstrateReceiverTypes()
// 演示方法集和接口实现
demonstrateMethodSets()
// 演示方法的继承和组合
demonstrateMethodComposition()
// 演示方法的实际应用
demonstratePracticalApplications()
// 演示方法的高级用法
demonstrateAdvancedMethodUsage()
}
// demonstrateBasicMethods 演示基本方法定义和调用
func demonstrateBasicMethods() {
fmt.Println("1. 基本方法定义和调用:")
// 创建结构体实例
fmt.Printf(" 创建和使用基本方法:\n")
rect := Rectangle{Width: 10, Height: 5}
fmt.Printf(" 矩形: %+v\n", rect)
fmt.Printf(" 面积: %.2f\n", rect.Area())
fmt.Printf(" 周长: %.2f\n", rect.Perimeter())
// 方法链调用
fmt.Printf(" 方法链调用:\n")
rect.SetWidth(8).SetHeight(6)
fmt.Printf(" 修改后的矩形: %+v\n", rect)
fmt.Printf(" 新面积: %.2f\n", rect.Area())
// 不同类型的方法
fmt.Printf(" 不同类型的方法:\n")
circle := Circle{Radius: 3}
fmt.Printf(" 圆形: %+v\n", circle)
fmt.Printf(" 面积: %.2f\n", circle.Area())
fmt.Printf(" 周长: %.2f\n", circle.Circumference())
// 基本类型的方法
fmt.Printf(" 基本类型的方法:\n")
var temp Temperature = 25.5
fmt.Printf(" 温度: %.1f°C\n", temp)
fmt.Printf(" 华氏度: %.1f°F\n", temp.ToFahrenheit())
fmt.Printf(" 开尔文: %.1f K\n", temp.ToKelvin())
fmt.Println()
}// demonstr
ateReceiverTypes 演示值接收者和指针接收者
func demonstrateReceiverTypes() {
fmt.Println("2. 值接收者和指针接收者:")
// 值接收者示例
fmt.Printf(" 值接收者示例:\n")
counter1 := Counter{Value: 0}
fmt.Printf(" 初始计数器: %+v\n", counter1)
// 值接收者方法不会修改原始值
counter1.IncrementByValue()
fmt.Printf(" 值接收者增加后: %+v\n", counter1) // 值不变
// 指针接收者示例
fmt.Printf(" 指针接收者示例:\n")
counter2 := Counter{Value: 0}
fmt.Printf(" 初始计数器: %+v\n", counter2)
// 指针接收者方法会修改原始值
counter2.IncrementByPointer()
fmt.Printf(" 指针接收者增加后: %+v\n", counter2) // 值改变
// 方法调用的自动转换
fmt.Printf(" 方法调用的自动转换:\n")
counter3 := Counter{Value: 10}
counterPtr := &counter3
// 值类型可以调用指针接收者方法(自动取地址)
counter3.IncrementByPointer()
fmt.Printf(" 值类型调用指针方法: %+v\n", counter3)
// 指针类型可以调用值接收者方法(自动解引用)
result := counterPtr.GetValueCopy()
fmt.Printf(" 指针类型调用值方法: %d\n", result)
// 大结构体的性能考虑
fmt.Printf(" 大结构体的性能考虑:\n")
largeStruct := LargeStruct{}
for i := 0; i < 1000; i++ {
largeStruct.Data[i] = i
}
// 值接收者会拷贝整个结构体
start := time.Now()
largeStruct.ProcessByValue()
valueTime := time.Since(start)
// 指针接收者只传递指针
start = time.Now()
largeStruct.ProcessByPointer()
pointerTime := time.Since(start)
fmt.Printf(" 值接收者耗时: %v\n", valueTime)
fmt.Printf(" 指针接收者耗时: %v\n", pointerTime)
fmt.Println()
}
// demonstrateMethodSets 演示方法集和接口实现
func demonstrateMethodSets() {
fmt.Println("3. 方法集和接口实现:")
// 接口实现
fmt.Printf(" 接口实现:\n")
var shapes []Shape
shapes = append(shapes, Rectangle{Width: 4, Height: 3})
shapes = append(shapes, Circle{Radius: 2})
shapes = append(shapes, Triangle{Base: 6, Height: 4})
totalArea := 0.0
for i, shape := range shapes {
area := shape.Area()
fmt.Printf(" 形状 %d 面积: %.2f\n", i+1, area)
totalArea += area
}
fmt.Printf(" 总面积: %.2f\n", totalArea)
// 方法集的规则
fmt.Printf(" 方法集的规则:\n")
// 值类型的方法集
var drawable1 Drawable = Rectangle{Width: 5, Height: 3}
drawable1.Draw()
// 指针类型的方法集
rect := Rectangle{Width: 5, Height: 3}
var drawable2 Drawable = &rect
drawable2.Draw()
// 可修改接口
fmt.Printf(" 可修改接口:\n")
var modifiable Modifiable = &rect
fmt.Printf(" 修改前: %+v\n", rect)
modifiable.Modify()
fmt.Printf(" 修改后: %+v\n", rect)
// 注意:值类型不能实现需要指针接收者的接口
// var modifiable2 Modifiable = rect // 编译错误
fmt.Println()
}
// demonstrateMethodComposition 演示方法的继承和组合
func demonstrateMethodComposition() {
fmt.Println("4. 方法的继承和组合:")
// 结构体嵌入
fmt.Printf(" 结构体嵌入:\n")
person := Person{
Name: "Alice",
Age: 30,
}
employee := Employee{
Person: person,
JobTitle: "软件工程师",
Salary: 80000,
}
// 可以直接调用嵌入类型的方法
fmt.Printf(" 员工信息: %s\n", employee.GetInfo())
fmt.Printf(" 员工详情: %s\n", employee.GetDetails())
// 匿名嵌入
fmt.Printf(" 匿名嵌入:\n")
manager := Manager{
Person: Person{
Name: "Bob",
Age: 35,
},
Department: "技术部",
TeamSize: 10,
}
// 直接访问嵌入类型的方法和字段
fmt.Printf(" 经理姓名: %s\n", manager.Name) // 直接访问嵌入字段
fmt.Printf(" 经理信息: %s\n", manager.GetInfo()) // 直接调用嵌入方法
fmt.Printf(" 管理信息: %s\n", manager.Manage())
// 方法重写
fmt.Printf(" 方法重写:\n")
student := Student{
Person: Person{
Name: "Charlie",
Age: 20,
},
School: "清华大学",
Grade: "大三",
}
// Student 重写了 GetInfo 方法
fmt.Printf(" 学生信息: %s\n", student.GetInfo())
// 仍然可以访问原始方法
fmt.Printf(" 基础信息: %s\n", student.Person.GetInfo())
fmt.Println()
}// dem
onstratePracticalApplications 演示方法的实际应用
func demonstratePracticalApplications() {
fmt.Println("5. 方法的实际应用:")
// 应用1: 银行账户管理
fmt.Printf(" 应用1 - 银行账户管理:\n")
account := BankAccount{
AccountNumber: "123456789",
Balance: 1000.0,
Owner: "Alice",
}
fmt.Printf(" 初始账户: %s\n", account.GetInfo())
account.Deposit(500.0)
fmt.Printf(" 存款后: %s\n", account.GetInfo())
success := account.Withdraw(200.0)
fmt.Printf(" 取款成功: %t, 余额: %.2f\n", success, account.Balance)
success = account.Withdraw(2000.0)
fmt.Printf(" 取款成功: %t, 余额: %.2f\n", success, account.Balance)
// 应用2: 购物车系统
fmt.Printf(" 应用2 - 购物车系统:\n")
cart := ShoppingCart{}
cart.AddItem("笔记本电脑", 5999.99, 1)
cart.AddItem("鼠标", 99.99, 2)
cart.AddItem("键盘", 299.99, 1)
fmt.Printf(" 购物车内容:\n")
cart.DisplayItems()
fmt.Printf(" 总价: %.2f\n", cart.GetTotal())
cart.RemoveItem("鼠标")
fmt.Printf(" 移除鼠标后总价: %.2f\n", cart.GetTotal())
// 应用3: 日志记录器
fmt.Printf(" 应用3 - 日志记录器:\n")
logger := Logger{Level: "INFO"}
logger.Info("应用程序启动")
logger.Warning("配置文件使用默认值")
logger.Error("数据库连接失败")
logger.Debug("调试信息") // 不会显示,因为级别是 INFO
logger.SetLevel("DEBUG")
logger.Debug("现在可以看到调试信息了")
// 应用4: 配置管理器
fmt.Printf(" 应用4 - 配置管理器:\n")
config := Config{
settings: make(map[string]string),
}
config.Set("database.host", "localhost")
config.Set("database.port", "5432")
config.Set("app.debug", "true")
fmt.Printf(" 数据库主机: %s\n", config.Get("database.host"))
fmt.Printf(" 应用调试: %s\n", config.Get("app.debug"))
fmt.Printf(" 不存在的配置: %s\n", config.Get("nonexistent"))
fmt.Printf(" 所有配置:\n")
config.DisplayAll()
fmt.Println()
}
// demonstrateAdvancedMethodUsage 演示方法的高级用法
func demonstrateAdvancedMethodUsage() {
fmt.Println("6. 方法的高级用法:")
// 高级用法1: 方法表达式
fmt.Printf(" 高级用法1 - 方法表达式:\n")
rect := Rectangle{Width: 4, Height: 3}
// 方法表达式:将方法转换为函数
areaFunc := Rectangle.Area
perimeterFunc := Rectangle.Perimeter
fmt.Printf(" 使用方法表达式计算面积: %.2f\n", areaFunc(rect))
fmt.Printf(" 使用方法表达式计算周长: %.2f\n", perimeterFunc(rect))
// 高级用法2: 方法值
fmt.Printf(" 高级用法2 - 方法值:\n")
// 方法值:绑定到特定实例的方法
rectAreaMethod := rect.Area
rectPerimeterMethod := rect.Perimeter
fmt.Printf(" 使用方法值计算面积: %.2f\n", rectAreaMethod())
fmt.Printf(" 使用方法值计算周长: %.2f\n", rectPerimeterMethod())
// 高级用法3: 接口组合
fmt.Printf(" 高级用法3 - 接口组合:\n")
var readWriter ReadWriter = &File{Name: "test.txt"}
data := []byte("Hello, World!")
readWriter.Write(data)
buffer := make([]byte, 20)
n := readWriter.Read(buffer)
fmt.Printf(" 读取到 %d 字节: %s\n", n, string(buffer[:n]))
// 高级用法4: 类型断言和方法调用
fmt.Printf(" 高级用法4 - 类型断言和方法调用:\n")
var shape Shape = Circle{Radius: 5}
// 类型断言获取具体类型
if circle, ok := shape.(Circle); ok {
fmt.Printf(" 圆的半径: %.2f\n", circle.Radius)
fmt.Printf(" 圆的周长: %.2f\n", circle.Circumference())
}
// 高级用法5: 方法集的动态调用
fmt.Printf(" 高级用法5 - 方法集的动态调用:\n")
calculator := Calculator{}
operations := []struct {
name string
method func(float64, float64) float64
}{
{"加法", calculator.Add},
{"减法", calculator.Subtract},
{"乘法", calculator.Multiply},
{"除法", calculator.Divide},
}
a, b := 10.0, 3.0
for _, op := range operations {
result := op.method(a, b)
fmt.Printf(" %.1f %s %.1f = %.2f\n", a, op.name, b, result)
}
// 高级用法6: 链式方法调用
fmt.Printf(" 高级用法6 - 链式方法调用:\n")
builder := NewStringBuilder()
result := builder.
Append("Hello").
Append(" ").
Append("World").
Append("!").
ToUpper().
Build()
fmt.Printf(" 构建结果: %s\n", result)
fmt.Println()
}// =
========= 类型和方法定义 ==========
// 基本结构体和方法
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// 指针接收者方法,支持方法链
func (r *Rectangle) SetWidth(width float64) *Rectangle {
r.Width = width
return r
}
func (r *Rectangle) SetHeight(height float64) *Rectangle {
r.Height = height
return r
}
func (r Rectangle) Draw() {
fmt.Printf(" 绘制矩形: %.1f x %.1f\n", r.Width, r.Height)
}
func (r *Rectangle) Modify() {
r.Width *= 1.1
r.Height *= 1.1
fmt.Printf(" 矩形已放大 10%%\n")
}
// 圆形结构体和方法
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Circumference() float64 {
return 2 * math.Pi * c.Radius
}
func (c Circle) Draw() {
fmt.Printf(" 绘制圆形: 半径 %.1f\n", c.Radius)
}
// 三角形结构体和方法
type Triangle struct {
Base float64
Height float64
}
func (t Triangle) Area() float64 {
return 0.5 * t.Base * t.Height
}
func (t Triangle) Draw() {
fmt.Printf(" 绘制三角形: 底边 %.1f, 高 %.1f\n", t.Base, t.Height)
}
// 基本类型的方法
type Temperature float64
func (t Temperature) ToFahrenheit() float64 {
return float64(t)*9/5 + 32
}
func (t Temperature) ToKelvin() float64 {
return float64(t) + 273.15
}
// 值接收者 vs 指针接收者示例
type Counter struct {
Value int
}
// 值接收者:不会修改原始值
func (c Counter) IncrementByValue() {
c.Value++
fmt.Printf(" 值接收者内部: %d\n", c.Value)
}
// 指针接收者:会修改原始值
func (c *Counter) IncrementByPointer() {
c.Value++
fmt.Printf(" 指针接收者内部: %d\n", c.Value)
}
func (c Counter) GetValueCopy() int {
return c.Value
}
// 大结构体性能测试
type LargeStruct struct {
Data [1000]int
}
func (ls LargeStruct) ProcessByValue() {
// 值接收者会拷贝整个结构体
sum := 0
for _, v := range ls.Data {
sum += v
}
}
func (ls *LargeStruct) ProcessByPointer() {
// 指针接收者只传递指针
sum := 0
for _, v := range ls.Data {
sum += v
}
}
// 接口定义
type Shape interface {
Area() float64
}
type Drawable interface {
Draw()
}
type Modifiable interface {
Modify()
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type Reader interface {
Read([]byte) int
}
type Writer interface {
Write([]byte) int
}
// 文件类型实现 ReadWriter 接口
type File struct {
Name string
data []byte
}
func (f *File) Read(buffer []byte) int {
n := copy(buffer, f.data)
return n
}
func (f *File) Write(data []byte) int {
f.data = append(f.data, data...)
return len(data)
}
// 结构体嵌入示例
type Person struct {
Name string
Age int
}
func (p Person) GetInfo() string {
return fmt.Sprintf("%s (%d岁)", p.Name, p.Age)
}
type Employee struct {
Person // 具名嵌入
JobTitle string
Salary float64
}
func (e Employee) GetDetails() string {
return fmt.Sprintf("%s - %s, 薪资: %.0f", e.GetInfo(), e.JobTitle, e.Salary)
}
// 匿名嵌入
type Manager struct {
Person // 匿名嵌入
Department string
TeamSize int
}
func (m Manager) Manage() string {
return fmt.Sprintf("管理 %s团队规模: %d人", m.Department, m.TeamSize)
}
// 方法重写示例
type Student struct {
Person
School string
Grade string
}
// 重写 Person 的 GetInfo 方法
func (s Student) GetInfo() string {
return fmt.Sprintf("%s (%d岁) - %s %s", s.Name, s.Age, s.School, s.Grade)
}// 实际应用
示例
// 银行账户
type BankAccount struct {
AccountNumber string
Balance float64
Owner string
}
func (ba *BankAccount) Deposit(amount float64) {
if amount > 0 {
ba.Balance += amount
fmt.Printf(" 存款 %.2f,当前余额: %.2f\n", amount, ba.Balance)
}
}
func (ba *BankAccount) Withdraw(amount float64) bool {
if amount > 0 && amount <= ba.Balance {
ba.Balance -= amount
fmt.Printf(" 取款 %.2f,当前余额: %.2f\n", amount, ba.Balance)
return true
}
fmt.Printf(" 取款失败:余额不足或金额无效\n")
return false
}
func (ba BankAccount) GetInfo() string {
return fmt.Sprintf("账户: %s, 户主: %s, 余额: %.2f",
ba.AccountNumber, ba.Owner, ba.Balance)
}
// 购物车系统
type CartItem struct {
Name string
Price float64
Quantity int
}
type ShoppingCart struct {
Items []CartItem
}
func (sc *ShoppingCart) AddItem(name string, price float64, quantity int) {
// 检查是否已存在该商品
for i := range sc.Items {
if sc.Items[i].Name == name {
sc.Items[i].Quantity += quantity
return
}
}
// 添加新商品
sc.Items = append(sc.Items, CartItem{
Name: name,
Price: price,
Quantity: quantity,
})
}
func (sc *ShoppingCart) RemoveItem(name string) {
for i, item := range sc.Items {
if item.Name == name {
sc.Items = append(sc.Items[:i], sc.Items[i+1:]...)
return
}
}
}
func (sc ShoppingCart) GetTotal() float64 {
total := 0.0
for _, item := range sc.Items {
total += item.Price * float64(item.Quantity)
}
return total
}
func (sc ShoppingCart) DisplayItems() {
for _, item := range sc.Items {
fmt.Printf(" %s: %.2f × %d = %.2f\n",
item.Name, item.Price, item.Quantity,
item.Price*float64(item.Quantity))
}
}
// 日志记录器
type Logger struct {
Level string
}
func (l *Logger) SetLevel(level string) {
l.Level = level
}
func (l Logger) shouldLog(level string) bool {
levels := map[string]int{
"DEBUG": 0,
"INFO": 1,
"WARN": 2,
"ERROR": 3,
}
currentLevel := levels[l.Level]
messageLevel := levels[level]
return messageLevel >= currentLevel
}
func (l Logger) log(level, message string) {
if l.shouldLog(level) {
timestamp := time.Now().Format("2006-01-02 15:04:05")
fmt.Printf(" [%s] %s: %s\n", timestamp, level, message)
}
}
func (l Logger) Debug(message string) {
l.log("DEBUG", message)
}
func (l Logger) Info(message string) {
l.log("INFO", message)
}
func (l Logger) Warning(message string) {
l.log("WARN", message)
}
func (l Logger) Error(message string) {
l.log("ERROR", message)
}
// 配置管理器
type Config struct {
settings map[string]string
}
func (c *Config) Set(key, value string) {
c.settings[key] = value
}
func (c Config) Get(key string) string {
if value, exists := c.settings[key]; exists {
return value
}
return ""
}
func (c Config) DisplayAll() {
for key, value := range c.settings {
fmt.Printf(" %s = %s\n", key, value)
}
}
// 计算器
type Calculator struct{}
func (calc Calculator) Add(a, b float64) float64 {
return a + b
}
func (calc Calculator) Subtract(a, b float64) float64 {
return a - b
}
func (calc Calculator) Multiply(a, b float64) float64 {
return a * b
}
func (calc Calculator) Divide(a, b float64) float64 {
if b != 0 {
return a / b
}
return 0
}
// 字符串构建器(链式调用)
type StringBuilder struct {
parts []string
}
func NewStringBuilder() *StringBuilder {
return &StringBuilder{parts: make([]string, 0)}
}
func (sb *StringBuilder) Append(str string) *StringBuilder {
sb.parts = append(sb.parts, str)
return sb
}
func (sb *StringBuilder) ToUpper() *StringBuilder {
for i, part := range sb.parts {
sb.parts[i] = strings.ToUpper(part)
}
return sb
}
func (sb *StringBuilder) Build() string {
return strings.Join(sb.parts, "")
}
/*
运行这个程序:
go run 05-methods.go
学习要点:
1. 方法是与特定类型关联的函数
2. 方法定义语法func (receiver Type) MethodName() ReturnType
3. 值接收者和指针接收者有不同的行为和用途
4. 方法集决定了类型可以实现哪些接口
5. 结构体嵌入可以实现方法的继承和组合
方法 vs 函数:
1. 方法有接收者,函数没有
2. 方法属于特定类型,函数是独立的
3. 方法可以访问接收者的字段和其他方法
4. 方法支持多态(通过接口)
接收者类型选择:
1. 值接收者:
- 不需要修改接收者
- 接收者是小的结构体
- 接收者是基本类型、数组或小的结构体
2. 指针接收者:
- 需要修改接收者
- 接收者是大的结构体(避免拷贝)
- 接收者包含不能拷贝的字段(如 sync.Mutex
方法集规则:
1. 值类型 T 的方法集:所有值接收者方法
2. 指针类型 *T 的方法集:所有值接收者和指针接收者方法
3. 接口实现需要考虑方法集的匹配
最佳实践:
1. 保持接收者类型的一致性
2. 优先使用指针接收者(除非有特殊原因)
3. 合理使用结构体嵌入实现代码复用
4. 设计清晰的接口和方法签名
5. 使用方法实现面向对象的设计模式
常见应用场景:
1. 数据封装和操作
2. 业务逻辑实现
3. 接口实现和多态
4. 链式调用和流畅接口
5. 状态管理
6. 配置和选项处理
高级特性:
1. 方法表达式和方法值
2. 接口组合
3. 类型断言
4. 动态方法调用
5. 链式方法调用
*/

View File

@@ -0,0 +1,16 @@
# 第三章:函数和方法
本章将学习 Go 语言的函数定义、调用以及方法的概念。
## 学习目标
- 掌握函数的定义和调用
- 理解多返回值的概念
- 学会使用可变参数
- 了解闭包和方法
## 文件列表
- `01-basic-functions.go` - 基础函数
- `02-multiple-returns.go` - 多返回值
- `03-variadic-functions.go` - 可变参数函数
- `04-closures.go` - 闭包
- `05-methods.go` - 方法

View File

@@ -0,0 +1,199 @@
/*
01-arrays.go - Go 语言数组详解
学习目标:
1. 理解数组的概念和特性
2. 掌握数组的声明和初始化
3. 学会数组的基本操作
4. 了解数组的内存布局
5. 掌握数组的实际应用场景
知识点:
- 数组的定义和特性
- 数组的声明和初始化方式
- 数组的访问和修改
- 数组的长度和容量
- 多维数组
- 数组的比较和拷贝
- 数组 vs 切片的区别
*/
package main
import "fmt"
func main() {
fmt.Println("=== Go 语言数组详解 ===\n")
// 演示数组的基本概念
demonstrateBasicArrays()
// 演示数组的声明和初始化
demonstrateArrayDeclaration()
// 演示数组的操作
demonstrateArrayOperations()
// 演示多维数组
demonstrateMultiDimensionalArrays()
// 演示数组的特性
demonstrateArrayProperties()
// 演示数组的实际应用
demonstratePracticalApplications()
// 演示数组 vs 切片
demonstrateArrayVsSlice()
}
// demonstrateBasicArrays 演示数组的基本概念
func demonstrateBasicArrays() {
fmt.Println("1. 数组的基本概念:")
// 数组的基本特性
fmt.Printf(" 数组的基本特性:\n")
fmt.Printf(" - 固定长度的元素序列\n")
fmt.Printf(" - 元素类型相同\n")
fmt.Printf(" - 长度是类型的一部分\n")
fmt.Printf(" - 零值是所有元素都为零值的数组\n")
fmt.Printf(" - 值类型,赋值和传参会拷贝整个数组\n")
// 基本数组示例
fmt.Printf(" 基本数组示例:\n")
var numbers [5]int // 声明长度为5的整数数组
fmt.Printf(" 声明数组: %v\n", numbers)
fmt.Printf(" 数组长度: %d\n", len(numbers))
fmt.Printf(" 数组类型: %T\n", numbers)
// 数组元素访问
numbers[0] = 10
numbers[1] = 20
numbers[2] = 30
fmt.Printf(" 修改元素后: %v\n", numbers)
fmt.Printf(" 第一个元素: %d\n", numbers[0])
fmt.Printf(" 最后一个元素: %d\n", numbers[len(numbers)-1])
fmt.Println()
}
// demonstrateArrayDeclaration 演示数组的声明和初始化
func demonstrateArrayDeclaration() {
fmt.Println("2. 数组的声明和初始化:")
// 方式1: 声明后赋值
fmt.Printf(" 方式1 - 声明后赋值:\n")
var arr1 [3]int
arr1[0] = 1
arr1[1] = 2
arr1[2] = 3
fmt.Printf(" arr1: %v\n", arr1)
// 方式2: 声明时初始化
fmt.Printf(" 方式2 - 声明时初始化:\n")
var arr2 = [3]int{10, 20, 30}
fmt.Printf(" arr2: %v\n", arr2)
// 方式3: 短变量声明
fmt.Printf(" 方式3 - 短变量声明:\n")
arr3 := [4]string{"Go", "Python", "Java", "C++"}
fmt.Printf(" arr3: %v\n", arr3)
// 方式4: 自动推断长度
fmt.Printf(" 方式4 - 自动推断长度:\n")
arr4 := [...]int{1, 2, 3, 4, 5} // ... 让编译器计算长度
fmt.Printf(" arr4: %v (长度: %d)\n", arr4, len(arr4))
// 方式5: 指定索引初始化
fmt.Printf(" 方式5 - 指定索引初始化:\n")
arr5 := [5]int{1: 10, 3: 30, 4: 40} // 指定索引1,3,4的值
fmt.Printf(" arr5: %v\n", arr5)
// 方式6: 混合初始化
fmt.Printf(" 方式6 - 混合初始化:\n")
arr6 := [...]string{0: "first", 2: "third", "fourth"} // 混合指定索引和顺序
fmt.Printf(" arr6: %v (长度: %d)\n", arr6, len(arr6))
// 不同类型的数组
fmt.Printf(" 不同类型的数组:\n")
boolArray := [3]bool{true, false, true}
floatArray := [4]float64{1.1, 2.2, 3.3, 4.4}
stringArray := [2]string{"hello", "world"}
fmt.Printf(" 布尔数组: %v\n", boolArray)
fmt.Printf(" 浮点数组: %v\n", floatArray)
fmt.Printf(" 字符串数组: %v\n", stringArray)
fmt.Println()
}
// demonstrateArrayOperations 演示数组的操作
func demonstrateArrayOperations() {
fmt.Println("3. 数组的操作:")
// 数组遍历
fmt.Printf(" 数组遍历:\n")
fruits := [4]string{"apple", "banana", "cherry", "date"}
// 使用索引遍历
fmt.Printf(" 使用索引遍历:\n")
for i := 0; i < len(fruits); i++ {
fmt.Printf(" fruits[%d] = %s\n", i, fruits[i])
}
// 使用 range 遍历
fmt.Printf(" 使用 range 遍历:\n")
for index, value := range fruits {
fmt.Printf(" fruits[%d] = %s\n", index, value)
}
// 只要值,忽略索引
fmt.Printf(" 只要值,忽略索引:\n")
for _, fruit := range fruits {
fmt.Printf(" 水果: %s\n", fruit)
}
// 只要索引,忽略值
fmt.Printf(" 只要索引,忽略值:\n")
for index := range fruits {
fmt.Printf(" 索引: %d\n", index)
}
// 数组修改
fmt.Printf(" 数组修改:\n")
numbers := [5]int{1, 2, 3, 4, 5}
fmt.Printf(" 原始数组: %v\n", numbers)
// 修改单个元素
numbers[2] = 99
fmt.Printf(" 修改索引2: %v\n", numbers)
// 批量修改
for i := range numbers {
numbers[i] *= 2
}
fmt.Printf(" 全部乘以2: %v\n", numbers)
// 数组查找
fmt.Printf(" 数组查找:\n")
target := "cherry"
found := false
foundIndex := -1
for i, fruit := range fruits {
if fruit == target {
found = true
foundIndex = i
break
}
}
if found {
fmt.Printf(" 找到 '%s' 在索引 %d\n", target, foundIndex)
} else {
fmt.Printf(" 未找到 '%s'\n", target)
}
fmt.Println()
}

View File

@@ -0,0 +1,16 @@
# 第四章:数据结构
本章将学习 Go 语言的内置数据结构,包括数组、切片、映射、结构体和指针。
## 学习目标
- 理解数组和切片的区别
- 掌握映射的操作方法
- 学会定义和使用结构体
- 了解指针的概念和用法
## 文件列表
- `01-arrays.go` - 数组
- `02-slices.go` - 切片
- `03-maps.go` - 映射
- `04-structs.go` - 结构体
- `05-pointers.go` - 指针

View File

@@ -0,0 +1,14 @@
# 第五章:接口
本章将学习 Go 语言的接口系统,这是 Go 实现多态的重要机制。
## 学习目标
- 理解接口的概念和作用
- 掌握接口的定义和实现
- 学会使用空接口
- 了解类型断言的用法
## 文件列表
- `01-basic-interfaces.go` - 基础接口
- `02-empty-interface.go` - 空接口
- `03-type-assertions.go` - 类型断言

View File

@@ -0,0 +1,17 @@
# 第六章:并发编程
本章将学习 Go 语言最重要的特性之一:并发编程。
## 学习目标
- 理解 goroutine 的概念
- 掌握 channel 的使用
- 学会使用 select 语句
- 了解同步原语的用法
- 掌握常见的并发模式
## 文件列表
- `01-goroutines.go` - Goroutines
- `02-channels.go` - Channels
- `03-select.go` - Select 语句
- `04-sync-package.go` - 同步包
- `05-worker-pools.go` - 工作池模式

View File

@@ -0,0 +1,14 @@
# 第七章:错误处理
本章将学习 Go 语言的错误处理机制,这是编写健壮程序的重要技能。
## 学习目标
- 理解 Go 的错误处理哲学
- 掌握基本的错误处理模式
- 学会创建自定义错误
- 了解 panic 和 recover 的用法
## 文件列表
- `01-basic-errors.go` - 基础错误处理
- `02-custom-errors.go` - 自定义错误
- `03-panic-recover.go` - Panic 和 Recover

View File

@@ -0,0 +1,14 @@
# 第八章:包管理
本章将学习 Go 语言的包系统,包括如何创建、导入和管理包。
## 学习目标
- 理解 Go 的包概念
- 掌握包的创建和导入
- 学会使用 Go Modules
- 了解包的可见性规则
## 文件列表
- `01-creating-packages.go` - 创建包
- `02-importing-packages.go` - 导入包
- `utils/helper.go` - 示例包

View File

@@ -0,0 +1,33 @@
// Package utils 提供一些实用的辅助函数
// 这是一个示例包,用于演示包的创建和使用
package utils
import "fmt"
// Add 计算两个整数的和
// 注意:函数名首字母大写,表示这是一个导出的(公开的)函数
func Add(a, b int) int {
return a + b
}
// Multiply 计算两个整数的乘积
func Multiply(a, b int) int {
return a * b
}
// greet 是一个私有函数(首字母小写)
// 只能在包内部使用,外部无法访问
func greet(name string) string {
return fmt.Sprintf("Hello, %s!", name)
}
// GetGreeting 是一个公开函数,内部调用私有函数
func GetGreeting(name string) string {
return greet(name)
}
// 包级别的变量
var PackageVersion = "1.0.0"
// 包级别的常量
const MaxRetries = 3

View File

@@ -0,0 +1,15 @@
# 第九章:高级特性
本章将学习 Go 语言的一些高级特性,包括反射、泛型、上下文和测试。
## 学习目标
- 了解反射的基本概念和用法
- 理解泛型的语法和应用
- 掌握 context 包的使用
- 学会编写单元测试
## 文件列表
- `01-reflection.go` - 反射
- `02-generics.go` - 泛型
- `03-context.go` - Context
- `04-testing.go` - 测试

View File

@@ -0,0 +1,24 @@
# 计算器项目
一个支持基本四则运算的命令行计算器程序。
## 功能特性
- 支持加法、减法、乘法、除法
- 错误处理(如除零错误)
- 交互式命令行界面
- 输入验证
## 运行方法
```bash
cd 01-calculator
go run main.go
```
## 使用示例
```
欢迎使用 Go 计算器!
请输入第一个数字: 10
请选择运算符 (+, -, *, /): +
请输入第二个数字: 5
结果: 10 + 5 = 15
```

View File

@@ -0,0 +1,31 @@
# 待办事项列表项目
一个命令行待办事项管理程序,支持添加、删除、标记完成等功能。
## 功能特性
- 添加新的待办事项
- 查看所有待办事项
- 标记事项为完成
- 删除待办事项
- 数据持久化(保存到文件)
## 运行方法
```bash
cd 02-todo-list
go run main.go
```
## 使用示例
```bash
# 添加待办事项
go run main.go add "学习 Go 语言"
# 查看所有事项
go run main.go list
# 标记完成
go run main.go complete 1
# 删除事项
go run main.go delete 1
```

View File

@@ -0,0 +1,38 @@
# Web 服务器项目
一个简单的 HTTP Web 服务器,提供 RESTful API。
## 功能特性
- HTTP 服务器
- RESTful API 端点
- JSON 数据处理
- 路由处理
- 中间件支持
- 静态文件服务
## API 端点
- `GET /` - 首页
- `GET /api/users` - 获取用户列表
- `POST /api/users` - 创建新用户
- `GET /api/users/{id}` - 获取特定用户
- `PUT /api/users/{id}` - 更新用户
- `DELETE /api/users/{id}` - 删除用户
## 运行方法
```bash
cd 03-web-server
go run main.go
```
服务器将在 http://localhost:8080 启动
## 使用示例
```bash
# 获取用户列表
curl http://localhost:8080/api/users
# 创建新用户
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name":"张三","email":"zhangsan@example.com"}'
```

View File

@@ -0,0 +1,43 @@
# 第十章:实践项目
本章包含三个实践项目,帮助你综合运用前面学到的 Go 语言知识。
## 学习目标
- 综合运用 Go 语言的各种特性
- 学会项目结构的组织
- 掌握实际开发中的最佳实践
- 提高解决实际问题的能力
## 项目列表
### 1. 计算器 (01-calculator/)
一个支持基本四则运算的命令行计算器程序。
**涉及知识点:**
- 基础语法
- 函数定义
- 错误处理
- 用户输入处理
### 2. 待办事项列表 (02-todo-list/)
一个命令行待办事项管理程序,支持添加、删除、标记完成等功能。
**涉及知识点:**
- 数据结构
- 文件操作
- JSON 序列化
- 命令行参数处理
### 3. Web 服务器 (03-web-server/)
一个简单的 HTTP Web 服务器,提供 RESTful API。
**涉及知识点:**
- HTTP 服务器
- 路由处理
- JSON API
- 并发处理
- 中间件
## 运行项目
每个项目目录下都有详细的 README.md 文件,包含运行说明和使用方法。

267
golang-learning/README.md Normal file
View File

@@ -0,0 +1,267 @@
# Go 语言学习指南
欢迎来到 Go 语言学习之旅!这是一个专为初学者设计的系统化学习资源,通过实际代码示例帮助你掌握 Go 编程语言。
## 📚 学习目标
通过这个学习指南,你将能够:
- 掌握 Go 语言的基础语法和核心概念
- 理解 Go 的并发编程模型
- 学会使用 Go 的标准库
- 编写结构良好、可维护的 Go 代码
- 构建实际的 Go 应用程序
## 🗂️ 项目结构
```
golang-learning/
├── README.md # 本文件 - 学习指南
├── go.mod # Go 模块文件
├── 01-basics/ # 第一章:基础语法
├── 02-control-flow/ # 第二章:控制流程
├── 03-functions/ # 第三章:函数和方法
├── 04-data-structures/ # 第四章:数据结构
├── 05-interfaces/ # 第五章:接口
├── 06-concurrency/ # 第六章:并发编程
├── 07-error-handling/ # 第七章:错误处理
├── 08-packages/ # 第八章:包管理
├── 09-advanced/ # 第九章:高级特性
└── 10-projects/ # 第十章:实践项目
```
## 🎯 推荐学习路径
### 第一阶段基础入门1-2周
**目标:掌握 Go 语言的基本语法**
1. **[01-basics/](01-basics/)** - 基础语法
- Hello World 程序
- 变量声明和初始化
- 常量定义
- 基本数据类型
- 运算符使用
2. **[02-control-flow/](02-control-flow/)** - 控制流程
- 条件语句 (if/else)
- 分支语句 (switch)
- 循环语句 (for)
- 范围遍历 (range)
### 第二阶段函数和数据2-3周
**目标:学会组织代码和处理数据**
3. **[03-functions/](03-functions/)** - 函数和方法
- 函数定义和调用
- 多返回值
- 可变参数
- 闭包
- 方法
4. **[04-data-structures/](04-data-structures/)** - 数据结构
- 数组
- 切片
- 映射
- 结构体
- 指针
### 第三阶段面向对象1-2周
**目标:理解 Go 的接口系统**
5. **[05-interfaces/](05-interfaces/)** - 接口
- 接口定义和实现
- 空接口
- 类型断言
### 第四阶段并发编程2-3周
**目标:掌握 Go 的并发特性**
6. **[06-concurrency/](06-concurrency/)** - 并发编程
- Goroutines
- Channels
- Select 语句
- 同步原语
- 工作池模式
### 第五阶段工程实践2-3周
**目标:学会编写健壮的程序**
7. **[07-error-handling/](07-error-handling/)** - 错误处理
- 基本错误处理
- 自定义错误
- Panic 和 Recover
8. **[08-packages/](08-packages/)** - 包管理
- 创建包
- 导入包
- Go Modules
### 第六阶段高级特性2-3周
**目标:掌握高级编程技巧**
9. **[09-advanced/](09-advanced/)** - 高级特性
- 反射
- 泛型
- Context
- 测试
### 第七阶段实践项目3-4周
**目标:综合运用所学知识**
10. **[10-projects/](10-projects/)** - 实践项目
- 计算器
- 待办事项列表
- Web 服务器
## 🚀 如何使用这个学习指南
### 1. 环境准备
确保你已经安装了 Go 语言环境:
```bash
# 检查 Go 版本
go version
# 如果没有安装,请访问 https://golang.org/dl/ 下载安装
```
### 2. 克隆或下载项目
```bash
# 如果你有 Git
git clone <repository-url>
cd golang-learning
# 或者直接下载并解压项目文件
```
### 3. 开始学习
```bash
# 进入第一个学习模块
cd 01-basics
# 运行第一个示例
go run 01-hello-world.go
```
### 4. 学习方法建议
**📖 阅读代码**
- 仔细阅读每个文件的注释
- 理解每行代码的作用
- 注意代码的组织结构
**🏃‍♂️ 运行示例**
- 运行每个 .go 文件
- 观察输出结果
- 对比预期和实际输出
**✏️ 动手实践**
- 修改示例代码
- 尝试不同的参数
- 观察结果变化
**🤔 思考总结**
- 理解每个概念的用途
- 思考实际应用场景
- 记录学习笔记
## 📋 学习检查清单
在每个模块学习完成后,确保你能够:
### 01-basics 基础语法
- [ ] 能够编写和运行 Hello World 程序
- [ ] 理解变量声明的不同方式
- [ ] 掌握 Go 的基本数据类型
- [ ] 会使用各种运算符
### 02-control-flow 控制流程
- [ ] 能够使用 if/else 进行条件判断
- [ ] 掌握 switch 语句的用法
- [ ] 理解 for 循环的各种形式
- [ ] 会使用 range 遍历数据
### 03-functions 函数和方法
- [ ] 能够定义和调用函数
- [ ] 理解多返回值的概念
- [ ] 掌握可变参数的使用
- [ ] 理解闭包和方法
### 04-data-structures 数据结构
- [ ] 掌握数组和切片的区别
- [ ] 能够操作映射map
- [ ] 理解结构体的定义和使用
- [ ] 掌握指针的概念
### 05-interfaces 接口
- [ ] 理解接口的概念
- [ ] 能够定义和实现接口
- [ ] 掌握类型断言的使用
### 06-concurrency 并发编程
- [ ] 理解 goroutine 的概念
- [ ] 能够使用 channel 进行通信
- [ ] 掌握 select 语句的用法
- [ ] 了解同步原语的使用
### 07-error-handling 错误处理
- [ ] 掌握 Go 的错误处理模式
- [ ] 能够创建自定义错误
- [ ] 理解 panic 和 recover
### 08-packages 包管理
- [ ] 能够创建和使用包
- [ ] 理解 Go Modules 的概念
- [ ] 掌握包的导入和导出
### 09-advanced 高级特性
- [ ] 了解反射的基本用法
- [ ] 理解泛型的概念
- [ ] 掌握 context 的使用
- [ ] 能够编写单元测试
### 10-projects 实践项目
- [ ] 完成计算器项目
- [ ] 完成待办事项列表项目
- [ ] 完成 Web 服务器项目
## 🔗 扩展资源
### 官方资源
- [Go 官方网站](https://golang.org/)
- [Go 官方文档](https://golang.org/doc/)
- [Go 标准库文档](https://pkg.go.dev/std)
- [Go 语言规范](https://golang.org/ref/spec)
### 推荐书籍
- 《Go 程序设计语言》
- 《Go 语言实战》
- 《Go 语言学习笔记》
### 在线资源
- [Go by Example](https://gobyexample.com/)
- [A Tour of Go](https://tour.golang.org/)
- [Go 语言中文网](https://studygolang.com/)
## 💡 学习建议
1. **循序渐进**:按照推荐的学习路径,不要跳跃式学习
2. **多动手**:理论结合实践,多写代码
3. **多思考**:理解概念背后的原理
4. **多交流**:加入 Go 语言社区,与其他学习者交流
5. **持续练习**:定期回顾和练习已学内容
## 🤝 贡献
如果你发现任何问题或有改进建议,欢迎:
- 提交 Issue
- 发起 Pull Request
- 分享你的学习心得
## 📄 许可证
本项目采用 MIT 许可证,详见 LICENSE 文件。
---
**祝你学习愉快!🎉**
记住:学习编程最重要的是坚持和实践。每天进步一点点,你就能掌握 Go 语言!

3
golang-learning/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module golang-learning
go 1.21