Wie kann man Zeiger in Go effektiv für die Speichereffizienz nutzen und gleichzeitig Speicherlecks in Datenstrukturen vermeiden?

Patricia Arquette
Freigeben: 2024-10-28 10:02:02
Original
982 Leute haben es durchsucht

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

Garbage Collection und korrekte Verwendung von Zeigern in Go

Hintergrundinformationen zu Zeigern

In Go werden Zeiger verwendet, um im Speicher gespeicherte Daten zu referenzieren, ohne sie zu kopieren die Daten selbst. Dies kann die Leistung und Speichereffizienz verbessern, insbesondere bei der Arbeit mit großen oder komplexen Datenstrukturen.

Das Problem

Der bereitgestellte Code beabsichtigt, eine Datenstruktur zu erstellen, die Tags einer Liste von Bild-URLs zuordnet . Beim ursprünglichen Entwurf wurde jedoch die Verwendung von Zeigern zum Speichern von Speicher in Betracht gezogen, was Fragen zur eventuellen Bereinigung des zugewiesenen Speichers aufwirft.

Antwort auf Fragen

Version 1:

  • Die Verwendung von Zeigern auf das URL-Feld führt zu einem Speicherverlust, da die zugrunde liegenden Zeichenfolgendaten immer noch von den Zeigern referenziert werden.
  • Die vollständigen Bildstrukturen und alle ihre Felder bleiben so lange im Speicher da alle in tagToUrlMap gespeicherten Zeiger auf sie verweisen.

Version 2:

  • Erstellen einer Zwischenvariablen zum Speichern der URL-Zeichenfolge und Die Verwendung eines Zeigers darauf behebt das durch Version 1 verursachte Speicherverlustproblem.
  • Es führt jedoch zu zusätzlichen Indirektionen und Komplexität und spart nicht wesentlich Speicher.

Optimale Lösung

Der effizienteste Ansatz zum Speichern von URLs besteht darin, Zeichenfolgenwerte direkt ohne Zeiger zu verwenden. Go optimiert die String-Verarbeitung bereits, indem es Strings mithilfe eines String-Pools speichert, der es mehreren Verweisen auf denselben String ermöglicht, sich eine einzige Speicherzuordnung zu teilen.

String-Internierung zur Speichererhaltung

Um noch mehr Speicherplatz zu sparen, kann der Code String-Internierung verwenden. Dabei wird nur eine Instanz einer Zeichenfolge gespeichert und immer dann darauf verwiesen, wenn dieselbe Zeichenfolge angetroffen wird.

Der bereitgestellte Code enthält eine einfache String-Internierungsfunktion (interned()), die einen Cache verwendet, um zuvor angetroffene Zeichenfolgen zu speichern und wiederzuverwenden .

Korrigierter Code

<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>
Nach dem Login kopieren

Zusätzliche Ressourcen

  • [Parallelität ist keine Parallelität](https://blog.golang.org/go-nuts)
  • [Speicherverwaltung in Go verstehen](https://blog.gopheracademy.com/advent-2016/understanding-memory-management-in-go/)
  • [Speicherbereinigung in Go ](https://www.golang-book.com/books/intro/12)
  • [stringsx.Pool](https://github.com/icza/gox) (Go-Bibliothek, die eine String-Pool)

Das obige ist der detaillierte Inhalt vonWie kann man Zeiger in Go effektiv für die Speichereffizienz nutzen und gleichzeitig Speicherlecks in Datenstrukturen vermeiden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!