/* 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 块中有效 */