Maison  >  Article  >  développement back-end  >  Comment utiliser efficacement les pointeurs dans Go pour améliorer l'efficacité de la mémoire tout en évitant les fuites de mémoire dans les structures de données ?

Comment utiliser efficacement les pointeurs dans Go pour améliorer l'efficacité de la mémoire tout en évitant les fuites de mémoire dans les structures de données ?

Patricia Arquette
Patricia Arquetteoriginal
2024-10-28 10:02:02983parcourir

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

Garbage Collecte et utilisation correcte des pointeurs dans Go

Contexte sur les pointeurs

Dans Go, les pointeurs sont utilisés pour référencer les données stockées en mémoire sans les copier les données elles-mêmes. Cela peut améliorer les performances et l'efficacité de la mémoire, en particulier lorsque vous travaillez avec des structures de données volumineuses ou complexes.

Le problème

Le code fourni vise à créer une structure de données qui mappe les balises à une liste d'URL d'images. . Cependant, la conception initiale envisageait d'utiliser des pointeurs pour économiser de la mémoire, ce qui soulève des questions sur le nettoyage éventuel de la mémoire allouée.

Réponse aux questions

Version 1 :

  • L'utilisation de pointeurs vers le champ URL entraîne une fuite de mémoire car les données de chaîne sous-jacentes sont toujours référencées par les pointeurs.
  • Les structures Image complètes et tous leurs champs resteront en mémoire aussi longtemps car l'un des pointeurs stockés dans tagToUrlMap pointe vers eux.

Version 2 :

  • Création d'une variable intermédiaire pour contenir la chaîne d'URL et l'utilisation d'un pointeur vers celui-ci résout le problème de fuite de mémoire provoqué par la version 1.
  • Cependant, cela introduit des indirections et une complexité supplémentaires, et n'économise pas de manière significative la mémoire.

Solution optimale

L'approche la plus efficace pour stocker les URL consiste à utiliser les valeurs de chaîne directement sans pointeurs. Go optimise déjà la gestion des chaînes en stockant les chaînes à l'aide d'un pool de chaînes, qui permet à plusieurs références à la même chaîne de partager une seule allocation de mémoire.

String Interning pour la conservation de la mémoire

Pour conserver davantage la mémoire, le code peut utiliser un interning de chaîne. Cela implique de stocker une seule instance d'une chaîne et de la référencer chaque fois que la même chaîne est rencontrée.

Le code fourni comprend une simple fonction d'internement de chaîne (interned()) qui utilise un cache pour stocker et réutiliser les chaînes précédemment rencontrées. .

Code corrigé

<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>

Ressources supplémentaires

  • [La concurrence n'est pas le parallélisme](https://blog.golang.org/go-nuts)
  • [Comprendre la gestion de la mémoire dans Go](https://blog.gopheracademy.com/advent-2016/understanding-memory-management-in-go/)
  • [Garbage Collection dans Go ](https://www.golang-book.com/books/intro/12)
  • [stringsx.Pool](https://github.com/icza/gox) (Bibliothèque Go qui fournit un piscine à cordes)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn