ホームページ システムチュートリアル Linux Go でスライスの容量と長さを操作するためのヒント

Go でスライスの容量と長さを操作するためのヒント

Mar 20, 2024 pm 02:36 PM
linux Linuxチュートリアル レッドハット Linuxシステム Linuxコマンド Linux 認定 レッドハットリナックス Linuxビデオ

在 Go 中使用切片的容量和长度的技巧

クイック テスト - 次のコードは何を出力しますか?

vals := make([]int, 5)
for i := 0; i 
<p>[0 0 0 0 0 0 1 2 3 4] と推測した方は正解です。 </p>
<p> テストで間違えても心配する必要はありません。これは Go 言語に移行するときによくある間違いです。この記事では、出力が期待したものと異なる理由と、Go のニュアンスを利用してコードをより効率的にする方法について説明します。 </p>
<div style="font-size: 14pt; color: white; background-color: black; border-left: red 10px solid; padding-left: 14px; margin-bottom: 20px; margin-top: 20px;"><strong>スライスと配列</strong></div><p>Go には配列とスライスの両方があります。戸惑うかもしれませんが、慣れてしまえばきっと気に入ります。お願い、私を信じて。 </p>
<p> スライスと配列の間には多くの違いがありますが、この記事で焦点を当てるのは、配列のサイズがその型の一部であるのに対し、スライスは動的サイズを持つことができるということです。スライスは、スライスのラッパーであるためです。配列。 </p>
<p>これは実際には何を意味するのでしょうか?したがって、配列 val a[10]int があるとします。配列のサイズは固定されており、変更できません。 len(a) を呼び出すと、このサイズは型の一部であるため、常に 10 が返されます。したがって、配列内に突然 10 個を超える項目が必要になった場合は、まったく異なるタイプの新しいオブジェクト (たとえば val b[11]int) を作成し、すべての値を a から b にコピーする必要があります。 </p>
<p> コレクション サイズの配列が価値のある特定の状況がありますが、一般的に言えば、これは開発者が望んでいることではありません。代わりに、彼らは Go の配列に似た、時間の経過とともに拡張できる機能を使用したいと考えていました。大雑把な方法は、必要以上に大きな配列を作成し、その配列のサブセットを配列として扱うことです。以下のコードは例です。 </p>
<pre class="brush:php;toolbar:false">var vals [20]int
for i := 0; i 
<p>コードでは長さ 20 の配列がありますが、サブセットのみを使用しているため、コードでは配列の長さが 5 であり、新しい項目を追加した後は 6 になると想定できます。配列 。 </p>
<p>これは (非常に大まかに) スライスの仕組みです。これらには、前の例のサイズ 20 の配列のように、サイズが設定された配列が含まれています。 </p>
<p>また、プログラムで使用される配列のサブセットも追跡します。これは append 属性で、前の例の subsetLen 変数に似ています。 </p>
<p>最後に、スライスには容量もあります。これは、前の例の配列の全長 (20) に似ています。これは、スライス配列に収まらなくなる前にサブセットのサイズが増加できることがわかるため、便利です。これが発生した場合、新しい配列を割り当てる必要がありますが、このロジックはすべて append 関数の背後に隠されています。 </p>
<p>つまり、append 関数を使用してスライスを結合すると、非常に配列に似た型が得られますが、時間が経つにつれて、より多くの要素を処理できるようになります。 </p>
<p> 前の例をもう一度見てみましょう。今回は配列の代わりにスライスを使用します。 </p>
<pre class="brush:php;toolbar:false">var vals []int
for i := 0; i 
<p> 配列と同じようにスライス内の要素にアクセスできますが、スライスと append 関数を使用することで、その背後にある配列のサイズを考慮する必要がなくなりました。 len 関数と cap 関数を使用することでこの問題を解決できますが、それほど心配する必要はありません。シンプルですよね? </p><div style="font-size: 14pt; color: white; background-color: black; border-left: red 10px solid; padding-left: 14px; margin-bottom: 20px; margin-top: 20px;"><strong>テストに戻る</strong></div>
<p>これを念頭に置いて、前回のテストを見直し、何が問題だったのかを見てみましょう。 </p>
<pre class="brush:php;toolbar:false">vals := make([]int, 5)
for i := 0; i 
<p>make を呼び出すとき、最大 3 つのパラメーターを渡すことができます。 1 つ目は割り当てたタイプ、2 つ目はタイプの「長さ」、3 つ目はタイプの「容量」です (このパラメータはオプションです)。 </p>
<p>引数 make([]int, 5) を渡すことによって、長さ 5 のスライスを作成することをプログラムに伝えます。この場合、デフォルトの容量は長さと同じです (この場合は 5)。 </p>
<p>これは希望どおりに見えるかもしれませんが、ここでの重要な違いは、新しい要素を追加した後の最初の要素に 5 つの要素が必要であると仮定して、スライスに「長さ」と「容量」を 5 に設定するように指示していることです。次に、append 関数を呼び出します。これにより、容量のサイズが増加し、スライスの最後に新しい要素が追加されます。 </p>
<p>Println() ステートメントをコードに追加すると、容量の変化が確認できます。 </p>
<pre class="brush:php;toolbar:false">vals := make([]int, 5)
fmt.Println("容量は次のとおりです:", cap(vals))
for i := 0; i 
<p>最終的には、目的の [0 1 2 3 4] ではなく、[0 0 0 0 0 0 1 2 3 4] という出力が得られます。 </p>
<p>それを修正するにはどうすればよいですか?これを行うにはいくつかの方法があります。ここでは 2 つを説明します。シナリオに最も役立つ方法を選択してください。 </p>
<div style="font-size: 14pt; color: white; background-color: black; border-left: red 10px solid; padding-left: 14px; margin-bottom: 20px; margin-top: 20px;"><strong>追加ではなくインデックス書き込みを直接使用します</strong></div>
<p>最初の修正は、make 呼び出しを変更せずに残し、インデックスを使用して各要素を明示的に設定することです。このようにして、次のコードが得られます: </p>
<pre class="brush:php;toolbar:false">vals := make([]int, 5)
for i := 0; i 
<p> この場合、使用したいインデックスとまったく同じ値を値に設定しますが、インデックスを個別に追跡することもできます。 </p>
<p>たとえば、マップのキーを取得したい場合は、次のコードを使用できます。 </p>
<pre class="brush:php;toolbar:false">パッケージメイン

