/* 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位系统上是int32,64位系统上是int64 var ui uint = 4294967295 // 32位系统上是uint32,64位系统上是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 字符用 byte,Unicode 字符用 rune 4. 字符串:使用 string,需要修改时转换为 []byte 或 []rune 注意事项: 1. 不同类型之间不能直接运算,必须转换为相同类型 2. 浮点数比较要考虑精度问题 3. 字符串索引访问的是字节,不是字符 4. 使用 range 遍历字符串可以正确处理 Unicode 字符 */