ポインタとメソッドの値の違い

Linda Hamilton
リリース: 2024-11-26 01:35:15
オリジナル
351 人が閲覧しました

The difference between pointers and values on methods

Go でメソッドを記述する場合、重要な決定の 1 つは、構造体を値で渡すかポインターで渡すかです。この選択は、パフォーマンス、コードの動作、メモリ割り当てに影響を与える可能性があります。この投稿では、実際の例を使用してこの違いを検討し、それぞれのアプローチがどのような場合に適切であるかを理解します。

小さな構造体と 2 つのメソッドから始めましょう。1 つは構造体が値によって渡され、もう 1 つはポインタによって渡されます。

package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

// Method with struct passed by value
func (p Person) CelebrateBirthdayValue() {
    p.Age++
}

// Method with struct passed by pointer
func (p *Person) CelebrateBirthdayPointer() {
    p.Age++
}

func main() {
    person := Person{Name: "Alice", Age: 30}

    // Passing by value
    person.CelebrateBirthdayValue()
    fmt.Println("After CelebrateBirthdayValue:", person.Age) // Output: 30

    // Passing by pointer
    person.CelebrateBirthdayPointer()
    fmt.Println("After CelebrateBirthdayPointer:", person.Age) // Output: 31
}
ログイン後にコピー
ログイン後にコピー

値とポインタの違い

構造体をメソッドに値で渡すと、Go は構造体のコピーを作成します。独立したコピーを使用しているため、メソッド内の構造体に加えられた変更は元の構造体には影響しません。

一方、構造体をポインタで渡す場合は、元の構造体のメモリ アドレスを渡します。これは、同じインスタンスを操作しているため、メソッド内の構造体に加えられた変更は、元の構造体を直接変更することを意味します。

要約:

  • 値による: メソッドは構造体のコピーを受け取り、新しいメモリ空間を作成します。

  • ポインタによる: メソッドは、同じメモリ空間を指す、元の構造体のメモリ アドレスを受け取ります。

ヒープ

構造体が値によって渡されると、コピーがスタックに割り当てられます。これは一般に高速で効率的です。ただし、構造体が大きい場合、コピーによって大量のスタック メモリが消費される可能性があります。

構造体がポインターによって渡される場合、ポインター自体はスタック上に割り当てられますが、特に new、make を使用して作成された場合、または匿名関数によってキャプチャされた場合には、元の構造体がヒープ上に割り当てられる可能性があります。

ヒープ割り当ては、割り当て時間とガベージ コレクションの点でより高価ですが、構造体全体をコピーせずに大量のデータを効率的に操作できます。

各アプローチをいつ使用するか

値による

構造体を値で渡すことは、次の場合に役立ちます。

  • 元の構造体が変更されていないことを確認したいと考えています。
  • 構造体は小さいため、コピーしてもパフォーマンスに大きな影響はありません。
  • このメソッドは、内部状態を変更する必要なく、単にデータを読み取るだけです。

例:

func (p Person) GetName() string {
    return p.Name
}
ログイン後にコピー

ここで、GetName は Name フィールドのみを読み取り、構造体の状態を変更せずに文字列を返します。

ポインタによる

ポインターによる構造体受け渡しは、次の場合に有益です。

  • 元の構造体を変更する必要があります。
  • 構造体は大きいため、そのデータをコピーするとメモリとパフォーマンスの面でコストがかかります。
  • コードの効率を向上させるために、不必要なコピーを避けたいと考えています。

例:

package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

// Method with struct passed by value
func (p Person) CelebrateBirthdayValue() {
    p.Age++
}

// Method with struct passed by pointer
func (p *Person) CelebrateBirthdayPointer() {
    p.Age++
}

func main() {
    person := Person{Name: "Alice", Age: 30}

    // Passing by value
    person.CelebrateBirthdayValue()
    fmt.Println("After CelebrateBirthdayValue:", person.Age) // Output: 30

    // Passing by pointer
    person.CelebrateBirthdayPointer()
    fmt.Println("After CelebrateBirthdayPointer:", person.Age) // Output: 31
}
ログイン後にコピー
ログイン後にコピー

この場合、UpdateName は元の構造体の Name フィールドを直接変更します。これは、コピーを作成するよりも効率的です。

結論

Go でメソッドを作成するときに、構造体を値で渡すかポインターで渡すかを決定することは、パフォーマンス、コードの動作、メモリ割り当てに影響を与える可能性がある重要な選択です。

値による受け渡しは、メソッド内で構造体の不変性を確保するのに役立ちますが、ポインターによる受け渡しは、元の構造体を変更して、より大きな構造体を操作する場合のパフォーマンスを最適化するために不可欠です。

以上がポインタとメソッドの値の違いの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート