go 语言网络序主机序(大小端字节序)转换的问题

go 语言大小端字节序的问题

我们一般把字节(byte)当作是数据的最小单位。当然,其实一个字节中还包含8个bit (bit = binary digit)。 在这样的CPU中,总是以4字节对齐的方式来读取或写入内存, 那么同样这4个字节的数据是以什么顺序保存在内存中的呢?我们下面详细探讨一下。

字节序包括:大端序和小端序。

而所谓大端序(big endian),便是指其“最高有效位(most significant byte)”落在低地址上的存储方式。
而对于小端序(little endian)来说就正好相反了,它把“最低有效位(least significant byte)”放在低地址上。

go处理字节序接口

Go中处理大小端序的代码位于 encoding/binary ,包中的全局变量BigEndian用于操作大端序数据,LittleEndian用于操作小端序数据,这两个变量所对应的数据类型都实行了ByteOrder接口

type ByteOrder interface {
	Uint16([]byte) uint16
	Uint32([]byte) uint32
	Uint64([]byte) uint64
	PutUint16([]byte, uint16)
	PutUint32([]byte, uint32)
	PutUint64([]byte, uint64)
	String() string
}

从函数的命名也可了解到前三个是读数据 中间三个是写数据
当类型不满足要求是我们也可以按照go语言的强转格式进行强转

入门demo

package main
import (
        "encoding/binary"
        "fmt"
)
func testBigEndian() {
        // 0000 0000 0000 0000   0000 0001 1111 1111
        var testInt int32 = 256
        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)
        fmt.Printf("bytes to int32: %d\n\n", convInt)
}

func testLittleEndian() {
        // 0000 0000 0000 0000   0000 0001 1111 1111
        var testInt int32 = 256
        fmt.Printf("%d use little endian: \n", testInt)
        var testBytes []byte = make([]byte, 4)
        fmt.Println("int32 to bytes:", testBytes)
        convInt := binary.LittleEndian.Uint32(testBytes)
        fmt.Printf("bytes to int32: %d\n\n", convInt)
}

func main() {
        testBigEndian()
        testLittleEndian()
}

运行结果如下
在这里插入图片描述
但有时候这样做未必会满足我们要求,因为我们编程一般只是做了中间的工作要按照已经封装好的模块之上进行开发。如果发现写入的int32来存储的ipv4发过去总是反的可以仔细研究一下下方代码

package main
import (
        "encoding/binary"
        "fmt"
)
func main() {
        var testInt int32 = -1062731517
        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.LittleEndian.Uint32(testBytes)
}

运行结果如下图
在这里插入图片描述

package main
import (
        "encoding/binary"
        "fmt"
)
func main() {
        var testInt int32 = -1062731517
        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.BigEndian.Uint32(testBytes)
        fmt.Println(convInt)
}

运行结果如下图
在这里插入图片描述

总结

为了增强程序的兼容性,我们在开发跨服务器的TCP服务时,每次发送和接受数据都要进行转换,这样做的目的是保证代码在任何计算机上执行时都能达到预期的效果。

参考来自 http://lihaoquan.me/2016/11/5/golang-byteorder.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值