go 语言网络序主机序(大小端字节序)转换的问题_白鹿港的博客

CSDN博客_go 大小端转换 · · 62 次点击 · · 开始浏览    

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

本文来自:CSDN博客_go 大小端转换

感谢作者:CSDN博客_go 大小端转换

查看原文:go 语言网络序主机序(大小端字节序)转换的问题_白鹿港的博客

62 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传