検索
ホームページバックエンド開発GolangGo言語の配列とスライスの違いは何ですか?

Go言語の配列とスライスの違いは何ですか?

Jan 13, 2023 pm 05:26 PM
golang言語を移動配列スライス

配列とスライスの違い: 1. スライスはポインタ型、配列は値型; 2. 配列の代入形式は値転送、スライスの代入形式は参照転送; 3. 長さ配列の長さは固定されており、スライスの長さは任意に調整できます (スライスは動的配列です); 4. 配列の長さは固定ですが、スライスの長さは任意に調整できます (スライスは動的配列です)。

Go言語の配列とスライスの違いは何ですか?

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

Go 言語の配列は C/C の配列とほぼ同等で、サイズが固定されており、動的にサイズを拡張することはできませんが、スライスは C/C のベクトルとほぼ同等です。 C は動的にサイズを拡張でき、サイズが容量を超えた場合にメモリを再割り当てし、新しいメモリ領域にデータをコピーします。 golang の配列とスライスをより深く理解するために、いくつかの質問に答えてみましょう。

1. 配列

Go のスライスは配列の上にある抽象データ型であるため、配列を理解する前にまず配列を理解する必要があります。スライス 。

1. 配列を宣言する 3 つの方法

  • var identifier [len]type
  • var identifier = [len]type{value1 , value2, … , valueN}
  • var identifier = […]type{value1, value2, … , valueN}

対応する:

  • identifier : = [len]type{}
  • identifier := [len]type{value1, value2, … , valueN}
  • identifier := […]type{value1, value2, …, valueN }

例:

var iarray1 [5]int32
var iarray2 [5]int32 = [5]int32{1, 2, 3, 4, 5}
iarray3 := [5]int32{1, 2, 3, 4, 5}
iarray4 := [5]int32{6, 7, 8, 9, 10}
iarray5 := [...]int32{11, 12, 13, 14, 15}
iarray6 := [4][4]int32{{1}, {1, 2}, {1, 2, 3}}  

fmt.Println(iarray1)
fmt.Println(iarray2)
fmt.Println(iarray3)
fmt.Println(iarray4)
fmt.Println(iarray5)
fmt.Println(iarray6)

結果:

[0 0 0 0 0]
[1 2 3 4 5]
[1 2 3 4 5]
[6 7 8 9 10]
[11 12 13 14 15]
[[1 0 0 0] [1 2 0 0] [1 2 3 0] [0 0 0 0]]

配列 iarray1 を調べますが、これは宣言されただけで割り当てられていません。Go 言語を使用すると、自動的に割り当てることができます。値は 0 です。 iarray2 と iarray3 をもう一度見てみると、Go 言語の宣言で型を示すかどうかを指定できることがわかります。var iarray3 = [5]int32{1, 2, 3, 4, 5} もまったく問題ありません。

2. 配列の容量と長さ

配列の容量と長さは同じです。 cap() 関数と len() 関数はどちらも、配列の容量 (つまり長さ) を出力します

3. Type

配列は値型です。ある配列を別の配列に代入するとき、渡された コピーです。スライスは参照型ですが、スライスによってラップされた配列は、スライスの基になる配列と呼ばれます。次の例を見てください:

//a是一个数组,注意数组是一个固定长度的,初始化时候必须要指定长度,不指定长度的话就是切片了
a := [3]int{1, 2, 3}
//b是数组,是a的一份拷贝
b := a
//c是切片,是引用类型,底层数组是a
c := a[:]
for i := 0; i < len(a); i++ {
 a[i] = a[i] + 1
}
//改变a的值后,b是a的拷贝,b不变,c是引用,c的值改变
fmt.Println(a) //[2,3,4]
fmt.Println(b) //[1 2 3]
fmt.Println(c) //[2,3,4]

2. スライス

Go 言語では、スライスは可変長で固定容量の同一の要素シーケンスです。 Go 言語のスライスの本質は配列です。配列の長さが固定されており、スライスの容量が隠し配列の長さになるため、容量も固定されます。可変長とは、配列の長さの範囲内で可変であることを指します。

1. スライスを作成する 4 つの方法

  • var slide1 = make([]int,5,10)
  • var slide2 = make([]int,5)
  • var スライス 3 = []int{}
  • var スライス 4 = []int{1,2,3,4,5}

同様に:

  • slice1 := make([]int,5,10)
  • slice2 := make([]int,5)
  • slice3 := []int{}
  • slice4 := []int{1,2,3,4,5}

上記の対応する出力

[0 0 0 0 0]
[0 0 0 0 0]
[]
[1 2 3 4 5]

