中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

go語言默認是大端嗎

發布時間:2023-01-05 10:40:39 來源:億速云 閱讀:120 作者:iii 欄目:編程語言

本篇內容主要講解“go語言默認是大端嗎”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“go語言默認是大端嗎”吧!

go語言默認是大端。一般來說網絡傳輸的字節序,可能是大端序或者小端序,取決于軟件開始時通訊雙方的協議規定。TCP/IP協議RFC1700規定使用“大端”字節序為網絡字節序,開發的時候需要遵守這一規則;而默認golang是使用大端序的。

一、概述

字節序:字節在電腦中存放時的序列與輸入/輸出時的序列;也指的是存放多字節數據的字節(byte)的順序,典型的情況是整數在內存中的存放方式和網絡傳輸的傳輸順序。

先看下基本概念:

  • 1、大端模式(Big endian):將高序字節存儲在起始地址(按照從低地址到高地址的順序存放數據的高位字節到低位字節)

  • 2、小端模式(Little endian):將低序字節存儲在起始地址(按照從低地址到高地址的順序存放據的低位字節到高位字節)

在計算機領域中,大小端序是跟硬件的體系結構有關的。

舉個栗子:如一個 var a = 0x11223344,對于這個變量的最高字節為0x11,最低字節為0x44。假設在內存中分配地址如下(地址都是連續的)

...0x00010x00020x00030x0004...

當分別處于大小端模式下的內容存放如下

(1)大端模式存儲(存儲地址為16位)

地址 數據

0x0004(高地址) 0x44

0x0003 0x33

0x0002 0x22

0x0001(低地址) 0x11

(2)小端模式存儲(存儲地址為16位)

地址 數據

0x0004(高地址) 0x11

0x0003 0x22

0x0002 0x33

0x0001(低地址) 0x44

二、大端序和小端序

在前面也簡單闡述了大小端序的定義并結合簡單實例來說明,接下來會給出詳細實例來說明:

1、大端序(Big-Endian):或稱大尾序

一個類型: int32 的數 0X0A0B0C0D的內存存放情況

go語言默認是大端嗎

數據是以8bits為單位

go語言默認是大端嗎

示例中,最高有效位是將0x0A存儲在最低的內存地址處,接著是0x0B存在后面的地址,類似十六進制字節從左往右的順序。

數據以16bits為單位

go語言默認是大端嗎

最高的16bit單元0x0A0B存儲在低位

2、小端序(little-endian):或稱小尾序

go語言默認是大端嗎

數據以8bits為單位

go語言默認是大端嗎

示例中最低有效位則是0x0D存儲的內存地址處,后面依次存放在后面的地址處。

數據以16bits為單位

go語言默認是大端嗎

最低的16bit單元0x0C0D存儲在低位。

3、總結

采用大端序的CPU和采用小端序的CPU不僅在字節上是相反的,在比特位上也是相反的。

比如0x01在內存中的存儲

大端序:內存低比特位 00000001 內存高比特位

小端序:內存低比特位 10000000 內存高比特位

比如0x00000001

大端序:內存低比特位 00000000 00000000 00000000 00000001 內存高比特位

小端序:內存低比特位 10000000 00000000 00000000 00000000 內存高比特位

應用

其實在前面羅列出那么東西,最終是為了接下來講述的在golang中涉及到網絡傳輸、文件存儲時的選擇。一般來說網絡傳輸的字節序,可能是大端序或者小端序,取決于軟件開始時通訊雙方的協議規定。TCP/IP協議RFC1700規定使用“大端”字節序為網絡字節序,開發的時候需要遵守這一規則。默認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)  //大端序模式的字節轉為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()
}

輸出結果:

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

在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)  // 服務函數

    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}

到此,相信大家對“go語言默認是大端嗎”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

和田县| 上蔡县| 玉环县| 昌都县| 旌德县| 荥阳市| 曲阜市| 雅安市| 东平县| 临西县| 比如县| 当阳市| 密云县| 连平县| 花莲县| 郸城县| 江北区| 安宁市| 辛集市| 新巴尔虎左旗| 焦作市| 阿拉尔市| 密山市| 资阳市| 曲松县| 邵东县| 长汀县| 吉隆县| 桂东县| 依兰县| 土默特左旗| 汤阴县| 乐平市| 高淳县| SHOW| 屏东市| 大新县| 塔河县| 石屏县| 石门县| 鄯善县|