Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk menggunakan penunjuk secara berkesan dalam Go untuk kecekapan memori sambil mengelakkan kebocoran memori dalam struktur data?

Bagaimana untuk menggunakan penunjuk secara berkesan dalam Go untuk kecekapan memori sambil mengelakkan kebocoran memori dalam struktur data?

Patricia Arquette
Patricia Arquetteasal
2024-10-28 10:02:02983semak imbas

How to effectively use pointers in Go for memory efficiency while avoiding memory leaks in data structures?

Pengumpulan Sampah dan Penggunaan Penunjuk yang Betul dalam Go

Latar Belakang pada Penunjuk

Dalam Go, penunjuk digunakan untuk merujuk data yang disimpan dalam ingatan tanpa menyalin data itu sendiri. Ini boleh meningkatkan prestasi dan kecekapan ingatan, terutamanya apabila bekerja dengan struktur data yang besar atau kompleks.

Masalahnya

Kod yang disediakan bertujuan untuk mencipta struktur data yang memetakan tag ke senarai URL imej . Walau bagaimanapun, reka bentuk awal dipertimbangkan menggunakan penunjuk untuk menyimpan memori, yang menimbulkan persoalan tentang pembersihan memori yang diperuntukkan.

Jawapan Kepada Soalan

Versi 1:

  • Menggunakan penuding ke medan URL mengakibatkan kebocoran memori kerana data rentetan asas masih dirujuk oleh penunjuk.
  • Struktur Imej lengkap dan semua medannya akan kekal dalam ingatan selagi kerana mana-mana penunjuk yang disimpan dalam tagToUrlMap menunjuk kepada mereka.

Versi 2:

  • Mencipta pembolehubah perantaraan untuk menahan rentetan URL dan menggunakan penuding kepadanya menyelesaikan isu kebocoran memori yang disebabkan oleh Versi 1.
  • Walau bagaimanapun, ia memperkenalkan arahan dan kerumitan tambahan, dan tidak menjimatkan memori dengan ketara.

Penyelesaian Optimum

Pendekatan paling cekap untuk menyimpan URL ialah menggunakan nilai rentetan secara langsung tanpa penunjuk. Go sudah mengoptimumkan pengendalian rentetan dengan menyimpan rentetan menggunakan kolam rentetan, yang membenarkan berbilang rujukan kepada rentetan yang sama untuk berkongsi peruntukan memori tunggal.

Pelatihan Rentetan untuk Pemuliharaan Memori

Untuk lebih menjimatkan ingatan, kod boleh menggunakan interning rentetan. Ia melibatkan hanya menyimpan satu tika rentetan dan merujuknya apabila rentetan yang sama ditemui.

Kod yang disediakan termasuk fungsi interning rentetan ringkas (interned()) yang menggunakan cache untuk menyimpan dan menggunakan semula rentetan yang ditemui sebelum ini .

Kod Dibetulkan

<code class="go">package main

import (
    "bytes"
    "encoding/json"
    "fmt"
)

type Image struct {
    URL string
    Description string
    Tags []Tag
}

type Tag struct {
    Name string
    Rank int
}

func searchImages() []*Image {
    parsedJSON := []*Image{
        &Image{
            URL: "https://c8.staticflickr.com/4/3707/11603200203_87810ddb43_o.jpg",
            Description: "Ocean islands",
            Tags: []Tag{
                Tag{"ocean", 1},
                Tag{"water", 2},
                Tag{"blue", 3},
                Tag{"forest", 4},
            },
        },
        &Image{
            URL: "https://c3.staticflickr.com/1/48/164626048_edeca27ed7_o.jpg",
            Description: "Bridge over river",
            Tags: []Tag{
                Tag{"bridge", 1},
                Tag{"river", 2},
                Tag{"water", 3},
                Tag{"forest", 4},
            },
        },
    }
    return parsedJSON
}

func interned(s string) string {
    if str, ok := cache[s]; ok {
        return str
    }
    cache[s] = s
    return s
}

var cache = make(map[string]string)

func main() {
    result := searchImages()

    tagToUrlMap := make(map[string][]string)

    for _, image := range result {
        imageURL := interned(image.URL)

        for _, tag := range image.Tags {
            tagName := interned(tag.Name)
            tagToUrlMap[tagName] = append(tagToUrlMap[tagName], imageURL)
        }
    }

    // Clear the interner cache
    cache = nil

    // Trim allocated slices to the minimum needed
    for tagName, urls := range tagToUrlMap {
        if cap(urls) > len(urls) {
            urls2 := make([]string, len(urls))
            copy(urls2, urls)
            tagToUrlMap[tagName] = urls2
        }
    }

    enc := json.NewEncoder(os.Stdout)
    enc.SetIndent("", "  ")
    if err := enc.Encode(tagToUrlMap); err != nil {
        panic(err)
    }
}</code>

Sumber Tambahan

  • [Concurrency is not parallelism](https://blog.golang.org/go-nuts)
  • [Memahami Pengurusan Memori dalam Go](https://blog.gopheracademy.com/advent-2016/understanding-memory-management-in-go/)
  • [Kutipan Sampah dalam Go ](https://www.golang-book.com/books/intro/12)
  • [stringsx.Pool](https://github.com/icza/gox) (Perpustakaan Go yang menyediakan kolam rentetan)

Atas ialah kandungan terperinci Bagaimana untuk menggunakan penunjuk secara berkesan dalam Go untuk kecekapan memori sambil mengelakkan kebocoran memori dalam struktur data?. 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