3) と 4) からわかるように、スライスの作成と配列の作成の唯一の違いは、Type の前の "[]" に数字があるかどうかです。空の場合、スライスを表します。 、それ以外の場合は配列を表します。スライスは可変長であるため、

2. 隠し配列

Go のスライスは配列の上にある抽象データ型であるため、作成されたスライスには常に配列が含まれます。存在します。

例:

slice0 := []string{"a", "b", "c", "d", "e"}
slice1 := slice0[2 : len(slice0)-1]
slice2 := slice0[:3]
fmt.Println(slice0, slice1, slice2)
slice2[2] = "8"
fmt.Println(slice0, slice1, slice2)

出力:

[a b c d e] [c d] [a b c]
[a b 8 d e] [8 d] [a b 8]

スライスslice0、slice1、slice2が同じ基になる配列への参照であるため、slice2が変更され、その他のスライスが変更されたことも示しています。 2 つすべてが変わります

3. append はスライスを追加します

組み込み関数 append は、同じ型の 1 つ以上の他の値をスライスに追加できます。スライス。追加された要素の数が元のスライスの容量を超える場合、最終的に返されるのは、新しい配列内の新しいスライスです。それを超えない場合、最終的に返されるのは、元の配列内のまったく新しいスライスです。いずれの場合も、追加は元のスライスには影響しません。

例:

slice1 := make([]int, 2, 5)
fmt.Println(len(slice1), cap(slice1))
for k := range slice1{
    fmt.Println(&slice1[k])
}
slice1 = append(slice1,4)
fmt.Println(len(slice1), cap(slice1))
for k := range slice1{
    fmt.Println(&slice1[k])
}
slice1 = append(slice1,5,6,7)
fmt.Println(len(slice1), cap(slice1))
for k := range slice1{
    fmt.Println(&slice1[k])
}

出力:

2 5 //长度和容量
0xc420012150
0xc420012158

3 5 //第一次追加,未超出容量,所以内存地址未发生改变
0xc420012150
0xc420012158
0xc420012160

6 10 //第二次追加,超过容量,内存地址都发生了改变,且容量也发生了改变,且是原来的2倍
0xc4200100f0
0xc4200100f8
0xc420010100
0xc420010108
0xc420010110
0xc420010118

別の例を見てください:

slice1 := make([]int, 2, 5)
slice2 := slice1[:1]
fmt.Println(len(slice1), cap(slice1))
for k := range slice1{
    fmt.Println(&slice1[k])
}
fmt.Println(len(slice2), cap(slice2))
for k := range slice2{
    fmt.Println(&slice2[k])
}

slice2 = append(slice2,4,5,6,7,8)

fmt.Println(len(slice1), cap(slice1))
for k := range slice1{
    fmt.Println(&slice1[k])
}
fmt.Println(len(slice2), cap(slice2))
for k := range slice2{
    fmt.Println(&slice2[k])
}

上記の出力:

2 5 //slice1的长度和容量
0xc4200700c0
0xc4200700c8

1 5  //slice2的长度和容量
0xc4200700c0

2 5 //slice2追加后,slice1的长度和容量、内存都未发生改变
0xc4200700c0
0xc4200700c8

6 10 //slice2追加后,超过了容量,所以slice2的长度和容量、内存地址都发生改变。
0xc42007e000
0xc42007e008
0xc42007e010
0xc42007e018
0xc42007e020
0xc42007e028

3. GO配列とスライスの違い

以下では主に、配列とスライスの違いを説明するためにいくつかの実際的な例を見ていきます。

1. 配列とスライスの代入形式

例 1

arr1 := [3] int {1,2,3}
arr2 := arr1
for k := range arr1 {
    fmt.Printf("%v ",&arr1[k]);
}

fmt.Println("");

for k := range arr2 {
    fmt.Printf("%v ",&arr2[k]);
}

fmt.Println("\n=================");

slice1 := [] int{1,2,3}
slice2 := slice1
for k := range slice1 {
    fmt.Printf("%v ",&slice1[k]);
}
fmt.Println("");
for k := range slice2 {
    fmt.Printf("%v ",&slice2[k]);
}

输出结果:
0xc420014140 0xc420014148 0xc420014150 
0xc420014160 0xc420014168 0xc420014170 
=================
0xc4200141a0 0xc4200141a8 0xc4200141b0 
0xc4200141a0 0xc4200141a8 0xc4200141b0

この例からわかるように、array割り当ては値のコピーであり、まったく新しい配列です。スライスの割り当ては参照 です。別の例を見てみましょう。

例 2:

arr1 := [3] int {1,2,3}
arr2 := arr1
fmt.Printf("%v %v ",arr1,arr2);

arr1[0] = 11
arr2[1] = 22
fmt.Printf("\n%v %v ",arr1,arr2);

fmt.Println("\n================");

slice1 := [] int{1,2,3}
slice2 := slice1
fmt.Printf("%v %v ",slice1,slice2);

slice1[0] = 11
slice2[1] = 22
fmt.Printf("\n%v %v ",slice1,slice2);

输出结果:
[1 2 3] [1 2 3] 
[11 2 3] [1 22 3] 
================
[1 2 3] [1 2 3] 
[11 22 3] [11 22 3]

この例は、配列が代入およびコピーであるのに対し、スライスは単なる参照であることをもう一度示します。例 1 と 2 のスライス宣言では、隠し配列が使用されています。非表示でない配列を使用した例 3 をもう一度見てみましょう。

例 3:

arr1 := [5] int {1,2,3}
slice1 := arr1[0:3]
slice2 := slice1[0:4]

fmt.Printf("len: %d cap: %d %v\n",len(arr1),cap(arr1),arr1); //打印出非隐藏数组
for k := range arr1 {
    fmt.Printf("%v ",&arr1[k]);
}

fmt.Println("");

fmt.Printf("len: %d cap: %d %v\n",len(slice1),cap(slice1),slice1); //打印切片1
for k := range slice1 {
    fmt.Printf("%v ",&slice1[k]);
}

fmt.Println("");

fmt.Printf("len: %d cap: %d %v\n",len(slice2),cap(slice2),slice2); //打印切片2
for k := range slice2 {
    fmt.Printf("%v ",&slice2[k]);
}
fmt.Println("\n=================");

arr1[0] = 11   //非隐藏数组、切片1、切片2各自发生更改
slice1[1] = 22
slice2[2] = 33

fmt.Printf("len: %d cap: %d %v\n",len(arr1),cap(arr1),arr1); //再次打印非隐藏数组
for k := range arr1 {
    fmt.Printf("%v ",&arr1[k]);
}

fmt.Println("");

fmt.Printf("len: %d cap: %d %v\n",len(slice1),cap(slice1),slice1); //再此打印切片1
for k := range slice1 {
    fmt.Printf("%v ",&slice1[k]);
}
fmt.Println("");

fmt.Printf("len: %d cap: %d %v\n",len(slice2),cap(slice2),slice2); //再次打印切片2
for k := range slice2 {
    fmt.Printf("%v ",&slice2[k]);
}

输出结果:
len: 5 cap: 5 [1 2 3 0 0]0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170 
len: 3 cap: 5 [1 2 3]0xc420012150 0xc420012158 0xc420012160 len: 4 cap: 5 [1 2 3 0]0xc420012150 0xc420012158 0xc420012160 0xc420012168 
=================
len: 5 cap: 5 [11 22 33 0 0]
0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170 
len: 3 cap: 5 [11 22 33]
0xc420012150 0xc420012158 0xc420012160 
len: 4 cap: 5 [11 22 33 0]
0xc420012150 0xc420012158 0xc420012160 0xc42001216

上記の 3 つの例を要約すると、スライスは、非表示の配列および非表示の配列への参照を含む、配列への参照であることがわかります。

2. 配列はパラメータとして使用され、関数

によって呼び出されます。
func Connect() {
    arr1 := [5] int {1,2,3}
    fmt.Printf("%v ",arr1);
    for k := range arr1 {
        fmt.Printf("%v ",&arr1[k]);
    }
    fmt.Println("");
    f1(arr1)
    fmt.Println("");
    f2(&arr1)
}
func f1(arr [5]int) {
    fmt.Printf("%v ",arr);
    for k := range arr {
        fmt.Printf("%v ",&arr[k]);
    }
}
func f2(arr *[5]int) {
    fmt.Printf("%v ",arr);
    for k := range arr {
        fmt.Printf("%v ",&arr[k]);
    }
}

输出结果:
[1 2 3 0 0]  0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170 
[1 2 3 0 0]  0xc4200121b0 0xc4200121b8 0xc4200121c0 0xc4200121c8 0xc4200121d0 
&[1 2 3 0 0] 0xc420012150 0xc420012158 0xc420012160 0xc420012168 0xc420012170

从上面的例子可以看出,数组在参数中,可以使用值传递和引用传递。值传递会拷贝新数组,引用传递则使用原数组。

func Connect() {
    slice1 := [] int {1,2,3}
    fmt.Printf("%v ",slice1);
    for k := range slice1 {
        fmt.Printf("%v ",&slice1[k]);
    }
    fmt.Println("");
    f1(slice1)
}
func f1(slice []int) {
    fmt.Printf("%v ",slice);
    for k := range slice {
        fmt.Printf("%v ",&slice[k]);
    }
}

输出结果:
[1 2 3] 0xc420014140 0xc420014148 0xc420014150 
[1 2 3] 0xc420014140 0xc420014148 0xc42001415