「fmt」をインポートします

関数 main() {
  fmt.Println(keys(map[string]struct{}{
    "犬": 構造体{}{}、
    "猫": 構造体{}{}、
  }))
}

func キー(m マップ[文字列]構造{}) []文字列 {
  ret := make([]string, len(m))
  私:= 0
  for key := range m {
    ret[i] = キー
    私
  }
  リターンレット
}
ログイン後にコピー

これは良いことです。返されるスライスの長さがマップの長さと同じであることがわかっているので、スライスをその長さで初期化し、各要素を適切なインデックスに割り当てることができます。このアプローチの欠点は、各インデックスに設定する値を知るために i を追跡しなければならないことです。

これで 2 番目の方法がわかります...

長さとして 0 を使用し、容量を指定します

追加する値のインデックスを追跡する代わりに、make 呼び出しを更新し、スライス タイプの後に 2 つの引数を指定できます。まず、スライスにまだ新しい要素を追加していないため、新しいスライスの長さは 0 に設定されます。次に、スライスには最終的に多くの文字列が追加されることがわかっているため、新しいスライスの容量はマップ パラメーターの長さに設定されます。

これでも、前の例と同じ配列をバックグラウンドで構築しますが、スライスの長さが 0 であるため、append を呼び出すと、配列がスライスの先頭に配置されます。

パッケージメイン

「fmt」をインポートします

関数 main() {
  fmt.Println(keys(map[string]struct{}{
    "犬": 構造体{}{}、
    "猫": 構造体{}{}、
  }))
}

