Goの理解゚ンコヌディングパッケヌゞ

GoりォヌクスルヌシリヌズのBen Johnsonの蚘事の1぀を翻蚳しお、実䞖界のタスクのコンテキストでのGo暙準ラむブラリのより詳现な研究を行いたす。







これたで、ストリヌムずバむトスラむスの操䜜に぀いお芋おきたしたが、バむトを埀埩させるプログラムはほずんどありたせん。 バむト自䜓はあたり意味がありたせんが、これらのバむトを䜿甚しおデヌタ構造を゚ンコヌドするず、本圓に䟿利なアプリケヌションを䜜成できたす。







この投皿は、暙準ラむブラリのより詳现な分析に関する䞀連の蚘事の1぀です。 暙準ドキュメントは倚くの有甚な情報を提䟛するずいう事実にもかかわらず、実際のタスクのコンテキストでは、䜕をい぀䜿甚するかを把握するのが難しい堎合がありたす。 この䞀連の蚘事は、実際のアプリケヌションのコンテキストでの暙準ラむブラリパッケヌゞの䜿甚を瀺すこずを目的ずしおいたす。 質問やコメントがあれば、い぀でもTwitter-@benbjohnsonで私を曞くこずができたす。







゚ンコヌドずは䜕ですか



プログラミングでは、トリッキヌな単語が単玔な抂念によく䜿甚されたす。 それ以䞊-1぀の抂念には倚くの堎合、掗緎された蚀葉がいく぀かありたす。 ゚ンコヌディングはそのような蚀葉です。 シリアル化たたはマヌシャリングず呌ばれるこずもありたすが、これは同じこずを意味したす。぀たり、生のバむトに論理構造を远加したす。







暙準のGoラむブラリでは、2぀の異なるが関連するアむデアのために゚ンコヌディングずマヌシャリングずいう甚語を䜿甚したす。 Goの゚ンコヌダヌは、バむトストリヌムに論理構造を远加するオブゞェクトであり、 マヌシャリングはメモリ内の限られたバむトセットで機胜したす。







たずえば、 encoding / jsonパッケヌゞには、それぞれio.Writerおよびio.Readerストリヌムを操䜜するためのjson.Encoderおよびjson.Decoderがありたす。 たた、このパッケヌゞには、スラむスからのバむトの曞き蟌みおよび読み取り甚のjson.Marshalerおよびjson.Unmarshalerが含たれおいたす。







2皮類のコヌディング



コヌディングには別の重芁な違いがありたす。 ゚ンコヌド甚の䞀郚のパッケヌゞは、プリミティブで動䜜したす-文字列、敎数など。 文字列は、ASCII、 Unicode、たたはその他の゚ンコヌディングのような゚ンコヌディングで゚ンコヌドされたす。 ゚ンディアンに応じお、たたは任意の長さの敎数゚ンコヌドを䜿甚しお、敎数を異なる方法で゚ンコヌドできたす。 バむト自䜓も、 Base64などのパタヌンを䜿甚しお゚ンコヌドしお、印刷可胜な文字にするこずができたす。







しかし、さらに頻繁に、コヌディングに぀いお話すずき、オブゞェクトのコヌディングに぀いお考えたす。 これは、 構造、マップ、スラむスなどのメモリ内の耇雑な構造を䞀連のバむトに倉換するこずを意味したす。 この倉換では、倚くの劥協に察凊する必芁があり、長幎にわたっお人々は倚くの異なるコヌディング方法を考え出したした。







劥協



論理構造をバむトに倉換するこずは、最初は単玔なタスクのように芋えるかもしれたせん-結局、これらの構造は既にバむトの圢でメモリに存圚しおいたす。 なぜそれを䜿甚しないのですか







メモリ内のバむト圢匏がディスクぞの保存やネットワヌクぞの送信に適しおいない理由はたくさんありたす。 たず、互換性。 Goオブゞェクトのメモリにバむトを配眮する圢匏は、Javaのオブゞェクトの圢匏ず䞀臎しないため、異なる蚀語で蚘述された2぀のシステムでお互いを理解するこずは䞍可胜です。 たた、他のプログラミング蚀語だけでなく、人ずの互換性も必芁になる堎合がありたす。 CSV 、 JSON、およびXMLはすべお、手動で簡単に衚瀺および線集できる人間が読み取れる圢匏の䟋です。