从这个例子中可以看出,切片在参数中传递本身就引用。

总结:

  • 切片是指针类型,数组是值类型

  • 数组的赋值形式为值传递,切片的赋值形式为引用传递

  • 数组的长度是固定的,而切片长度可以任意调整(切片是动态的数组)

  • 数组只有长度一个属性,而切片比数组多了一个容量(cap)属性

【相关推荐:Go视频教程编程教学

以上がGo言語の配列とスライスの違いは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

GolangisidealforBuildingsCalables Systemsduetoitsefficiency andConcurrency、Whilepythonexcelsinquickscriptinganddataanalysisduetoitssimplicityand vastecosystem.golang'ssignencouragesclean、readisinediteNeditinesinedinediseNabletinedinedinedisedisedioncourase

Golang and C:Concurrency vs. Raw SpeedGolang and C:Concurrency vs. Raw SpeedApr 21, 2025 am 12:16 AM

Golangは並行性がCよりも優れていますが、Cは生の速度ではGolangよりも優れています。 1)Golangは、GoroutineとChannelを通じて効率的な並行性を達成します。これは、多数の同時タスクの処理に適しています。 2)Cコンパイラの最適化と標準ライブラリを介して、極端な最適化を必要とするアプリケーションに適したハードウェアに近い高性能を提供します。

なぜゴランを使うのですか?説明された利点と利点が説明されていますなぜゴランを使うのですか?説明された利点と利点が説明されていますApr 21, 2025 am 12:15 AM

Golangを選択する理由には、1)高い並行性パフォーマンス、2)静的タイプシステム、3)ガベージ収集メカニズム、4)豊富な標準ライブラリとエコシステムは、効率的で信頼できるソフトウェアを開発するための理想的な選択肢となります。

Golang vs. C:パフォーマンスと速度の比較Golang vs. C:パフォーマンスと速度の比較Apr 21, 2025 am 12:13 AM

Golangは迅速な発展と同時シナリオに適しており、Cは極端なパフォーマンスと低レベルの制御が必要なシナリオに適しています。 1)Golangは、ごみ収集と並行機関のメカニズムを通じてパフォーマンスを向上させ、高配列Webサービス開発に適しています。 2)Cは、手動のメモリ管理とコンパイラの最適化を通じて究極のパフォーマンスを実現し、埋め込みシステム開発に適しています。

GolangはCよりも速いですか?制限の調査GolangはCよりも速いですか?制限の調査Apr 20, 2025 am 12:19 AM

Golangは、コンピレーション時間と同時処理においてより良いパフォーマンスを発揮しますが、Cはランニング速度とメモリ管理においてより多くの利点があります。 1.Golangの編集速度は速く、迅速な発展に適しています。 2.Cは速く実行され、パフォーマンスクリティカルなアプリケーションに適しています。 3. Golangは、同時処理においてシンプルで効率的で、同時プログラミングに適しています。 4.Cマニュアルメモリ管理により、パフォーマンスが高くなりますが、開発の複雑さが向上します。

Golang:WebサービスからシステムプログラミングまでGolang:WebサービスからシステムプログラミングまでApr 20, 2025 am 12:18 AM

WebサービスとシステムプログラミングへのGolangのアプリケーションは、主にそのシンプルさ、効率性、並行性に反映されています。 1)Webサービスでは、Golangは、強力なHTTPライブラリと同時処理機能を介して、高性能WebアプリケーションとAPIの作成をサポートしています。 2)システムプログラミングでは、Golangはハードウェアに近い機能とC言語との互換性を使用して、オペレーティングシステムの開発と組み込みシステムに適しています。

Golang vs. C:ベンチマークと現実世界のパフォーマンスGolang vs. C:ベンチマークと現実世界のパフォーマンスApr 20, 2025 am 12:18 AM

GolangとCには、パフォーマンスの比較に独自の利点と欠点があります。1。ゴーランは、高い並行性と迅速な発展に適していますが、ごみ収集はパフォーマンスに影響を与える可能性があります。 2.Cは、パフォーマンスとハードウェア制御を高くしますが、開発の複雑さが高くなります。選択を行うときは、プロジェクトの要件とチームのスキルを包括的な方法で考慮する必要があります。

Golang vs. Python:比較分析Golang vs. Python:比較分析Apr 20, 2025 am 12:17 AM

Golangは、高性能および同時プログラミングシナリオに適していますが、Pythonは迅速な開発とデータ処理に適しています。 1.Golangは、シンプルさと効率性を強調し、バックエンドサービスとマイクロサービスに適しています。 2。Pythonは、データサイエンスと機械学習に適した簡潔な構文とリッチライブラリで知られています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、