参考同学们的介绍和golang的encoding/binary包,特记录备查

一、关于字节序

字节序顺序,又称端序和尾序,是跨越多字节的程序对象的存储规则。

字节序跟CPU架构有关,intel 和AMD cpu采用的都是小端序。网络传输使用大端,也被称之为网络字节序,或网络序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。

  • 大端字节序 高位字节在前,低位字节在后
  • 小端字节序 低位字节在前,高位字节在后

大段字节序更容易理解,为什么会有小端字节序?

计算机读取字节时先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序

二、golang binary

2.1.encoding/binary包

// A ByteOrder specifies how to convert byte sequences into
  // 16-, 32-, or 64-bit unsigned integers.
  type ByteOrder interface {
  	Uint16([]byte) uint16
  	Uint32([]byte) uint32
  	Uint64([]byte) uint64
  	PutUint16([]byte, uint16)
  	PutUint32([]byte, uint32)
  	PutUint64([]byte, uint64)
  	String() string
  }

BigEndian和LittleEndian均实现了ByteOrder接口,因此可以的使用接口的所有方法。前三个方法读取数据。后三个方法写入数据。String()方法返回”LittleEndian”或者”BigEndian”,返回是哪个结构进行调用。

2.2.示例代码

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"unsafe"
)

func main() {
	systemEdian()
	testBigEdian()
	testLittleEdian()
}

//判断我们系统中的字节序类型
func systemEdian() {
	var i int = 0x1
	bs := (*[int(unsafe.Sizeof(0))]byte)(unsafe.Pointer(&i))
	if bs[0] == 0 {
		fmt.Println("system edian is little endian")
	} else {
		fmt.Println("system edian is big endian")
	}
}

func testBigEdian() {
	var pi float64 = math.Pi
	b := new(bytes.Buffer)
	err := binary.Write(b, binary.BigEndian, pi)
	if err != nil {
		fmt.Println("binary write BigEndian err", err)
		return
	}
	fmt.Printf("% x \n", b.Bytes())
	var pii float64
	err = binary.Read(b, binary.BigEndian, &pii)
	if err != nil {
		fmt.Println("binary.Read BigEndian failed:", err)
	}
	fmt.Println(pii)
}
func testLittleEdian() {
	var pi float64 = math.Pi
	b2 := new(bytes.Buffer)
	err := binary.Write(b2, binary.LittleEndian, pi)
	if err != nil {
		fmt.Println("binary write LittleEndian err", err)
		return
	}
	fmt.Printf("% x \n", b2.Bytes())
	var pii2 float64
	err = binary.Read(b2, binary.LittleEndian, &pii2)
	if err != nil {
		fmt.Println("binary.Read LittleEndian failed:", err)
	}
	fmt.Println(pii2)
}