Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Amalan pengaturcaraan keselamatan memori fungsi Golang

Amalan pengaturcaraan keselamatan memori fungsi Golang

WBOY
WBOYasal
2024-04-23 13:12:02361semak imbas

Menulis kod selamat memori dalam Go adalah penting untuk mengelakkan ranap program, kerosakan data dan kelemahan keselamatan. Amalan termasuk: menghantar penunjuk, menggunakan kapasiti kepingan, mengelakkan limpahan penimbal, menggunakan kepingan dengan berhati-hati, menggunakan make() untuk membuat kepingan dan peta, menggunakan tangguh untuk melepaskan sumber dan menggunakan penyegerakan.Mutex untuk menyegerakkan akses serentak. Mengikuti amalan ini boleh meningkatkan keteguhan dan kebolehpercayaan kod anda dan dapat dilihat dalam kes praktikal.

Amalan pengaturcaraan keselamatan memori fungsi Golang

Go Amalan Pengaturcaraan Selamat Memori Berfungsi

Menulis kod selamat memori dalam Go adalah penting untuk mengelakkan ranap program, kerosakan data dan kelemahan keselamatan. Mengikuti amalan berikut boleh membantu meningkatkan keteguhan dan kebolehpercayaan kod anda.

Petunjuk lulus

Petunjuk lulus (*T) dan bukannya nilai ​​(T) menghalang pengubahsuaian nilai yang diluluskan secara tidak sengaja. Contohnya: *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()
  // 执行其他操作
}

使用 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++
    }()
  }
  // 等待所有协程完成
}

实战案例

考虑一个计算两个切片交集的函数:

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
    }
  • Menggunakan kapasiti hirisan

Kepingan ([]T) adalah berdasarkan tatasusunan asas, jadi memahami kapasitinya adalah penting. Kapasiti mewakili panjang maksimum tatasusunan. Apabila kapasiti melebihi, Go akan memperuntukkan tatasusunan asas yang lebih besar secara automatik, sekali gus menukar alamat kepingan.

Kod berikut menunjukkan perkara ini:

rrreee🎜Mengelakkan Limpahan Penampan🎜🎜Limpahan penimbal berlaku apabila jumlah data yang disimpan melebihi penimbal yang diperuntukkan kepadanya. Dalam Go, ini boleh dielakkan menggunakan kaedah berikut: 🎜
  • Gunakan tatasusunan panjang tetap: Tatasusunan diperuntukkan ruang tetap pada masa penyusunan dan dijamin tidak melimpah. 🎜
  • Gunakan kepingan dan urus kapasitinya dengan betul: Jejaki panjang dan kapasiti kepingan anda dan laraskannya mengikut keperluan. 🎜
  • Gunakan fungsi copy(): copy() untuk memastikan jumlah data yang disalin tidak melebihi kapasiti penimbal sasaran. 🎜🎜🎜Gunakan kepingan dengan berhati-hati🎜🎜Kepingan bukan jenis yang selamat untuk ingatan kerana ia berkongsi tatasusunan asas. Pengubahsuaian pada kepingan mungkin secara tidak dijangka mempengaruhi pembolehubah lain yang menggunakan tatasusunan yang sama. 🎜🎜Contoh berikut menggambarkan perkara ini: 🎜rrreee🎜Gunakan make() untuk membuat kepingan dan peta 🎜🎜Gunakan make() untuk mencipta kepingan dan peta secara eksplisit untuk menentukan permulaannya keupayaan untuk mengelakkan peruntukan yang tidak perlu. 🎜🎜Gunakan tunda untuk melepaskan sumber 🎜🎜Pernyataan tunda memastikan bahawa blok kod dilaksanakan sebelum fungsi kembali. Ini berguna untuk membebaskan sumber seperti fail terbuka atau sambungan rangkaian. 🎜🎜Contoh berikut menggunakan tunda untuk menutup fail: 🎜rrreee🎜Menggunakan sync.Mutex🎜🎜sync.Mutex digunakan untuk menyegerakkan serentak akses kepada kunci Mutex kongsi untuk sumber. Mutex boleh memperoleh dan melepaskan kunci melalui kaedah Lock() dan Unlock(). 🎜🎜Contoh berikut menggunakan sync.Mutex untuk melindungi akses serentak kepada data kongsi: 🎜rrreee🎜Contoh praktikal🎜🎜Pertimbangkan fungsi yang mengira persilangan dua keping: 🎜rrreee🎜Dengan mengikuti perkara berikut prinsip, kami Keselamatan memori fungsi ini boleh dipertingkatkan: 🎜
    • Gunakan kapasiti kepingan untuk mengelakkan peruntukan yang tidak perlu. 🎜
    • Gunakan fungsi copy() untuk menambahkan elemen dengan selamat. 🎜
    • Gunakan make() untuk membuat kepingan secara eksplisit. 🎜🎜🎜Kod penambahbaikan terakhir adalah seperti berikut: 🎜rrreee🎜Mengikuti amalan ini membantu menulis fungsi Go yang selamat memori dan meningkatkan keteguhan, kebolehpercayaan dan keselamatan kod. 🎜

Atas ialah kandungan terperinci Amalan pengaturcaraan keselamatan memori fungsi Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn