414 lines
12 KiB
Go
414 lines
12 KiB
Go
/*
|
||
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 字符
|
||
*/ |