func キー(m マップ[文字列]構造{}) []文字列 {
  ret := make([]string, 0, len(m))
  for key := range m {
    ret = append(ret, key)
  }
  リターンレット
}
ログイン後にコピー
append がそれを処理するのであれば、なぜ容量について心配する必要があるのでしょうか?

次に、「追加機能でスライスの容量を増やすことができるのであれば、なぜプログラムに容量を指示する必要があるのでしょうか?」と疑問に思うかもしれません。

実のところ、ほとんどの場合、これについてはあまり心配する必要はありません。コードがより複雑になる場合は、var vals []int でスライスを初期化し、残りを append 関数に処理させます。

しかし、この状況は異なります。これは容量を宣言することの難しさを示す例ではありません。実際、提供されたマップに直接マッピングされることがわかっているため、スライスの最終容量を決定するのは簡単です。したがって、初期化するときにスライスの容量を宣言し、プログラムが不必要なメモリ割り当てを実行するのを防ぐことができます。

追加のメモリ割り当てを確認したい場合は、Go Playground で次のコードを実行します。容量が増加するたびに、プログラムはメモリを割り当てる必要があります。

パッケージメイン 「fmt」をインポートします 関数 main() { fmt.Println(keys(map[string]struct{}{ "犬": 構造体{}{}、 "猫": 構造体{}{}、 "マウス": 構造体{}{}、 「オオカミ」: 構造体{}{}、 「ワニ」: 構造体{}{}、 })) } func キー(m マップ[文字列]構造{}) []文字列 { var ret[]文字列 fmt.Println(cap(ret)) for key := range m { ret = append(ret, key) fmt.Println(cap(ret)) } リターンレット }
ログイン後にコピー
ログイン後にコピー
次に、これを同じコードと、事前に定義された容量を使用したコードと比較します。

パッケージメイン 「fmt」をインポートします 関数 main() { fmt.Println(keys(map[string]struct{}{ "犬": 構造体{}{}、 "猫": 構造体{}{}、 "マウス": 構造体{}{}、 「オオカミ」: 構造体{}{}、 「ワニ」: 構造体{}{}、 })) } func キー(m マップ[文字列]構造{}) []文字列 { ret := make([]string, 0, len(m)) fmt.Println(cap(ret)) for key := range m { ret = append(ret, key) fmt.Println(cap(ret)) } リターンレット }
ログイン後にコピー
ログイン後にコピー
最初のコード例では、容量は 0 から始まり、1、2、4、そして最後に 8 と増加しました。つまり、配列を 5 回割り当てる必要があり、最後の割り当てにはスライスした配列が保持されていました。は 8 で、最終的に必要な値よりも大きくなります。

一方、2 番目の例は同じ容量 (5) で開始および終了し、keys() 関数の先頭で 1 回割り当てるだけで済みます。また、余分なメモリの無駄を避け、この配列に適合する完璧なサイズのスライスを返します。

過剰な最適化を行わないでください
前に述べたように、私は通常、このような小さな最適化を行うことはお勧めしませんが、最終的なサイズの影響が非常に顕著である場合は、スライスに適切な容量または長さを設定してみることを強くお勧めします。

これはプログラムのパフォーマンスの向上に役立つだけでなく、入力のサイズと出力のサイズの関係を明示的に示すことでコードを明確にするのにも役立ちます。

要約
この記事は、スライスとアレイの違いについて詳しく説明するものではなく、容量と長さがスライスに与える影響と、シナリオでのスライスの使用方法について簡単に紹介します。


以上がGo でスライスの容量と長さを操作するためのヒントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

ホット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 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

VSCODEに必要なコンピューター構成 VSCODEに必要なコンピューター構成 Apr 15, 2025 pm 09:48 PM

VSコードシステムの要件:オペレーティングシステム:オペレーティングシステム:Windows 10以降、MACOS 10.12以上、Linux Distributionプロセッサ:最小1.6 GHz、推奨2.0 GHz以上のメモリ:最小512 MB、推奨4 GB以上のストレージスペース:最低250 MB以上:その他の要件を推奨:安定ネットワーク接続、XORG/WAYLAND(Linux)

