ホームページ  >  記事  >  バックエンド開発  >  Golang 関数のメモリ安全プログラミングの実践

Golang 関数のメモリ安全プログラミングの実践

WBOY
WBOYオリジナル
2024-04-23 13:12:02416ブラウズ

Go でメモリセーフなコードを記述することは、プログラムのクラッシュ、データの破損、セキュリティの脆弱性を防ぐために重要です。実践方法としては、ポインタの受け渡し、スライス容量の使用、バッファ オーバーフローの回避、慎重にスライスを使用すること、make() を使用してスライスとマップを作成すること、defer を使用してリソースを解放すること、sync.Mutex を使用して同時アクセスを同期することなどが挙げられます。これらのプラクティスに従うと、コードの堅牢性と信頼性が向上し、実際のケースに反映される可能性があります。

Golang 関数のメモリ安全プログラミングの実践

Go の関数型メモリセーフ プログラミングの実践

Go でメモリセーフなコードを記述することは、プログラムのクラッシュ、データ破損、セキュリティの脆弱性を防ぐために重要です。次の実践に従うと、コードの堅牢性と信頼性を向上させることができます。

ポインターの受け渡し

値 (T) の代わりにポインター (*T) を渡すことで、渡された値が誤って変更されるのを防ぎます。 。例:

func Swap(a, b *int) {
  *a, *b = *b, *a
}

スライス容量の使用

スライス ([]T) は基礎となる配列に基づいているため、その容量を理解することが重要です。容量はアレイの最大長を表します。容量を超えると、Go はより大きな基本配列を自動的に割り当て、スライスのアドレスを変更します。

次のコードは、これを示しています。

s := []int{1, 2, 3}
println(len(s), cap(s))  // 3 3

s = append(s, 4)
println(len(s), cap(s))  // 4 6

バッファ オーバーフローの回避

#​​##バッファ オーバーフローは、保存されているデータの量が、割り当てられているバッファを超えると発生します。 Go では、次の方法を使用してこの状況を回避できます。

    固定長配列を使用する: 配列にはコンパイル時に固定スペースが割り当てられ、オーバーフローしないことが保証されます。
  • スライスを使用し、その容量を適切に管理する: スライスの長さと容量を追跡し、必要に応じて調整します。
  • 使用
  • copy() 関数: copy() コピーされたデータの量がターゲット バッファの容量を超えないようにします。
スライスの使用には注意してください

スライスは基礎となる配列を共有するため、メモリセーフなタイプではありません。スライスへの変更は、同じ配列を使用する他の変数に予期せず影響を与える可能性があります。

次の例はこれを示しています。

s1 := []int{1, 2, 3}
s2 := s1[1:]

s1[0] = 4
println(s1)  // [4 2 3]
println(s2)  // [2 3]

make()make()

を使用してスライスとマップを作成する スライスとマップを明示的に作成すると、次のことが可能になります。初期容量を指定することで、不必要な割り当てを回避できます。

defer を使用してリソースを解放します。

defer ステートメントは、関数が戻る前にコードのブロックが実行されるようにします。これは、開いているファイルやネットワーク接続などのリソースを解放するのに役立ちます。

次の例では、defer を使用してファイルを閉じます:

func main() {
  file, err := os.Open("file.txt")
  if err != nil {
    return
  }
  defer file.Close()
  // 执行其他操作
}

Using sync.Mutex

sync。 Mutex は、共有リソースへの同時アクセスを同期するために使用されるミューテックス ロックです。

Mutex

Lock() メソッドと Unlock() メソッドを使用してロックを取得および解放できます。 次の例では、sync.Mutex を使用して、共有データへの同時アクセスを保護します。

var mu sync.Mutex
var count int

func main() {
  for i := 0; i < 10; i++ {
    go func() {
      mu.Lock()
      defer mu.Unlock()
      count++
    }()
  }
  // 等待所有协程完成
}

実用的なケース次の交差を計算する計算を考えてみましょう。 2 つのスライス 関数:

func Intersection(s1, s2 []int) []int {
  var res []int
  for _, v1 := range s1 {
    for _, v2 := range s2 {
      if v1 == v2 {
        res = append(res, v1)
      }
    }
  }
  return res
}

次の原則に従うことで、この関数のメモリの安全性を向上させることができます:

スライス容量を使用して、不要な割り当てを回避します。

    copy()
  • 関数を使用して要素を安全に追加します。
  • スライスを明示的に作成するには、make() を使用します。
  • 最終的に改善されたコードは次のとおりです:
    func Intersection(s1, s2 []int) []int {
      res := make([]int, 0, min(len(s1), len(s2)))
      for _, v1 := range s1 {
        for _, v2 := range s2 {
          if v1 == v2 {
            copy(res[len(res):], []int{v1})
          }
        }
      }
      return res
    }
  • これらのプラクティスに従うと、メモリセーフな Go 関数を作成し、コードの堅牢性、信頼性、セキュリティを向上させることができます。

以上がGolang 関数のメモリ安全プログラミングの実践の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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