Home>Article>Backend Development> Go language defaults to big endian or little endian
The go language defaults to big endian. Generally speaking, the byte order of network transmission may be big endian or little endian, depending on the protocol provisions of the communication parties when the software starts. The TCP/IP protocol RFC1700 stipulates the use of "big endian" byte order as network byte order. This rule needs to be followed during development; by default, golang uses big endian order.
The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.
Endianness: the sequence of bytes when stored in the computer and the sequence of input/output; also refers to the storage of multi-bytes The order of bytes of data, typically the way integers are stored in memory and the transmission order of network transmission.
Let’s look at the basic concepts first:
1. Big endian mode (Big endian): Store high-order bytes at the starting address (from low address to Store the high-order byte of the data in the order of the high address to the low-order byte)
2. Little endian mode (Little endian): Store the low-order byte at the starting address (in accordance with the starting address) The low-order byte of the data is stored in the order from low address to high address)
In the computer field, big and small endianness is related to the hardware architecture.
For example: For example, a var a = 0x11223344, the highest byte of this variable is 0x11, and the lowest byte is 0x44. Assume that the addresses allocated in memory are as follows (the addresses are all consecutive)
... | 0x0001 | 0x0002 | 0x0003 | 0x0004 | ... |
---|
When the contents are in big and small endian modes respectively, they are stored as follows
(1) Big endian mode storage (storage address is 16 bits)
Address data
0x0004(High address) 0x44
0x0003 0x33
0x0002 0x22
0x0001(Low address) 0x11
(2) Little endian mode storage (storage address is 16 bits)
Address data
0x0004 (high address) 0x11
0x0003 0x22
0x0002 0x33
0x0001 (low address) 0x44
The definition of big-endian and big-endian was briefly explained above. It will be explained with simple examples, and detailed examples will be given next:
1. Big-Endian: or Big-endian
A type: the memory storage situation of the int32 number 0X0A0B0C0D
The data is in 8bits
In the example , the most significant bit is to store 0x0A at the lowest memory address, followed by 0x0B at the subsequent address, similar to the order of hexadecimal bytes from left to right.
Data is in units of 16bits
The highest 16bit unit 0x0A0B is stored in the low bit
2, little endian Order (little-endian): or little-endian
The data is in 8bits
Example The least significant bit is the memory address stored in 0x0D, and is stored at subsequent addresses in sequence.
Data is in units of 16bits
The lowest 16bit unit 0x0C0D is stored in the low bit.
3. Summary
A CPU using big-endian order and a CPU using little-endian order are not only opposite in bytes, but also in bits. .
For example, the storage of 0x01 in memory
Big endian: low memory bit 00000001 high memory bit
Little endian: low memory bit 10000000 high memory bit Bits
For example, 0x00000001
Big endian: memory low bits 00000000 00000000 00000000 00000001 memory high bits
Little endian: memory low bits 10000000 00000000 00000000 00000000 memory High bits
In fact, the things listed above are ultimately for the following description of network transmission and file storage in golang. choose. Generally speaking, the byte order of network transmission may be big endian or little endian, depending on the protocol provisions of the communication parties when the software starts. TCP/IP protocol RFC1700 stipulates the use of "big endian" byte order as network byte order, and this rule needs to be followed during development. By default golang uses big endian order. For details, see the golang package encoding/binary, which has provided the use of big and little endian order
import ( "encoding/binary" "fmt" ) func BigEndian() { // 大端序 // 二进制形式:0000 0000 0000 0000 0001 0002 0003 0004 var testInt int32 = 0x01020304 // 十六进制表示 fmt.Printf("%d use big endian: \n", testInt) var testBytes []byte = make([]byte, 4) binary.BigEndian.PutUint32(testBytes, uint32(testInt)) //大端序模式 fmt.Println("int32 to bytes:", testBytes) convInt := binary.BigEndian.Uint32(testBytes) //大端序模式的字节转为int32 fmt.Printf("bytes to int32: %d\n\n", convInt) } func LittleEndian() { // 小端序 //二进制形式: 0000 0000 0000 0000 0001 0002 0003 0004 var testInt int32 = 0x01020304 // 16进制 fmt.Printf("%d use little endian: \n", testInt) var testBytes []byte = make([]byte, 4) binary.LittleEndian.PutUint32(testBytes, uint32(testInt)) //小端序模式 fmt.Println("int32 to bytes:", testBytes) convInt := binary.LittleEndian.Uint32(testBytes) //小端序模式的字节转换 fmt.Printf("bytes to int32: %d\n\n", convInt) } func main() { BigEndian() LittleEndian() }
Output results:
16909060 use big endian: int32 to bytes: [1 2 3 4] ### [0001 0002 0003 0004] bytes to int32: 16909060 16909060 use little endian: int32 to bytes: [4 3 2 1] ### [0004 0003 0002 0001] bytes to int32: 16909060
In the RPCX framework, the big-endian mode is used to encode the messages involved in the RPC call process
func (m Message) Encode() []byte { // 编码消息 // 编码metadata将key-value转为key=value&key=value形式 meta := encodeMetadata(m.Metadata) spL := len(m.ServicePath) // 服务长度 smL := len(m.ServiceMethod) // 服务函数 var err error payload := m.Payload // 消息体 if m.CompressType() != None { // 压缩 compressor := Compressors[m.CompressType()] if compressor == nil { // 默认使用None压缩类型 m.SetCompressType(None) } else { payload, err = compressor.Zip(m.Payload) // GZIP压缩 if err != nil { // 压缩失败 不对传输消息进行压缩 m.SetCompressType(None) payload = m.Payload } } } // RPCX数据包 = header + ID + total size + // 服务名及内容: servicePath(size(servicePath) 、len(servicePath)) + // 服务函数及内容:serviceMethod(size(serviceMethod) 、 len(serviceMethod)) + // 元数据及内容: metadata(size(metadata) 、len(metadata)) + // 消息体及内容:payload(size(payload) 、 len(payload)) // 消息长度 = size(servicePath) + len(servicePath) + size(serviceMethod) // + len(serviceMethod) + size(metadata) + len(metadata) // + size(payload) + len(payload) totalL := (4 + spL) + (4 + smL) + (4 + len(meta)) + (4 + len(payload)) // header + dataLen + spLen + sp + smLen + sm // + metaL + meta + payloadLen + payload metaStart := 12 + 4 + (4 + spL) + (4 + smL) // meata开始位置 payLoadStart := metaStart + (4 + len(meta)) // payLoad开始位置 l := 12 + 4 + totalL data := make([]byte, l) copy(data, m.Header[:]) // 拷贝header内容 // 将数据包以大端序模式进行编码 //totalLen binary.BigEndian.PutUint32(data[12:16], uint32(totalL)) // binary.BigEndian.PutUint32(data[16:20], uint32(spL)) copy(data[20:20+spL], util.StringToSliceByte(m.ServicePath)) binary.BigEndian.PutUint32(data[20+spL:24+spL], uint32(smL)) copy(data[24+spL:metaStart], util.StringToSliceByte(m.ServiceMethod)) binary.BigEndian.PutUint32(data[metaStart:metaStart+4], uint32(len(meta))) copy(data[metaStart+4:], meta) binary.BigEndian.PutUint32(data[payLoadStart:payLoadStart+4], uint32(len(payload))) copy(data[payLoadStart+4:], payload) return data}
[Related recommendations:Go video tutorial,Programming teaching】
The above is the detailed content of Go language defaults to big endian or little endian. For more information, please follow other related articles on the PHP Chinese website!