目次
間違った結論: ポインターを使用する方が良いでしょうか?
ホームページ バックエンド開発 Golang Go ポインターをいつ使用するか知っていますか?

Go ポインターをいつ使用するか知っていますか?

Sep 24, 2021 pm 03:08 PM
go ポインタ

この記事は、go language チュートリアルコラムで、Go ポインター (Go Pointer) がどのような状況で使用されるのかを紹介するものです。 !

Go ポインターをいつ使用するか知っていますか?

GOコードでのポインターの使用は、特に使用法のシナリオを区別するのが困難な場合、初心者にはそれほど友好的ではありません。

ポインターを使用する際の最大の誤解の 1 つは、Go のポインターが C 言語のポインターに非常に似ているということだと思います。しかし、そうではありません。 Go では、ポインタは C/C と同じように機能しません。

この記事では、Go ポインターを正しく使用する方法について説明します。

間違った結論: ポインターを使用する方が良いでしょうか?

一般に、ポインターを使用すると常に値をコピーする必要がなくなるため、アプリケーションの実行が高速になると考えられています。 Go でも同じ考えがあるのは不思議ではありません。

ただし、Go での ポインターの受け渡しは、通常、値の受け渡し よりも遅くなります。これは、Go がガベージ コレクション言語であることの結果です。関数へのポインタを渡すとき、Go はエスケープ解析を実行して、変数をヒープに格納するかスタックに格納するかを決定する必要があります。これによりすでに余分なオーバーヘッドが追加されていますが、それ以外の場合は変数をヒープに保存できます。変数をヒープに保存すると、GC の実行中に時間もロスします。

Go の便利な機能は、コマンド go build -gcflags="-m" を実行することで、エスケープ解析がどのように行われたかを確認できることです。これを行うと、Go は変数がヒープにエスケープするかどうかを教えてくれます:

./main.go:44:20: greet ... argument does not escape
./main.go:44:21: greeting escapes to heap
./main.go:44:21: name escapes to heap
ログイン後にコピー

変数がヒープにエスケープしない場合、変数はスタック上に残ります。スタックは変数をクリアするためにガベージ コレクターを必要とせず、push/pop 操作のみを実行します。

コンテンツが値によって渡される場合、そのコンテンツは常にスタック上で処理されるため、ガベージ コレクションのオーバーヘッドは発生しません。 (GC はデフォルトで実行されます。ヒープ内のコンテンツが少ないということは、GC が行うべき作業が少ないことを意味します)。

ポインターを使用するとパフォーマンスが低下することがわかりました。必要な場合はポインターを使用しますか?

大規模なデータ構造のコピー

ポインタのパフォーマンスは常に値の転送より悪いのでしょうか?明らかにそうではありません。大規模なデータ構造を扱う場合、ポインタが役に立ちます。これにより、ガベージ コレクションのコストが大量のデータのコピーのコストで相殺される可能性があります。

これについて話すと、「そのビッグデータはどのくらいの大きさにすべきですか?」といつも尋ねられます。

ここに固定値はないと思いますが、パフォーマンスに関連するものはすべてベンチマークする必要があります。 Go には強力なベンチマーク ツールが組み込まれており、これを最大限に活用できます。

変数

関数のパラメーターを変更する唯一の方法は、ポインターを渡すことです。デフォルトでは、値の変更はコピーに対して実行されます。したがって、これらの変更は、それを呼び出す関数に反映できません。

次のコードを見てください:

type person struct {
 name string
}func main() {
 p := person{"Richard"}
 rename(p)
 fmt.Println(p)
}func rename(p person) {
 p.name = "test"
}
ログイン後にコピー
person への変更はそのコピーに対して実行されるため、出力は

Richard になります。基になる人物オブジェクトの値を変更する場合は、ポインターを使用する必要があります。

