데이터 구조에서 메모리 누수를 방지하면서 메모리 효율성을 위해 Go에서 포인터를 효과적으로 사용하는 방법은 무엇입니까?

Patricia Arquette
풀어 주다: 2024-10-28 10:02:02
원래의
982명이 탐색했습니다.

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

Go에서 포인터의 가비지 수집 및 올바른 사용

포인터의 배경

Go에서 포인터는 복사하지 않고 메모리에 저장된 데이터를 참조하는 데 사용됩니다. 데이터 그 자체. 이는 특히 크거나 복잡한 데이터 구조로 작업할 때 성능과 메모리 효율성을 향상시킬 수 있습니다.

문제

제공된 코드는 태그를 이미지 URL 목록에 매핑하는 데이터 구조를 생성하기 위한 것입니다. . 그러나 초기 설계에서는 메모리를 절약하기 위해 포인터를 사용하는 것을 고려했기 때문에 할당된 메모리의 최종 정리에 대한 의문이 제기되었습니다.

질문에 대한 응답

버전 1:

  • URL 필드에 대한 포인터를 사용하면 기본 문자열 데이터가 여전히 포인터에 의해 참조되기 때문에 메모리 누수가 발생합니다.
  • 완전한 이미지 구조체와 모든 해당 필드는 오랫동안 메모리에 유지됩니다. tagToUrlMap에 저장된 포인터 중 하나가 이를 가리키고 있기 때문입니다.

버전 2:

  • URL 문자열과 이에 대한 포인터를 사용하면 버전 1에서 발생한 메모리 누수 문제가 해결됩니다.
  • 그러나 추가적인 간접 참조와 복잡성이 발생하고 메모리가 크게 절약되지 않습니다.

최적의 솔루션

URL을 저장하는 가장 효율적인 접근 방식은 포인터 없이 직접 문자열 값을 사용하는 것입니다. Go는 동일한 문자열에 대한 여러 참조가 단일 메모리 할당을 공유할 수 있도록 하는 문자열 풀을 사용하여 문자열을 저장함으로써 이미 문자열 처리를 최적화합니다.

메모리 보존을 위한 문자열 인턴

메모리를 더욱 절약하기 위해 코드는 문자열 인턴을 사용할 수 있습니다. 여기에는 문자열 인스턴스를 하나만 저장하고 동일한 문자열이 나타날 때마다 이를 참조하는 작업이 포함됩니다.

제공된 코드에는 캐시를 사용하여 이전에 발생한 문자열을 저장하고 재사용하는 간단한 문자열 인터닝 함수(interned())가 포함되어 있습니다. .

수정된 코드

<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>
로그인 후 복사

추가 리소스

  • [동시성은 병렬성이 아니다](https://blog.golang.org/go-nuts)
  • [Go의 메모리 관리 이해](https://blog.gopheracademy.com/advent-2016/understanding-memory-management-in-go/)
  • [Go의 가비지 컬렉션 ](https://www.golang-book.com/books/intro/12)
  • [stringsx.Pool](https://github.com/icza/gox) (Go 라이브러리는 스트링 풀)

위 내용은 데이터 구조에서 메모리 누수를 방지하면서 메모리 효율성을 위해 Go에서 포인터를 효과적으로 사용하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!