ホームページ  >  記事  >  バックエンド開発  >  Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

青灯夜游
青灯夜游オリジナル
2023-01-05 10:28:504251ブラウズ

Go 言語のデフォルトはビッグ エンディアンです。一般に、ソフトウェア起動時の通信相手のプロトコル規定により、ネットワーク伝送のバイトオーダーはビッグエンディアンとなる場合とリトルエンディアンとなる場合があります。 TCP/IP プロトコル RFC1700 では、ネットワーク バイト オーダーとして「ビッグ エンディアン」バイト オーダーの使用が規定されており、開発中はこのルールに従う必要があります。デフォルトでは、golang はビッグ エンディアン オーダーを使用します。

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。

1. 概要

エンディアン: コンピュータに保存されるときのバイトのシーケンスと入出力のシーケンス。マルチバイトのストレージも指します。データのバイト順、通常は整数がメモリに格納される方法とネットワーク送信の送信順序。

まず基本的な概念を見てみましょう:

  • 1. ビッグ エンディアン モード (ビッグ エンディアン): 開始アドレスに上位バイトを格納します (下位アドレスからアドレスまで)。データの上位バイトをアドレスの上位から下位バイトの順に格納します)

  • #2. リトルエンディアンモード(Little endian):下位バイトを格納開始アドレスのバイト(開始アドレスに応じて) データの下位バイトは下位アドレスから上位アドレスの順に格納されます)

コンピュータ分野では、ビッグエンディアンとスモールエンディアンはハードウェア アーキテクチャに関連しています。

例: たとえば、var a = 0x11223344、この変数の最上位バイトは 0x11、最下位バイトは 0x44 です。メモリ上に割り当てられたアドレスが次のとおりであるとします(アドレスはすべて連続しています)

... 0x0001 0x0002 0x0003 0x0004 ...

コンテンツがそれぞれビッグエンディアンモードとスモールエンディアンモードの場合、以下のように格納されます。

(1) ビッグエンディアンモードの格納(格納アドレスは16ビット)

アドレスデータ

0x0004(上位アドレス) 0x44

0x0003 0x33

0x0002 0x22

0x0001(下位アドレス) 0x11

(2) リトルエンディアンモードストレージ (ストレージアドレスは 16 ビット)

アドレスデータ

0x0004 (上位アドレス) 0x11

0x0003 0x22

0x0002 0x33

0x0001 (低アドレス) 0x44

2. ビッグエンディアンとリトルエンディアン

big-endian の定義エンディアンとビッグエンディアンについては上で簡単に説明しましたが、簡単な例で説明し、次に詳細な例を示します:

1. ビッグエンディアン: またはビッグエンディアン

A型: int32数値0X0A0B0C0D

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

データのメモリ格納状況は8ビットです

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

この例では、最上位ビットは、左から右への 16 進バイトの順序と同様に、最下位メモリ アドレスに 0x0A を格納し、その後のアドレスに 0x0B が続きます。

データは 16 ビット単位です

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

最上位の 16 ビット単位 0x0A0B が下位ビットに格納されます

2、リトルエンディアン 順序 (リトルエンディアン): またはリトルエンディアン

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

データは 8 ビットです

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

例 最下位ビットは 0x0D に格納されるメモリ アドレスで、以降のアドレスに順番に格納されます。

データは16ビット単位です

Go言語のデフォルトはビッグエンディアンまたはリトルエンディアンです

下位ビットには最下位16ビット単位の0x0C0Dが格納されます。

3. 概要

ビッグエンディアン順序を使用する CPU とリトルエンディアン順序を使用する CPU は、バイト数だけでなくビット数も逆です。

たとえば、メモリ内の 0x01 のストレージ

ビッグ エンディアン: メモリ下位ビット 00000001 メモリ上位ビット

リトル エンディアン: メモリ下位ビット 10000000 メモリ上位ビット

例: 0x00000001

ビッグ エンディアン: メモリの下位ビット 00000000 00000000 00000000 00000001 メモリの上位ビット

リトル エンディアン: メモリの下位ビット 10000000 00000000 00000000 00000000 メモリの上位ビット

アプリケーション

実際、上記にリストされているものは、最終的には、golang でのネットワーク送信とファイル ストレージについての次の説明のためのものです。一般に、ソフトウェア起動時の通信相手のプロトコル規定により、ネットワーク伝送のバイトオーダーはビッグエンディアンとなる場合とリトルエンディアンとなる場合があります。 TCP/IP プロトコル RFC1700 では、ネットワーク バイト オーダーとして「ビッグ エンディアン」バイト オーダーを使用することが規定されており、開発時にはこの規則に従う必要があります。デフォルトでは、golang はビッグエンディアン順序を使用します。詳細については、ビッグ エンディアン順序とリトル エンディアン順序の使用を提供する golang パッケージのエンコーディング/バイナリを参照してください。

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 ビデオ チュートリアル プログラミング教育 ]

以上がGo言語のデフォルトはビッグエンディアンまたはリトルエンディアンですの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。