本篇內容主要講解“go語言默認是大端嗎”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“go語言默認是大端嗎”吧!
企業(yè)建站必須是能夠以充分展現(xiàn)企業(yè)形象為主要目的,是企業(yè)文化與產(chǎn)品對外擴展宣傳的重要窗口,一個合格的網(wǎng)站不僅僅能為公司帶來巨大的互聯(lián)網(wǎng)上的收集和信息發(fā)布平臺,成都創(chuàng)新互聯(lián)面向各種領域:廣告設計等成都網(wǎng)站設計、成都營銷網(wǎng)站建設解決方案、網(wǎng)站設計等建站排名服務。
go語言默認是大端。一般來說網(wǎng)絡傳輸?shù)淖止?jié)序,可能是大端序或者小端序,取決于軟件開始時通訊雙方的協(xié)議規(guī)定。TCP/IP協(xié)議RFC1700規(guī)定使用“大端”字節(jié)序為網(wǎng)絡字節(jié)序,開發(fā)的時候需要遵守這一規(guī)則;而默認golang是使用大端序的。
字節(jié)序:字節(jié)在電腦中存放時的序列與輸入/輸出時的序列;也指的是存放多字節(jié)數(shù)據(jù)的字節(jié)(byte)的順序,典型的情況是整數(shù)在內存中的存放方式和網(wǎng)絡傳輸?shù)膫鬏旐樞颉?/p>
先看下基本概念:
1、大端模式(Big endian):將高序字節(jié)存儲在起始地址(按照從低地址到高地址的順序存放數(shù)據(jù)的高位字節(jié)到低位字節(jié))
2、小端模式(Little endian):將低序字節(jié)存儲在起始地址(按照從低地址到高地址的順序存放據(jù)的低位字節(jié)到高位字節(jié))
在計算機領域中,大小端序是跟硬件的體系結構有關的。
舉個栗子:如一個 var a = 0x11223344,對于這個變量的最高字節(jié)為0x11,最低字節(jié)為0x44。假設在內存中分配地址如下(地址都是連續(xù)的)
... | 0x0001 | 0x0002 | 0x0003 | 0x0004 | ... |
---|
當分別處于大小端模式下的內容存放如下
(1)大端模式存儲(存儲地址為16位)
地址 數(shù)據(jù)
0x0004(高地址) 0x44
0x0003 0x33
0x0002 0x22
0x0001(低地址) 0x11
(2)小端模式存儲(存儲地址為16位)
地址 數(shù)據(jù)
0x0004(高地址) 0x11
0x0003 0x22
0x0002 0x33
0x0001(低地址) 0x44
在前面也簡單闡述了大小端序的定義并結合簡單實例來說明,接下來會給出詳細實例來說明:
1、大端序(Big-Endian):或稱大尾序
一個類型: int32 的數(shù) 0X0A0B0C0D的內存存放情況
數(shù)據(jù)是以8bits為單位
示例中,最高有效位是將0x0A存儲在最低的內存地址處,接著是0x0B存在后面的地址,類似十六進制字節(jié)從左往右的順序。
數(shù)據(jù)以16bits為單位
最高的16bit單元0x0A0B存儲在低位
2、小端序(little-endian):或稱小尾序
數(shù)據(jù)以8bits為單位
示例中最低有效位則是0x0D存儲的內存地址處,后面依次存放在后面的地址處。
數(shù)據(jù)以16bits為單位
最低的16bit單元0x0C0D存儲在低位。
3、總結
采用大端序的CPU和采用小端序的CPU不僅在字節(jié)上是相反的,在比特位上也是相反的。
比如0x01在內存中的存儲
大端序:內存低比特位 00000001 內存高比特位
小端序:內存低比特位 10000000 內存高比特位
比如0x00000001
大端序:內存低比特位 00000000 00000000 00000000 00000001 內存高比特位
小端序:內存低比特位 10000000 00000000 00000000 00000000 內存高比特位
其實在前面羅列出那么東西,最終是為了接下來講述的在golang中涉及到網(wǎng)絡傳輸、文件存儲時的選擇。一般來說網(wǎng)絡傳輸?shù)淖止?jié)序,可能是大端序或者小端序,取決于軟件開始時通訊雙方的協(xié)議規(guī)定。TCP/IP協(xié)議RFC1700規(guī)定使用“大端”字節(jié)序為網(wǎng)絡字節(jié)序,開發(fā)的時候需要遵守這一規(guī)則。默認golang是使用大端序。詳情見golang中包encoding/binary已提供了大、小端序的使用
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) //大端序模式的字節(jié)轉為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) //小端序模式的字節(jié)轉換
fmt.Printf("bytes to int32: %d\n\n", convInt)
}
func main() {
BigEndian()
LittleEndian()
}
輸出結果:
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
在RPCX框架中關于RPC調用過程涉及的傳遞消息進行編碼的,采用的就是大端序模式
func (m Message) Encode() []byte { // 編碼消息
// 編碼metadata將key-value轉為key=value&key=value形式
meta := encodeMetadata(m.Metadata)
spL := len(m.ServicePath) // 服務長度
smL := len(m.ServiceMethod) // 服務函數(shù)
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數(shù)據(jù)包 = header + ID + total size +
// 服務名及內容: servicePath(size(servicePath) 、len(servicePath)) +
// 服務函數(shù)及內容:serviceMethod(size(serviceMethod) 、 len(serviceMethod)) +
// 元數(shù)據(jù)及內容: 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內容
// 將數(shù)據(jù)包以大端序模式進行編碼
//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}
到此,相信大家對“go語言默認是大端嗎”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!