VSCODEは拡張子をインストールできません VSCODEは拡張子をインストールできません Apr 15, 2025 pm 07:18 PM

VSコード拡張機能のインストールの理由は、ネットワークの不安定性、許可不足、システム互換性の問題、VSコードバージョンが古すぎる、ウイルス対策ソフトウェアまたはファイアウォール干渉です。ネットワーク接続、許可、ログファイル、およびコードの更新、セキュリティソフトウェアの無効化、およびコードまたはコンピューターの再起動を確認することにより、問題を徐々にトラブルシューティングと解決できます。

Apr 16, 2025 pm 07:39 PM

NotePadはJavaコードを直接実行することはできませんが、他のツールを使用することで実現できます。コマンドラインコンパイラ(Javac)を使用してByteCodeファイル(filename.class)を生成します。 Javaインタープリター(Java)を使用して、バイトコードを解釈し、コードを実行し、結果を出力します。

Linuxアーキテクチャ:5つの基本コンポーネントを発表します Linuxアーキテクチャ:5つの基本コンポーネントを発表します Apr 20, 2025 am 12:04 AM

Linuxシステムの5つの基本コンポーネントは次のとおりです。1。Kernel、2。Systemライブラリ、3。Systemユーティリティ、4。グラフィカルユーザーインターフェイス、5。アプリケーション。カーネルはハードウェアリソースを管理し、システムライブラリは事前コンパイルされた機能を提供し、システムユーティリティはシステム管理に使用され、GUIは視覚的な相互作用を提供し、アプリケーションはこれらのコンポーネントを使用して機能を実装します。

vscodeはMacに使用できますか vscodeはMacに使用できますか Apr 15, 2025 pm 07:36 PM

VSコードはMacで利用できます。強力な拡張機能、GIT統合、ターミナル、デバッガーがあり、豊富なセットアップオプションも提供しています。ただし、特に大規模なプロジェクトまたは非常に専門的な開発の場合、コードと機能的な制限がある場合があります。

vscodeの使用方法 vscodeの使用方法 Apr 15, 2025 pm 11:21 PM

Visual Studio Code(VSCODE)は、Microsoftが開発したクロスプラットフォーム、オープンソース、および無料のコードエディターです。軽量、スケーラビリティ、および幅広いプログラミング言語のサポートで知られています。 VSCODEをインストールするには、公式Webサイトにアクセスして、インストーラーをダウンロードして実行してください。 VSCODEを使用する場合、新しいプロジェクトを作成し、コードを編集し、コードをデバッグし、プロジェクトをナビゲートし、VSCODEを展開し、設定を管理できます。 VSCODEは、Windows、MacOS、Linuxで利用でき、複数のプログラミング言語をサポートし、マーケットプレイスを通じてさまざまな拡張機能を提供します。その利点には、軽量、スケーラビリティ、広範な言語サポート、豊富な機能とバージョンが含まれます

GITの倉庫アドレスを確認する方法 GITの倉庫アドレスを確認する方法 Apr 17, 2025 pm 01:54 PM

gitリポジトリアドレスを表示するには、次の手順を実行します。1。コマンドラインを開き、リポジトリディレクトリに移動します。 2。「git remote -v」コマンドを実行します。 3.出力と対応するアドレスでリポジトリ名を表示します。

vscodeとは何ですか?vscodeとは何ですか? vscodeとは何ですか?vscodeとは何ですか? Apr 15, 2025 pm 06:45 PM

VSコードは、Microsoftが開発した無料のオープンソースクロスプラットフォームコードエディターと開発環境であるフルネームVisual Studioコードです。幅広いプログラミング言語をサポートし、構文の強調表示、コード自動完了、コードスニペット、および開発効率を向上させるスマートプロンプトを提供します。リッチな拡張エコシステムを通じて、ユーザーは、デバッガー、コードフォーマットツール、GIT統合など、特定のニーズや言語に拡張機能を追加できます。 VSコードには、コードのバグをすばやく見つけて解決するのに役立つ直感的なデバッガーも含まれています。

See all articles