原文:http://lihaoquan.me/2016/11/5/golang-byteorder.html

这个人的博客写的不错,品质也比较高。 我应该也要有这种精神,这种态度。深入到计算机的世界中去。也是一种快乐。

使用Go开发一个简单反向代理服务 这篇文章也要研究一下。很好
---------------------------------------------------------------------------------------------
go语言的字节序

go

最近在看nsq的源码时候,发现它处理message的时候,都会采用字节序进行数据包的处理,于是我觉得有必要深入了解下TCP协议中 字节序的知识

字节序(Byte Order)

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

字节序包括:大端序和小端序,为什么要这么麻烦还要分门别类呢?举个例子,255用二进制表达就是1111 1111,再加1就是1 0000 0000,多了一个1出来,显然我们需要再用额外的一个字节来存放这个1,但是这个1要存放在第一个字节还是第二个字节呢?这时候因为人们选择的不同,就出现了大端序和小端序的差异。

而所谓大字节序(big endian),便是指其“最高有效位(most significant byte)”落在低地址上的存储方式。例如像地址a写入0x0A0B0C0D之后,在内存中的数据便是:

而对于小字节序(little endian)来说就正好相反了,它把“最低有效位(least significant byte)”放在低地址上。例如:

对于我们常用的CPU架构,如Intel,AMD的CPU使用的都是小字节序,而例如Mac OS以前所使用的Power PC使用的便是大字节序(不过现在Mac OS也使用Intel的CPU了)。

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
}

其中,前三个方法用于读取数据,后三个方法用于写入数据。

大家可能会注意到,上面的方法操作的都是无符号整型,如果我们要操作有符号整型的时候怎么办呢?很简单,强制转换就可以了,比如这样:

func PutInt32(b []byte, v int32) {
binary.BigEndian.PutUint32(b, uint32(v))
}

为了深入了解它们,我们先写一个程序观察下go处理大端序和小端序的方式:

package main

import (
"encoding/binary"
"fmt"
"unsafe"
) const INT_SIZE int = int(unsafe.Sizeof(0)) //判断我们系统中的字节序类型
func systemEdian() {
var i int = 0x1
bs := (*[INT_SIZE]byte)(unsafe.Pointer(&i))
if bs[0] == 0 {
fmt.Println("system edian is little endian")
} else {
fmt.Println("system edian is big endian")
}
} 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)
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() {
systemEdian()
fmt.Println("")
testBigEndian()
testLittleEndian()
}

执行的结果:

system edian is big endian

256 use big endian:
int32 to bytes: [0 0 1 0]
bytes to int32: 256 256 use little endian:
int32 to bytes: [0 1 0 0]
bytes to int32: 256

总结

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

【转】go语言的字节序的更多相关文章

  1. C语言字节对齐问题详解(对齐、字节序、网络序等)

    首先说明一下,本文是转载自: http://www.cnblogs.com/clover-toeic/p/3853132.html 博客园用的少,不知道怎么发布转载文章,只能暂时这样了. 引言 考虑下 ...

  2. C语言中的位域、字节序、比特序、大小端

    转:http://www.360doc.com/content/13/0624/10/496343_295125641.shtml 1.比特序 / 位序 /  bit numbering / bit  ...

  3. 用C语言,如何判断主机是 大端还是小端(字节序)

    所谓大端就是指高位值在内存中放低位地址,所谓小端是指低位值在内存中放低位地址.比如 0x12345678 在大端机上是 12345678,在小端机上是 78564312,而一个主机是大端还是小端要看C ...

  4. 09.C语言:预处理(宏定义)、字节序、地址对齐

    一.预处理 预处理 gcc -E Hello.c -o hello.i 编译 gcc -S hello.i -o hello.s 汇编 gcc -c hello.s -o hello.o 链接 gcc ...

  5. c语言getipaddrtable获得ip地址与sendArp获得mac地址以及一些字节序问题记录

    https://docs.microsoft.com/zh-cn/windows/win32/api/iphlpapi/nf-iphlpapi-getipaddrtable msdn,有很多c的源码还 ...

  6. PHP: 深入pack/unpack 字节序

    http://my.oschina.net/goal/blog/195749?p=1 目录[-] 写在前面的话 什么是字节序 MSB和LSB 大端序 小端序 网络字节序 主机字节序 总结 pack/u ...

  7. 【MINA】字节序知识

    字节序,分为高位在前和低位在前,说白了就是先从低操作还是从高位操作 java和网络的字节序是一致的,都是高位在前,这意味着java端序列化和反序列化时不用关心字节序的问题, 那问题是,那讨论字节序有什 ...

  8. TODO:字节序的一些理解

    TODO:字节序的一些理解 本文是小编对字节序的片面理解,希望对你有帮助哈. 字节序,即字节在电脑中存放时的序列与输入(输出)时的序列是先到的在前还是后到的在前. 1.Little endian:将低 ...

  9. 刨根究底字符编码之十一——UTF-8编码方式与字节序标记

    UTF-8编码方式与字节序标记 一.UTF-8编码方式 1. 接下来将分别介绍Unicode字符集的三种编码方式:UTF-8.UTF-16.UTF-32.这里先介绍应用最为广泛的UTF-8. 为满足基 ...

随机推荐

  1. AC日记——小A的糖果 洛谷七月月赛

    小A的糖果 思路: for循环贪心: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #defi ...

  2. 删除DOM节点应用

    <!-- HTML结构 --> <ul id="test-list"> <li>JavaScript</li> <li> ...

  3. JavaScript函数的防抖和节流

    防抖 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间 思路: 每次触发事件时都取消之前的延时调用方法 function debounce(fn) { let tim ...

  4. 洛谷——P1476 休息中的小呆

    P1476 休息中的小呆 题目描述 当大家在考场中接受考验(折磨?)的时候,小呆正在悠闲(欠扁)地玩一个叫“最初梦想”的游戏.游戏描述的是一个叫pass的有志少年在不同的时空穿越对抗传说中的大魔王ch ...

  5. 设计模式-外观模式(Facade Pattern)

    本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 外观模式简介 外观模式的作用用一句话说就是简化接口,举个例子楼主每次编程的时候都要点开IDE.点 ...

  6. BestCoder Round #65 (ZYB's Game)

    ZYB's Game Accepts: 672 Submissions: 1207 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536 ...

  7. 【费用流】NOI2008志愿者招募

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 5171  Solved: 3089[Submit][Stat ...

  8. 【树形dp】Find Metal Mineral

    [HDU4003]Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (J ...

  9. [CODE FESTIVAL 2016]Encyclopedia of Permutations

    题意:给定一个排列,其中有可能有一些未确定的数,求出所有可能的排列的排名之和 首先我们要知道怎么算一个给定排列的排名,设它为$p_{1\cdots n}$ 排名即为比它小的排列数$+1$,对于每一个比 ...

  10. 【推导】【贪心】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem D. Clones and Treasures

    给你一行房间,有的是隐身药水,有的是守卫,有的是金币. 你可以任选起点,向右走,每经过一个药水或金币就拿走,每经过一个守卫必须消耗1个药水,问你最多得几个金币. 药水看成左括号,守卫看成右括号, 就从 ...