整型分为有符号(signed)或无符号(unsigned)。
有符号整型
有符号整型根据整型所占的空间分为:
类型 | 占用的空间 | 取值范围 |
int | 依赖平台 | 依赖平台 |
int8 | 8 bit/1字节 | -2^7 至 2^7 -1 |
int16 | 16 bit/2两字节 | -2^15 至 2^15 -1 |
int32 | 32 bit/4字节 | -2^31 至 2^31 -1 |
int64 | 64 bit/8字节 | -2^63 至26^3 - 1 |
int类型所占空间依赖于操作系统,主要分为两种:
- 在32位的机器上,int占用的空间为32位,即是4字节。
- 在64位的机器上,int占用的空间位64位,即是8字节。
声明int类型的变量
var i int
声明变量为int时,如果没有显式赋值,其默认值为0。
隐式声明int变量
i := 1
var j = 1
使用整型数值做简短变量声明或者类型推断声明,变量的默认类型时int。可以使用reflect.TypeOf()查看变量的类型:
package main
import (
"fmt"
"reflect"
)
func main() {
i := 2
fmt.Printf("i的类型时%s\n", reflect.TypeOf(i))
}
查看int类型所占空间
go语言的bits.UintSize和unsafe.Sizeof()都可以用来获取int类型所占用bit大小。
package main
import (
"fmt"
"math/bits"
"unsafe"
)
func main() {
sizeOfIntInBits := bits.UintSize
fmt.Printf("%d bit\n", sizeOfIntInBits)
var i int
fmt.Printf("%d 字节\n", unsafe.Sizeof(i))
}
使用场景
在大多数需要有符号的整型的地方,推荐使用int。以下情况则使用其他类型的整型:
- 在32位的机器上,数值超过-2^31到2^31范围时,使用整型int64。在32位机器上,int64是有两个32位的地址构成的。
- 数值范围较小时,使用适合的整型类型,如人的年龄,可以使用int8。这种情况下,遵守保小不保大的原则。
- 只有在比较大的整型数值才会使用int64类型。例如:time.Duration是int64。
无符号整型
对应于有符号整型,无符号整型分为:
类型 | 占用空间 | 取值范围 |
uint | 依赖平台 | 依赖平台 |
uint8 | 8 bit/1字节 | 0 至 2^8 -1 |
uint16 | 16 bit/2字节 | 0 至 2^16 -1 |
uint32 | 32 bit/4字节 | 0 至 2^32 -1 |
uint64 | 64 bit/8字节 | 0 至 2^64 -1 |
uintptr | 依赖平台 | 依赖平台 |
uint类型所占空间依赖于操作系统,主要分为两种:
- 在32位的机器上,uint占用的空间为32位,即是4字节。
- 在64位的机器上,uint占用的空间位64位,即是8字节。
声明uint类型的变量
var i uint
uint需要显式声明,如果要查看uint类型所占空间,可以使用bits.UintSize和unsafe.Sizeof()。同样,reflect.TypeOf()
可以查看变量的类型。
package main
import (
"fmt"
"math/bits"
"reflect"
"unsafe"
)
func main() {
sizeOfIntInBits := bits.UintSize
fmt.Printf("%d bit\n", sizeOfIntInBits)
var i uint
fmt.Printf("%d 字节\n", unsafe.Sizeof(i))
fmt.Printf("i的类型是%s\n", reflect.TypeOf(i))
}
uintptr
uintptr也是无符号的整型,它的空间大到足以容纳任何指针地址。因此,其所占空间和范围取决于平台。
- 在32位的机器上,uint占用的空间为32位,取值范围:-2^31 to 2^31 -1。
- 在64位的机器上,uint占用的空间位64位,取值范围:-2^63 to 2^63 -1。
特性:
- uintptr可以和unsafe.Pointer相互转换
- uintptr和其他整型一样进行数值运算
- uintptr可以保存一个指针地址,但它只是一个值,并不引用任何对象
使用场景:
- uintprt和unsafe.Pointer一起使用,用来做非安全的内存访问。
- 用来保存指针地址用于打印和存储。因为uintprt只是一个值,不引用任何对象,也就是不影响对象的垃圾回收。
示例:
package main
import (
"fmt"
"unsafe"
)
type sample struct {
a int
b string
}
func main() {
s := &sample{a: 1, b: "test"}
//获取b在结构体s的地址
p := unsafe.Pointer(uintptr(unsafe.Pointer(s)) + unsafe.Offsetof(s.b))
}
这里需要说明下,在Go语言中,&表示取地址符号 , 取得某个变量的地址,返回的是变量的指针。