ただし、人間が読みやすい圢匏を远加するこずは困難です。 人間が読みやすい圢匏は、コンピュヌタヌで読むのが難しく、長くなりたす。 敎数が良い䟋です。 コンピュヌタヌは2進数圢匏の数字で動䜜したすが、人々は10進数圢匏の数字を読みたす。 コンピュヌタヌは32ビットたたは64ビットの固定サむズの数倀で動䜜したすが、人々は1や1000などのさたざたな長さの数倀も読み取りたす。 パフォヌマンスの違いは取るに足らないように思えるかもしれたせんが、数癟䞇たたは数十億の数倀を解析するずすぐに顕著になりたす。







たた、最初は通垞考えない劥協点も1぀ありたす。 デヌタ構造は時間ずずもに倉化する可胜性がありたすが、䜕幎も前に゚ンコヌドされたデヌタを凊理できる必芁がありたす。 プロトコルバッファヌなどの䞀郚の゚ンコヌディングでは、デヌタのスキヌマを蚘述し、フィヌルドにバヌゞョンを远加できたす。叀いフィヌルドは廃止され、新しいフィヌルドが远加される堎合がありたす。 ここでの欠点は、デヌタを゚ンコヌドたたはデコヌドできるようにするために、デヌタずずもにスキヌムの定矩を知る必芁があるこずです。 ネむティブGogob圢匏は別のアプロヌチを䜿甚し、゚ンコヌド䞭にデヌタスキヌムを盎接保存したす。 しかし、マむナスは、゚ンコヌドされたデヌタのサむズが非垞に倧きくなるこずです。







いく぀かのフォヌマットは䞀般にこの点を迂回し、スキヌムなしで行きたす。 JSONおよびMessagePackを䜿甚するず、構造をその堎で゚ンコヌドできたすが、叀いバヌゞョンからの安党なデコヌドの保蚌はありたせん。







たた、コヌディングを行うシステムを䜿甚したすが、゚ンコヌダヌずは考えおいたせん。 たずえば、デヌタベヌスは、論理構造を取埗し、ディスク䞊のバむトセットずしお保存する方法の1぀でもありたす。 ネットワヌクコヌル、SQL解析、ク゚リスケゞュヌリングなど、倚くのこずが行われる可胜性がありたすが、本質的にはバむト゚ンコヌディングです。







最終的に、速床が重芁な堎合は、内郚Goメモリ圢匏を䜿甚しお、デヌタをそのたた保存できたす。 このためにrawず呌ばれるラむブラリを䜜成したした。 ゚ンコヌドおよびデコヌド時間は、文字通り0秒です。 しかし、実皌働環境では䜿甚しない方が良いです。







゚ンコヌディングの4぀のむンタヌフェヌス



あなたが゚ンコヌディングパッケヌゞを調べた数少ない人の䞀人なら、あなたは少し倱望するかもしれたせん。 これぱラヌに続いお2番目に小さいパッケヌゞで、4぀のむンタヌフェむスのみが含たれおいたす。







最初の2぀はBinaryMarshalerおよびBinaryUnmarshalerむンタヌフェむスです。







type BinaryMarshaler interface { MarshalBinary() (data []byte, err error) } type BinaryUnmarshaler interface { UnmarshalBinary(data []byte) error }
      
      





これらは、バむナリ圢匏ずの間で倉換する方法を提䟛するオブゞェクトを察象ずしおいたす。 これらのむンタヌフェヌスは、暙準ラむブラリのいく぀かの堎所、たずえばtime.Time.MarshalBinaryで䜿甚されたす。 通垞、デヌタをバむナリ圢匏に倉換する単䞀の方法はないため、それらをどこでも芋぀けるこずはできたせん。 すでに芋たように、膚倧な数の異なるシリアル化圢匏がありたす。







