Go 整数类型详解🧮
Go 整数类型详解
一、核心重点(快速掌握)
序号 | 重点内容 | 备注说明 |
---|---|---|
1 | 类型分类:有符号与无符号 | int8 , int16 , int32 , int64 和 uint8 , uint16 , uint32 , uint64 |
2 | 平台相关类型:int 和 uint | 在32位系统是4字节,在64位系统是8字节 |
3 | 零值默认为0 | 未显式初始化的整数变量默认值为0 |
4 | 支持常量定义 | 使用 const 定义常量,不分配内存 |
5 | 类型转换必须显式 | Go语言不允许隐式类型转换,如需转换必须使用强制类型转换 |
6 | 字面量支持多种进制 | 十进制、二进制(0b )、八进制(0o )、十六进制(0x ) |
7 | 支持溢出检测(Go 1.21+) | 使用 math 包中的 Add , Mul 等函数进行带溢出检查的运算 |
二、知识点详解(专题深入)
1、整数类型分类
1.1 有符号整数类型(Signed Integers)
类型名 | 所占字节数 | 取值范围 |
---|---|---|
int8 | 1 | -128 ~ 127 |
int16 | 2 | -32768 ~ 32767 |
int32 | 4 | -2147483648 ~ 2147483647 |
int64 | 8 | -9223372036854775808 ~ 9223372036854775807 |
1.2 无符号整数类型(Unsigned Integers)
类型名 | 所占字节数 | 取值范围 |
---|---|---|
uint8 | 1 | 0 ~ 255 |
uint16 | 2 | 0 ~ 65535 |
uint32 | 4 | 0 ~ 4294967295 |
uint64 | 8 | 0 ~ 18446744073709551615 |
注意点:
uint8
是最常用的无符号类型之一,对应 ASCII 字符。- 尽量避免使用
int
和uint
,除非你确实需要依赖平台特性。
实例代码:
package main
import "fmt"
func main() {
var a int8 = 127
var b uint8 = 255
fmt.Println("a =", a) // 输出: a = 127
fmt.Println("b =", b) // 输出: b = 255
}
2、平台相关类型:int 与 uint
类型名 | 所占字节数(32位系统) | 所占字节数(64位系统) |
---|---|---|
int | 4 | 8 |
uint | 4 | 8 |
技巧:
- 如果你的程序对性能或内存敏感,建议使用固定大小的类型(如
int32
或int64
)以确保跨平台一致性。 - 对于数组索引、循环计数器等场景,推荐使用
int
。
实例代码:
package main
import (
"fmt"
"unsafe"
)
func main() {
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(0)) // 根据平台输出4或8
fmt.Printf("Size of uint: %d bytes\n", unsafe.Sizeof(uint(0)))
}
注意点:
unsafe.Sizeof
不计算动态内存,仅返回静态类型的大小。- 使用
int
和uint
时要特别注意跨平台兼容性问题。
3、整数字面量表示法
Go 支持多种进制的整数字面量表示方式:
进制类型 | 前缀示例 | 示例值 |
---|---|---|
十进制 | 无 | 123 |
二进制 | 0b |
0b1010 |
八进制 | 0o |
0o755 |
十六进制 | 0x |
0x1A3F |
实例代码:
package main
import "fmt"
func main() {
a := 123 // 十进制
b := 0b1010 // 二进制
c := 0o755 // 八进制
d := 0x1A3F // 十六进制
fmt.Printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d)
}
注意点:
- Go 1.13 开始支持
0b
表示二进制,之前版本不可用。 - 下划线
_
可用于增强可读性,例如:0b1010_1111
。
4、整数常量(const)
Go 中可以使用 const
关键字定义整数常量,具有以下特点:
- 编译时常量,不占用运行时内存。
- 可以跨越类型边界进行赋值,只要在目标类型范围内。
实例代码:
package main
import "fmt"
const (
MaxInt8 = 1<<7 - 1 // 127
MinInt8 = -1 << 7 // -128
MaxUint16 = 1<<16 - 1 // 65535
)
func main() {
var a int8 = MaxInt8
var b uint16 = MaxUint16
fmt.Println("a =", a)
fmt.Println("b =", b)
}
注意点:
- 常量表达式中可以使用位移操作来简化数值定义。
- 常量不能取地址,也不能使用
&
操作符。
5、类型转换必须显式
Go 不允许隐式类型转换,必须使用显式语法进行类型转换。
实例代码:
package main
import "fmt"
func main() {
var a int = 100
var b int32 = int32(a) // 显式转换
fmt.Println("b =", b)
}
注意点:
- 转换可能导致数据丢失,应谨慎处理。
- 使用
strconv
包可在字符串和整数之间转换。
6、溢出处理(Go 1.21+)
Go 1.21 引入了 math
包中的安全整数运算函数,可用于检测溢出。
支持函数列表:
函数名 | 功能描述 |
---|---|
math.Add |
加法并检测是否溢出 |
math.Sub |
减法并检测是否溢出 |
math.Mul |
乘法并检测是否溢出 |
math.Div |
除法并检测是否溢出或除零错误 |
math.Mod |
取模并检测是否溢出或除零错误 |
实例代码:
package main
import (
"fmt"
"math"
)
func main() {
a := math.MaxInt64
b := int64(1)
sum, overflow := math.Add64(a, b)
if overflow {
fmt.Println("加法溢出!")
} else {
fmt.Println("sum =", sum)
}
}
注意点:
- 该功能适用于金融、加密等高精度场景。
- 旧版本 Go 需自行实现溢出判断逻辑。
7、常见陷阱与注意事项汇总
陷阱/问题 | 解决方案/建议 |
---|---|
混合类型运算报错 | 显式转换其中一个操作数为相同类型 |
使用 int 造成跨平台问题 | 推荐使用固定大小类型,如 int32 或 int64 |
误用 uint 导致负数问题 | 注意 uint 无法表示负数,可能导致死循环或逻辑错误 |
忽略溢出风险 | 使用 math 包中的安全运算函数(Go 1.21+) |
字面量格式错误 | 使用正确前缀:0b 、0o 、0x |
忘记初始化变量 | Go 默认初始化为0,但显式初始化更清晰可靠 |
8、使用 iota
定义枚举常量(Enumerated Constants)
知识点:
iota
是 Go 中的预声明标识符,在const
块中自动递增,通常用于定义枚举常量。- 每个
const
块中iota
从 0 开始计数,遇到新的const
块则重置为 0。 - 可以通过位移等操作控制其值的增长方式。
类型 | 描述 |
---|---|
枚举常量 | 使用 iota 实现常量自增机制 |
实例代码:
package main
import "fmt"
const (
Red = iota // 0
Green // 1
Blue // 2
)
func main() {
fmt.Println("Red:", Red) // 输出: 0
fmt.Println("Green:", Green) // 输出: 1
fmt.Println("Blue:", Blue) // 输出: 2
}
多组枚举示例:
const (
_ = iota
First
Second
Third
)
const (
A = iota + 1 // 1
B // 2
C // 3
)
func main() {
fmt.Println("First:", First) // 输出: 1
fmt.Println("C:", C) // 输出: 3
}
高级用法:按位定义状态标志
const (
Read = 1 << iota // 1
Write // 2
Execute // 4
)
func main() {
fmt.Printf("Read: %b\n", Read) // 输出: 1 (二进制)
fmt.Printf("Write: %b\n", Write) // 输出: 10
fmt.Printf("Execute: %b\n", Execute) // 输出: 100
}
注意点:
- 若不需要第一个值,可用
_
忽略初始iota
值。 - 在不同
const
块之间,iota
会重新从 0 开始。 - 不要在非
const
上下文中使用iota
,否则编译报错。
技巧:
- 利用
iota
和位运算可以高效定义权限、状态码、协议字段等。 - 可结合注释与命名规范提升可读性。