func main() {
 p := person{"Richard"}
 rename(&p)
 fmt.Println(p)
}func rename(p *person) {
 p.name = "test"
}
ログイン後にコピー
上記と同様に、

testを出力します。可変性とは、Go でポインターが使用される状況です。これが良いことなのかどうかは議論の余地がある。

API の一貫性

ポインターを使用して最新の値を維持します。これにより、すべてのメソッドがその値を変更しない場合でも、API の一貫性が保たれます。

したがって、これ:

func (p *person) rename(s string) {
   p.name = s 
}func (p *person) printName() {
  fmt.Println(p.name)
}
ログイン後にコピー

func (p *person) rename(s string) {
   p.name = s 
}func (p person) printName() {
  fmt.Println(p.name)
}
ログイン後にコピー
よりも優れていますが、一貫性のために

printName でポインターを使用する必要はありません。ただし、これにより API が簡素化され、参照が必要な場所を正確に覚えておく必要がなくなります。

欠落していることを示します

一般的な値を使用する場合、デフォルト値はゼロになります。ただし、何かが欠落しているか、値が入力されていないことを知る必要があるシナリオもあります。たとえば、構造体には学生のテストのスコアが含まれています。構造体が空でスコアが 0 の場合、学生はテストの成績が良くなかった、またはテストをまったく受けなかったことを意味しますか?

ポインターのデフォルトのゼロ値は

nil ポインターであり、値が設定されていないことを意味します。この要件は、次のように実装することもできます。

type exam struct {
    score   int
    present bool
}
ログイン後にコピー
別の

present フィールドを使用して、学生が試験を受けなかったことを示します。

価値を選択する理由は何ですか?

#これはやや主観的なものです。プログラミングに対する理解は人によって異なるため、同じ概念を持つ必要はありません。

Go では可能な限りデフォルト値を使用することが合理的であると考えています。これはすべての状況で機能するわけではありませんが、私の場合は大きな事故を防ぐことができました。ポインターの代わりに値を使用すると、NULL ポインターによるトニー・ホアの「100 万ドルの間違い」は発生しません。

デフォルト値のゼロは、多数の宣言を避けるのに役立ちます。

另一个好处是易变性造成的问题比它解决的问题多的得多。易变性给函数带来的副作用同时使得调试变得更加困难。 通过让函数返回修改之后的结构体,可以避免这种突变。

重写之前的例子

func main() {
 p := person{"richard"}
 p = rename(p)
 fmt.Println(p)
}func rename(p person) person {
 p.name = "test"
 return p
}
ログイン後にコピー

这也是 append 如何工作的,所以并不陌生。

x := []int{1,2}
x = append(x, 3)
x = append(x, 4)
ログイン後にコピー

鉴于指针的安全性,和值处理比指针处理更快,使用指针需要反复斟酌。

原文地址:https://medium.com/@meeusdylan/when-to-use-pointers-in-go-44c15fe04eac

译文地址:https://learnku.com/go/t/60923

以上が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衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Go WebSocket メッセージを送信するにはどうすればよいですか? Go WebSocket メッセージを送信するにはどうすればよいですか? Jun 03, 2024 pm 04:53 PM

Go では、gorilla/websocket パッケージを使用して WebSocket メッセージを送信できます。具体的な手順: WebSocket 接続を確立します。テキスト メッセージを送信します。 WriteMessage(websocket.TextMessage,[]byte("message")) を呼び出します。バイナリ メッセージを送信します。WriteMessage(websocket.BinaryMessage,[]byte{1,2,3}) を呼び出します。

Golang の技術的なパフォーマンスの最適化でメモリ リークを回避するにはどうすればよいですか? Golang の技術的なパフォーマンスの最適化でメモリ リークを回避するにはどうすればよいですか? Jun 04, 2024 pm 12:27 PM

