3 回答
TA贡献1820条经验 获得超9个赞
您可以使用数组将单个表示int32为两个int16s,然后按照 Rob Pike 的建议将它们组合起来:
func test3() (total int64) {
type A struct {
t int32
u [2]int16
}
a := [...]A{
{1, [2]int16{100, 0}},
{2, [2]int16{3, 0}},
}
for i := 0; i < N; i++ {
p := &a[i%2]
switch p.t {
case 1:
total += int64(p.u[0]<<0 | p.u[1]<<8)
case 2:
total += int64(p.u[0])
}
}
return
}
使用原始的 Go 编译器,它的运行速度比 C 版本慢约 2 倍,而使用 gccgo (-O3) 时,它的运行速度与 C 一样快。
但请注意,这种方法假定小端整数。您需要切换大端架构的转换顺序。
此外,如果您需要从字节切片解码结构,您应该真正使用encoding/binary. 创建这个库是为了在字节序列和其他类型之间进行转换。
TA贡献1875条经验 获得超5个赞
联合可能包含数字类型和八位字节字符串,因此我尝试使用字节切片作为值容器并unsafe.Pointer根据具体类型使用它。
func test3() (total int64) {
type A struct {
t int32
u []byte
}
a := [...]A{{1, make([]byte, 8)}, {2, make([]byte, 8)}}
*(*int32)(unsafe.Pointer(&a[0].u)) = 100
*(*int16)(unsafe.Pointer(&a[1].u)) = 3
for i := 0; i < 5000000000; i++ {
p := &a[i%2]
switch p.t {
case 1:
total += int64(*(*int32)(unsafe.Pointer(&p.u)))
case 2:
total += int64(*(*int16)(unsafe.Pointer(&p.u)))
}
}
return
}
结果:
$ go run union.go
257500000000
12.844752701s
$ go run -compiler gccgo -gccgoflags -O3 union.go
257500000000
6.640667s
它是最好的版本吗?
- 3 回答
- 0 关注
- 387 浏览
添加回答
举报