Meng小羽

Debug客栈

永远相信美好的事情即将发生! 非标准程序猿 / 🧑‍💻爱编码 / 📹爱摄影 / ⛰️爱徒步 / ❤️更爱女朋友 / 米家好物推荐官 关注我哦,让我们一起变得更强~
github
x
bilibili
zhihu
youtube
follow
email

Go 言語の基礎: 配列、スライス、マップ

Go 言語では、ユーザーデータの保存と管理を容易にするために、データ構造は ** 配列(Array)、スライス(Slice)、マップ(Map)** の 3 つに分けられます。

最近、Go 言語の基礎を学んで、これらの 3 つの構造の実装原理を見ました:

配列(Array)#

  • 配列はスライスとマップの基本データ構造です
  • 配列は固定長のデータ型であり、メモリ上でも連続的に割り当てされます。したがって、インデックス配列のデータアクセス速度は非常に速いです。
  • 配列を宣言する際には、配列の格納タイプと数(配列の長さ)を指定する必要があります
  • 配列変数の型には、配列の長さと要素の型が含まれており、2 つの部分が同じである場合にのみ、配列同士を互いに代入できます。

作成と初期化#

配列を宣言すると、そのデータ型と長さは変更できません。

// 配列リテラルを使用して配列を宣言する
array := [5]int{1, 2, 3, 4, 5}

// 長さを自動的に推測して配列を宣言する
array := [...]int{1, 2, 3, 4, 5, 6}
// ...を使用して長さを代替し、初期化要素の数に基づいて推測する

// 特定の要素値を指定して配列を宣言する
array := [5]int{1:10, 2:20}

ポインタ型#

配列の要素の型は、任意の組み込み型、または特定の構造体型、またはポインタ型にすることができます。

// 長さ3の文字列ポインタ配列を宣言する
var array1 [3]*string

// ポインタ配列に要素を指定する
*array1[0] = "demo0"
*array1[1] = "demo1"
*array1[2] = "demo2"

多次元配列#

配列自体は 1 次元データであり、多次元配列は複数の配列の組み合わせです。

// 2次元配列を宣言する
var array = [3][2]int
// 3と2の2つの次元を持つ要素を宣言しました

// 2次元配列を初期化する
var array = [3][2]int{ {1, 2}, {3, 4}, {5, 6}}

配列の関数間のパス:関数間で変数を渡す際、渡されるのは常に変数の値のコピーであるため、配列変数を渡す場合は配列全体をコピーします!関数を定義する際には、大きなデータ型の場合はポインタ型のパラメータを設計するべきです。これにより、関数呼び出し時には各ポインタに 8 バイトのメモリをスタックに割り当てるだけで済みますが、これはポインタが指す値(共有メモリ)を変更することを意味します。実際、ほとんどの場合、配列ではなくスライス型を使用するべきです。

スライス(Slice)#

  • スライスは参照型であり、そのポインタフィールドが指す基底配列の一部またはすべてを参照します。
  • スライスは動的配列の概念に基づいて構築されています。
  • スライスの動的な拡張は、append を使用して実現されます。
  • 縮小は、スライスを再度スライスすることで実現されます。新しいスライスは元のスライスと同じ基底配列を共有し、それらのポインタは同じ基底配列を指します。

作成と初期化#

スライス型には 3 つのフィールドがあります:

  • ポインタ:スライスが含む最初の要素のアドレスを指します。
  • 長さ:スライスが含む基底配列の要素の数(スライスにアクセスできる要素の数)。
  • 容量:スライスが成長できる最大要素数、つまり基底配列の長さです。

make とスライスリテラル

// makeを使用してスライスを作成する
slice := make([]int, 3)

// 長さと容量を持つスライスを作成する
slice := make([]int, 1, 6)
// 長さが1で容量が6の要素

**nilと空のスライス**

```go
// nilの文字列スライス
var slice []string

// 空のスライス
slice := []int{}
// 空の整数スライス

** スライスは基底配列を参照するだけであり、基底配列のデータはスライス自体に属していないため、スライスは 24 バイトのメモリしか必要としません(64 ビットマシン上では):ポインタフィールド 8 バイト、長さフィールド 8 バイト、容量フィールド 8 バイトです。そのため、関数間で直接スライスを渡すことは効率的です。スタックメモリに 24 バイトのみを割り当てるだけです。

len関数はスライスの長さを返し、cap関数はスライスの容量を返します。

マップ(Map)#

  • マップは順序のないキーバリューペアのコレクションを格納するために使用されます。
  • マップは順序がないコレクションであり、ハッシュテーブルが使用されています。
  • マップのハッシュテーブルには、複数のバケットが含まれており、各バケットにはいくつかのキーバリューペアが格納されています。
  • マップ内部では 2 つの配列が使用されます:
    • 最初の配列:バケットの選択に使用されるハッシュキーの上位 8 ビット値を格納しています。この配列は、キーバリューペアがどのバケットに存在するかを区別するために使用されます。
    • 2 番目の配列:各バケットにはバイト配列があり、まずすべてのキーが順番に格納され、その後にバケットのすべての値が格納されます。

作成と初期化#

// 学生情報を格納するマップを作成する
students := map[string]string{
    "name" : "mengxiaoyu",
    "age"  : "22",
    "sex"  : "boy",
    "hobby": "pingpang",
}

// マップのすべての情報を表示する
for key, value := range students{
    fmt.printf("key:%s, \t value:%s\n", key, value);
}

マップのキーバリューペアを反復処理する順序はランダムです。マップのキーバリューペアを順序通りに取得するには、まずマップのキーをスライスに取得し、そのスライスをソートし、最後にそのスライスを反復処理して、対応するマップの値を取得する必要があります。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。