メモリ リークは、ファイル、ネットワーク接続、データベース接続などの使用されなくなったリソースを閉じることによって、Go プログラムのメモリを継続的に増加させる可能性があります。弱参照を使用してメモリ リークを防ぎ、強参照されなくなったオブジェクトをガベージ コレクションの対象にします。 go coroutine を使用すると、メモリ リークを避けるために、終了時にコルーチンのスタック メモリが自動的に解放されます。

Go で正規表現を使用してタイムスタンプを照合するにはどうすればよいですか? Go で正規表現を使用してタイムスタンプを照合するにはどうすればよいですか? Jun 02, 2024 am 09:00 AM

Go では、正規表現を使用してタイムスタンプを照合できます。ISO8601 タイムスタンプの照合に使用されるような正規表現文字列をコンパイルします。 ^\d{4}-\d{2}-\d{2}T \d{ 2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ 。 regexp.MatchString 関数を使用して、文字列が正規表現と一致するかどうかを確認します。

GolangとGo言語の違い GolangとGo言語の違い May 31, 2024 pm 08:10 PM

Go と Go 言語は、異なる特性を持つ別個の存在です。 Go (Golang とも呼ばれます) は、同時実行性、高速なコンパイル速度、メモリ管理、およびクロスプラットフォームの利点で知られています。 Go 言語の欠点としては、他の言語に比べてエコシステムが充実していないこと、構文が厳格であること、動的型付けが欠如していることが挙げられます。

C++ でのポインターと参照の詳細な分析によるメモリ使用量の最適化 C++ でのポインターと参照の詳細な分析によるメモリ使用量の最適化 Jun 02, 2024 pm 07:50 PM

ポインターと参照を使用すると、C++ でのメモリ使用量を最適化できます。 ポインター: 他の変数のアドレスを格納し、別の変数を指すことができるため、メモリが節約されますが、ワイルド ポインターが生成される可能性があります。参考: 別の変数にエイリアスされ、常に同じ変数を指し、ワイルド ポインターを生成せず、関数パラメーターに適しています。メモリ使用量を最適化すると、不必要なコピーを回避し、メモリ割り当てを削減し、スペースを節約することにより、コードの効率とパフォーマンスを向上させることができます。

Go 同時関数の単体テストのガイド Go 同時関数の単体テストのガイド May 03, 2024 am 10:54 AM

並行関数の単体テストは、同時環境での正しい動作を確認するのに役立つため、非常に重要です。同時実行機能をテストするときは、相互排他、同期、分離などの基本原則を考慮する必要があります。並行機能は、シミュレーション、競合状態のテスト、および結果の検証によって単体テストできます。

Golang フレームワークのドキュメントのベスト プラクティス Golang フレームワークのドキュメントのベスト プラクティス Jun 04, 2024 pm 05:00 PM

明確で包括的なドキュメントを作成することは、Golang フレームワークにとって非常に重要です。ベスト プラクティスには、Google の Go コーディング スタイル ガイドなど、確立されたドキュメント スタイルに従うことが含まれます。見出し、小見出し、リストなどの明確な組織構造を使用し、ナビゲーションを提供します。スタート ガイド、API リファレンス、概念など、包括的で正確な情報を提供します。コード例を使用して、概念と使用法を説明します。ドキュメントを常に最新の状態に保ち、変更を追跡し、新機能を文書化します。 GitHub の問題やフォーラムなどのサポートとコミュニティ リソースを提供します。 API ドキュメントなどの実践的なサンプルを作成します。

Go WebSocket はどのようにデータベースと統合しますか? Go WebSocket はどのようにデータベースと統合しますか? Jun 05, 2024 pm 03:18 PM

GoWebSocket をデータベースと統合する方法: データベース接続をセットアップする: データベースに接続するには、database/sql パッケージを使用します。 WebSocket メッセージをデータベースに保存する: INSERT ステートメントを使用して、メッセージをデータベースに挿入します。データベースから WebSocket メッセージを取得する: データベースからメッセージを取得するには、SELECT ステートメントを使用します。

See all articles