「Go Language レッスン 1」コース学習ノート (8)

基本的なデータ型

Go でネイティブにサポートされている数値型は何ですか?

  • Go言語の種類は大きく分けて、基本データ型、複合データ型、インターフェース型の3種類に分かれます。
    • その中で、日常の Go コーディングで最もよく使われるのは基本データ型であり、最もよく使われる基本データ型は数値型です。

整数

  • Go 言語の整数は、主に現実世界の整数値を表すために使用されます。これは、プラットフォームに依存しない整数とプラットフォームに依存する整数に分類できます。これらの主な違いは、これらの整数型の長さが異なる CPU アーキテクチャまたはオペレーティング システムでも一貫しているかどうかです。
    • プラットフォームに依存しない整数
      • どの CPU アーキテクチャでも、どのオペレーティング システムでも、長さは固定されています。
        ここに画像の説明を挿入
      • 符号付き整数 (int8 ~ int64) と符号なし整数 (uint8 ~ uint64) の本質的な違いは、バイナリの最上位ビット (bit) が符号ビットとして解釈されるかどうかであり、これは符号なし整数と符号付き整数に影響します。値の型の範囲です。
      • Go は、整数のビット エンコード方法として 2 の補数 (Two's Complement) を使用します。したがって、単純に最上位ビットを負符号とみなして、残りのビットで表される値を負符号の後ろの値とみなすことはできません。Go の補数コードは、元のコードを 1 ビットずつ反転し、1 を加算することで得られます。
    • プラットフォームに依存する整数
      • プラットフォームに依存しない整数はプラットフォームに依存する整数に対応し、その長さはオペレーティング プラットフォームに応じて異なります。
      • Go 言語では、プラットフォームに関連する 3 つの整数型 (int、uint、および uintptr) がネイティブで提供されます。
        ここに画像の説明を挿入
      • これら 3 つの型の長さはプラットフォームに依存するため、移植性要件を備えたコードを作成する場合は、これらの型の長さに強く依存しないでください。
      • ターゲット オペレーティング プラットフォームでのこれら 3 つのタイプのサイズがわからない場合は、unsafe パッケージによって提供される SizeOf 関数を使用して取得できます。
  • 整数オーバーフローの問題
    • 整数型が演算に含まれており、その結果が整数型の値の境界を超える場合、整数オーバーフローの問題が発生していると言えます。
    • 整数型はオーバーフロー後の「結果」を表すことができないため、オーバーフローが発生した後も、対応する整数変数の値は値の範囲内に収まりますが、結果の値が期待と一致せず、プログラム ロジック エラーが発生します。
  • リテラル値とフォーマットされた出力
    • Go 言語は、設計当初から数値リテラル値 (Number Literal) に関する C 言語の文法形式を継承しています。
    • 以前の Go バージョンでは、10 進数、8 進数、および 16 進数の数値リテラルがサポートされていました。
    • Go 1.13 では、Go はバイナリ リテラルと 2 つの形式の 8 進リテラルのサポートを追加しました。
    • リテラル値の可読性を向上させるために、Go バージョン 1.13 では、リテラル値に数値区切り記号「_」を追加することもサポートされており、区切り記号を使用して数値をグループ化し、可読性を向上させることができます。
    • 逆に、標準ライブラリの fmt パッケージのフォーマット済み出力関数を使用して、さまざまな基数の整数変数を出力することもできます。

浮動小数点

  • 浮動小数点のバイナリ表現
    • Go 言語では、2 つの浮動小数点型 float32 と float64 が提供されており、それぞれ単精度および倍精度浮動小数点数値型に対応します。
      • ただし、Go 言語では float 型は提供されていません
      • つまり、Go が提供する浮動小数点型はすべてプラットフォームに依存しません。
      • float32でもfloat64でも、変数のデフォルト値は0.0ですが、占有するメモリ空間が異なり、表現できる浮動小数点数の範囲や精度も異なります。
    • メモリ内の浮動小数点数のバイナリ表現 (ビット表現) は、整数のバイナリ表現よりもはるかに複雑です。ここに画像の説明を挿入
      • メモリ内の浮動小数点数の 2 進表現は、符号ビット、指数 (つまり、変換された指数)、および仮数の 3 つの部分に分割されます。このように表される浮動小数点数は、( − 1 ) s ∗ 1. M ∗ 2 E − offset (-1)^s * 1.M * 2 ^{E-offset} と等しくなります。( 1 )s1.M _2E オフセット _ _ _
        • 符号ビットが 1 の場合、浮動小数点値は負になります。
        • 符号ビットが 0 の場合、浮動小数点値は正になります。
        • 式中のオフセットを指数オフセット値と呼びます。
      • 指数と仮数における単精度 (float32) 浮動小数点数と倍精度 (float64) 浮動小数点数の違い:
        ここに画像の説明を挿入
        • 単精度浮動小数点型 (float32) は、符号ビットに 1 ビット、指数部に 8 ビット、仮数部に残りの 23 ビットを割り当てます。
        • 倍精度浮動小数点型の場合、符号ビットの長さが単精度浮動小数点型と同じであることを除けば、他の 2 つの部分の長さは単精度浮動小数点型よりも大幅に大きくなります。浮動小数点型で、オーダーコードのビット数は11ビット、仮数部はさらに52ビットあります。
  • リテラル値とフォーマットされた出力
    • Go の浮動小数点リテラルは大きく 2 つのカテゴリに分類でき、1 つは浮動小数点値を 10 進数で直接表現する形式です。このカテゴリでは、リテラル値を通じて浮動小数点値を直接決定できます。
    • もう 1 つは科学的記数法です。科学的表記法で表現された浮動小数点リテラルの場合、浮動小数点値を決定するために特定の変換を実行する必要があります。ここで、科学表記法は 10 進数と 16 進数の 2 種類に分けられます。
      6674.28e-2 // 6674.28 * 10^(-2) = 66.742800
      .12345E+5 // 0.12345 * 10^5 = 12345.000000
      0x2.p10 // 2.0 * 2^10 = 2048.000000
      0x1.Fp+0 // 1.9375 * 2^0 = 1.937500
      

複数型

  • Go では、complex64 と complex128 の 2 種類の複素数が提供されており、complex64 の実数部と虚数部は float32 型、complex128 の実数部と虚数部は float64 型です。複素数に型が明示的に割り当てられていない場合、そのデフォルトの型は complex128 です。
  • 複雑なリテラル値の表現に関しては、実際には 3 つの方法があります。
    • まず、複合型変数を複合リテラル値で直接初期化できますvar c = 5 + 6i
    • 次に、Go は、complex128 型の値を作成するのに便利な complex 関数も提供しますvar c = complex(5, 6) // 5 + 6i
    • 3 番目に、Go が提供する定義済み関数 real および imagi を使用して、複素数の実数部と虚数部を取得することもできます。戻り値は浮動小数点型です。
      var c = complex(5, 6) // 5 + 6i
      r := real(c) // 5.000000
      i := imag(c) // 6.000000
      

文字列型

  • Go では、文字列型は string です。
    • Go 言語は、文字列型を通じて「文字列」の抽象化を統一します。
    • このようにして、コード内に出現する文字列定数、文字列変数、または文字列リテラル値のいずれであっても、その型は一律に文字列に設定されます。
    • 文字列型のデータは不変であるため、同時実行のセキュリティと文字列のストレージ使用率が向上します。
  • Go ストリングの構成
    • Go 言語の文字列値も null 許容のバイト列であり、バイト列のバイト数を文字列の長さと呼びます。各バイトは単なる孤立したデータであり、意味を表現しません。
    • 文字列は、NULL 許容の一連の文字で構成されます。
  • ルーンの種類と文字リテラル
    • Go は、Unicode コード ポイントを表すためにルーン タイプを使用します。Rune は本質的に int32 型のエイリアス型であり、int32 型と完全に同等です。
    • ルーン インスタンスは Unicode 文字であり、Go 文字列はルーン インスタンスのコレクションとみなすこともできます。ルーン変数を文字リテラルで初期化できます。
    • Go では、文字リテラルの表現がいくつかありますが、最も一般的なのは一重引用符で囲まれた文字リテラルです。
    • Unicode 固有のエスケープ文字 \u または \U を接頭辞として使用して、Unicode 文字を表すこともできます。
    • コード ポイントを表すルーンは本質的に整数であるため、整数値を使用して、値を文字リテラルとしてルーン変数に直接割り当てることもできます。
  • 文字列リテラル
    • 文字列は文字の集合です。単一の文字を表す一重引用符を、複数の文字の文字列を表す二重引用符に置き換える必要があります。
    • 文字列型は実際には「記述子」であり、実際には文字列データそのものを格納するのではなく、基になるストレージへのポインタと文字列の長さフィールドのみで構成されます。
    • 関数/メソッドのパラメーターを介して文字列型を直接渡すことで、過度のオーバーヘッドが発生することはありません。渡されるのは単なる「記述子」であり、実際の文字列データではないためです。
  • Go 文字列型に対する一般的な操作
    • 添字
      • 文字列の実装では、実際にデータを格納するのは基礎となる配列です。
      • 文字列の添字付けは、基本的に基になる配列の添字付けと同じです。
        var s = "中国人"
        fmt.Printf("0x%x\n", s[0]) // 0xe4:字符“中” utf-8编码的第一个字节
        
      • 添え字を使用すると、文字ではなく、文字列内の特定の添え字のバイトが取得されます。
    • 文字の反復
      • Go には、通常の反復と範囲反復の 2 つの形式の反復があります。
      • これら 2 つの反復形式で文字列を操作して得られる結果は異なります。
      • 通常の反復による文字列の操作は、バイト パースペクティブ反復です。反復の各ラウンドの結果は、文字列の内容を構成するバイトと、そのバイトが配置されている添え字値です。これは、次と同等です。基になる文字列配列を反復処理します。
      • 範囲反復の場合、反復の各ラウンドで取得されるのは、文字列内の Unicode 文字のコード ポイント値と文字列内の文字のオフセット値です。
      • このような繰り返しによって文字列の文字数を取得できますが、Go が提供する組み込み関数 len を介して取得できるのは文字列の内容の長さ (バイト数) だけです。
      • 文字列内の文字数を取得するより特殊な方法は、標準ライブラリの UTF-8 パッケージにある RuneCountInString 関数を呼び出すことです。
    • 文字列の連結
      • Go は、+/+= 演算子による文字列連結をネイティブにサポートしています。
      • +/+= による文字列連結の開発者エクスペリエンスは最高ですが、連結パフォーマンスは最速ではない可能性があります。
      • このメソッドに加えて、Go は文字列連結操作を実行するための strings.Builder、strings.Join、fmt.Sprintf およびその他の関数も提供します
    • 文字列比較
      • Go の文字列型は、==、!=、>=、<=、>、< などのさまざまな比較演算子をサポートしています。
      • 文字列の比較では、Go は辞書編集的な比較戦略を使用して、2 つの文字列型変数を各文字列の先頭からバイトごとに比較します。
        • 2 つの文字列の間に最初の異なる要素が出現すると、比較は終了し、これら 2 つの要素の比較結果が文字列の最終比較結果として使用されます。
        • 2 つの文字列の長さが異なる場合、長さの短い文字列は空の要素で埋められ、空の要素は他の空でない要素よりも小さくなります。
      • Go の文字列型が不変であることを考えると、2 つの文字列の長さが同じでなければ、特定の文字列データを比較する必要はなく、2 つの文字列が異なると結論付けることもできます。ただし、2 つの文字列の長さが同じである場合は、データ ポインタが同じ基になるストレージ データを指しているかどうかをさらに判断する必要があります。それでも同じであれば、2 つの文字列は同等であると言えますが、異なる場合は、実際のデータの内容をさらに比較する必要があります。
    • 文字列変換
      • Go は、文字列とバイト スライス、文字列とルーン スライスの間の双方向変換をサポートしています。この変換には関数を呼び出す必要はなく、明示的な型変換を使用するだけです。

おすすめ

転載: blog.csdn.net/fangzhan666/article/details/132343891