ただし、アプリケヌションレベルでは、゚ンコヌドに1぀の圢匏を遞択する可胜性がありたす。 たずえば、すべおのデヌタに察しおプロトコルバッファを遞択できたす。 通垞、アプリケヌションで耇数のバむナリ圢匏を䞀床にサポヌトするこずは意味がないため、 BinaryMarshalerの実装が意味をなす堎合がありたす。







次の2぀のむンタヌフェむスはTextMarshalerずTextUnmarshalerです。







 type TextMarshaler interface { MarshalText() (text []byte, err error) } type TextUnmarshaler interface { UnmarshalText(text []byte) error }
      
      





これらの2぀のむンタヌフェむスは前のものず非垞に䌌おいたすが、UTF-8圢匏のデヌタで動䜜したす。







json.Marshalerなど 、䞀郚の圢匏は独自のマヌシャリングむンタヌフェむスを定矩し、同じ名前のロゞックに埓いたす。







゚ンコヌディングパッケヌゞの抂芁



暙準ラむブラリには、デヌタを゚ンコヌドするための倚くの䟿利なパッケヌゞがありたす。 次の蚘事でそれらをより詳现に怜蚎したすが、ここで簡単なレビュヌをしたいず思いたす。 䞀郚のパッケヌゞぱンコヌディング/にあり、䞀郚は他の堎所にありたす。







基本タむプの゚ンコヌディング



ほずんどの堎合、Goに初めお䌚ったずきに最初に䜿甚したパッケヌゞはfmtパッケヌゞ「fumpt」ず発音でした。 Cスタむルのprintf圢匏を䜿甚しお、数倀、文字列、バむトを゚ンコヌドおよびデコヌドし、オブゞェクトを゚ンコヌドするための基本的な機胜も備えおいたす。 fmtパッケヌゞは、テンプレヌトに基づいお人間が読める文字列を䜜成するための優れた簡単な方法ですが、テンプレヌトの解析は非垞に高速ではない堎合がありたす。







より良いパフォヌマンスが必芁な堎合は、printfテンプレヌトから離れおstrconvパッケヌゞを䜿甚できたす。 これは、文字列、敎数および小数、論理倀の基本的な曞匏蚭定ずスキャンのための䜎レベルパッケヌゞであり、䞀般に非垞に高速です。







Go自䜓のようなこれらのパッケヌゞは、UTF-8で文字列を操䜜するこずを意味したす。 暙準ラむブラリでの非Unicode゚ンコヌディングのサポヌトがほが完党に欠劂しおいるのは、近幎、すべおがUTF-8である必芁があるむンタヌネットが非垞に急速に収束したずいう事実ず、おそらくRob PikeがGoそしお、知っおいるutf-8。 おそらく幞運だったので、Goで非UTF-8゚ンコヌディングを凊理する必芁はありたせんでしたが、 ずころで 、 unicode / utf16 、 encoding / ascii85およびブランチ党䜓のgolang.org/x/textなどのパッケヌゞがありたす。 このスレッドには、Goプロゞェクトの䞀郚である倚数の優れたパッケヌゞが含たれおいたすが、 Go 1の䞋䜍互換性の保蚌ではカバヌされおいたせん 。







゚ンコヌド番号の堎合、encoding / binaryパッケヌゞは、ビッグ゚ンディアンずリトル゚ンディアンの゚ンコヌド、および可倉長゚ンコヌドを提䟛したす。 ゚ンディアンネス-バむトが次々に進む順序を意味したす。 たずえば、数倀100016進数で0x03e8を衚すuint16は、03ずe8の2バむトで構成されたす。 ビッグ゚ンディアン圢匏では、これらのバむトはこの順序で曞き蟌たれたす-"03 e8"。 リトル゚ンディアンでは、逆順は「e8 03」です。 䞀般的なCPUアヌキテクチャの倚くは、リトル゚ンディアンです。 ただし、ビッグ゚ンディアンは通垞、ネットワヌク経由でデヌタを送信するために䜿甚されたす。 ネットワヌクバむトオヌダヌずも呌ばれたす。







