详情见文章:详解大端模式和小端模式
总结来说:
-
就是地址位在计算机存储的位置不同,例如0x12 34 56 78在不同模式存储方式不同
-
大端模式(一般用于在通信协议中比较常见)
0x12 0x34 0x56 0x78
-
小端模式 (大部分操作系统本地存储方式)
0x78 0x56 0x34 0x12
2.go语言常见字节序处理函数
导入包
"encoding/binary"
以常见tcp 网络处理为例子使用
package main
import (
"encoding/binary"
"encoding/hex"
"fmt"
)
func main() {
var a uint64=10
var buffer =make([]byte,8)
binary.BigEndian.PutUint64(buffer,a)
fmt.Println(hex.EncodeToString(buffer)) //000000000000000a
b:=binary.BigEndian.Uint64(buffer)
fmt.Println(b) //10
}
-
首先定义一个uint64 整数,占8个字节
-
然后将a 转为 大端存储的字节流,这时候我们用hex.EncodeToString(buffer)查看16进制为000000000000000a,如果是正常小端模式存储下那这个a肯定在前面了,为a000000000000000
3.如何获取直接获取在操作系统的字节序呢
还是以上面的例子,是不是直接将变量a的地址获取处理,转成字节数组,查看16进制,就可以看操作系统是大小端呢,肯定可以,下面来实验下。
package main
import (
"encoding/hex"
"fmt"
"unsafe"
)
func main() {
var a uint64=10
tmp:=*(*[8]byte)(unsafe.Pointer(&a))
fmt.Println(hex.EncodeToString(tmp[:])) //0a00000000000000
}
-
从结果来看是小端模式,我用的是win10 操作系统
-
unsafe.Pointer获取变量的地址再转成字节数组
-
注意必须转成字节数组而不是切片
4.项目中的应用
etcd\pkg\cpuutil\endian.go
package cpuutil
import (
"encoding/binary"
"unsafe"
)
const intWidth int = int(unsafe.Sizeof(0))
var byteOrder binary.ByteOrder
// ByteOrder returns the byte order for the CPU's native endianness.
func ByteOrder() binary.ByteOrder { return byteOrder }
func init() {
i := int(0x1)
if v := (*[intWidth]byte)(unsafe.Pointer(&i)); v[0] == 0 {
byteOrder = binary.BigEndian
} else {
byteOrder = binary.LittleEndian
}
}