[当我同步学习代码时,WaitGroup,我注意到WaitGroup使用state1字段来确保状态可以原子存储。
喜欢这个:
type WaitGroup struct {
noCopy noCopy
state1 [3]uint32
}
// state returns pointers to the state and sema fields stored within wg.state1.
func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {
if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2]
} else {
return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0]
}
}
但是当我在Mac和Linux上进行检查时,在64位系统上,在mod 8为4之后显示4字节对齐的数据结构地址,而在32位系统上为0。
我很好奇它在golang中如何保证?
代码在下面:
type M struct {
x [3]uint32
}
var c = M{}
println(
unsafe.Sizeof(c),
unsafe.Alignof(c),
uintptr(unsafe.Pointer(&c.x)),
uintptr(unsafe.Pointer(&c.x))%8,
)
# 64-bit arch
$ go run main.go
12 4 824634396524 4
# 32-bit arch
$ GOARCH=386 go run main.go
12 4 289613752 0
来自golang.org:
计算机体系结构可能要求内存地址对齐;也就是说,对于变量的地址为因子的倍数,变量类型的对齐方式。 Alignof函数接受一个表达式表示任何类型的变量,并返回(type的变量(以字节为单位)。
因此,假设Alignof(c)
为4
,它将与4
对齐,而不必与8
字节对齐。
[创建M
的另一个对象时
var c = M{}
var d = M{}
println(
unsafe.Sizeof(c),
unsafe.Alignof(c),
uintptr(unsafe.Pointer(&c.x))%8,
)
println(
" ",
uintptr(unsafe.Pointer(&d.x))%8,
)
我知道了:
12 4 4
0