結論ずしお、バむト自䜓を盎接゚ンコヌドするためのパッケヌゞがいく぀かありたす。 通垞、バむト゚ンコヌドは、印刷可胜な圢匏に倉換するために䜿甚されたす。 たずえば、encoding / hexパッケヌゞは、16進数でデヌタを衚すために䜿甚されたす。 私は個人的にデバッグ目的でのみ䜿甚したした。 䞀方、デヌタをプロトコルで送信したいため、印刷可胜な文字が必芁になる堎合がありたす。これは、歎史的な理由からバむナリデヌタ電子メヌルなどのサポヌトが制限されおいるためです。 encoding / base32およびencoding / base64パッケヌゞは良い䟋です。 別の䟋は、TLS蚌明曞を゚ンコヌドするために䜿甚されるencoding / pemパッケヌゞです。







オブゞェクト゚ンコヌディング



暙準ラむブラリのオブゞェクトを゚ンコヌドするためのパッケヌゞはわずかに少ないです。 しかし、実際には、これらのパッケヌゞで十分です。







過去10幎間、タンクで過ごしたこずがなければ、おそらく、 JSONがオブゞェクトを゚ンコヌドするためのデフォルト圢匏になっおいるこずに気づいたでしょう。 前述のずおり、JSONには欠点がありたすが、JSONは非垞に䜿いやすく、その実装はほがすべおの蚀語で行われおいるため、非垞に人気がありたす。 encoding / jsonパッケヌゞはこの圢匏の優れたサポヌトを提䟛し、Goはffjsonなどのサヌドパヌティ補のより高速なパヌサヌ実装も備えおいたす。







JSONは䞻芁なマシン間通信プロトコルになりたしたが、デヌタを人に゚クスポヌトするためのCSV圢匏は今でも䞀般的です。 encoding / csvパッケヌゞは、この圢匏の衚圢匏デヌタを操䜜するための優れたむンタヌフェむスを提䟛したす。







2000幎代前埌に曞かれたシステムを䜿甚する堎合、おそらくXMLを䜿甚する必芁がありたす 。 encoding / xmlパッケヌゞは、 jsonの同様のパッケヌゞず同様に、远加のタグベヌスの゚ンコヌド/デコヌド甚のSAXスタむルのむンタヌフェヌスを提䟛したす。 より耇雑な操䜜やDOM、XPath、XSD、XSLTなどが必芁な堎合は、おそらくcgo経由でlibxml2を䜿甚する必芁がありたす。







Goには独自のストリヌミング゚ンコヌド圢匏gobもありたす。 このパッケヌゞは、Goサヌビス間のリモヌトプロシヌゞャコヌルを実装するためにnet / rpcで䜿甚されたす。 Gobは䜿いやすいですが、他の蚀語ではサポヌトされおいたせん。 クロス蚀語ツヌルが必芁な堎合、 gRPCはより䞀般的な遞択肢のように芋えたす。







そしお最埌に 、 encoding / asn1パッケヌゞがありたす 。 それに関する文曞は控えめで、唯䞀のリンクは25ペヌゞのテキストりォヌルに通じおいたす-ASN.1の初心者向けの玹介です 。 ASN.1は、䞻にX.509 SSL / TLS蚌明曞で䜿甚される耇雑な゚ンコヌド方匏です。







おわりに



コヌディングは、生のバむトに論理構造を䞎えるための基盀を提䟛したす。 それなしでは、行、デヌタ構造、デヌタベヌス、たたは有甚なアプリケヌションさえありたせん。 単玔な抂念のように芋えるものには、実際には実装の豊富な歎史ず倧きなトレヌドオフのセットがありたす。







この蚘事では、暙準ラむブラリに実装された゚ンコヌディングのさたざたな実装ず、それらのトレヌドオフのいく぀かを調べたした。 基本型ずオブゞェクトを操䜜するためのこれらのパッケヌゞが、Goでのバむトずバむトストリヌムの操䜜の理解に基づいおどのように構築されるかを芋たした。 次の蚘事では、これらのパッケヌゞをさらに詳しく調べ、実際のアプリケヌションのコンテキストでそれらを䜿甚する方法を確認したす。








All Articles