Programing

Go에서 슬라이스를 어떻게 지우나요?

crosscheck 2020. 7. 21. 07:54
반응형

Go에서 슬라이스를 어떻게 지우나요?


Go에서 슬라이스를 지우는 적절한 방법은 무엇입니까?

go 포럼 에서 찾은 내용은 다음과 같습니다 .

// test.go
package main

import (
    "fmt"
)

func main() {
    letters := []string{"a", "b", "c", "d"}
    fmt.Println(cap(letters))
    fmt.Println(len(letters))
    // clear the slice
    letters = letters[:0]
    fmt.Println(cap(letters))
    fmt.Println(len(letters))
}

이 올바른지?

명확히하기 위해, 버퍼는 삭제되어 재사용 될 수 있습니다.

바이트 패키지 의 예는 Buffer.Truncate 함수입니다.

Reset은 단지 Truncate (0)을 호출합니다. 따라서이 경우 70 행은 다음과 같이 평가됩니다. b.buf = b.buf [0 : 0]

http://golang.org/src/pkg/bytes/buffer.go

// Truncate discards all but the first n unread bytes from the buffer.
60  // It panics if n is negative or greater than the length of the buffer.
61  func (b *Buffer) Truncate(n int) {
62      b.lastRead = opInvalid
63      switch {
64      case n < 0 || n > b.Len():
65          panic("bytes.Buffer: truncation out of range")
66      case n == 0:
67          // Reuse buffer space.
68          b.off = 0
69      }
70      b.buf = b.buf[0 : b.off+n]
71  }
72  
73  // Reset resets the buffer so it has no content.
74  // b.Reset() is the same as b.Truncate(0).
75  func (b *Buffer) Reset() { b.Truncate(0) }

그것은 모두 '명확한'에 대한 당신의 정의에 달려 있습니다. 유효한 것 중 하나는 다음과 같습니다.

slice = slice[:0]

그러나 캐치가 있습니다. 슬라이스 요소가 T 유형 인 경우 :

var slice []T

다음 시행 len(slice)은 "트릭"이상으로, 영으로, 하지 의 요소를 만들

slice[:cap(slice)]

가비지 수집에 적합합니다. 일부 시나리오에서는 이것이 최적의 방법 일 수 있습니다. 그러나 "메모리 누수"의 원인 일 수도 있습니다. 메모리가 사용되지 않지만 잠재적으로 접근 할 수 있으며 ( '슬라이스'를 다시 슬라이스 한 후) 가비지 "수집 가능"이 아닙니다.


슬라이스를 설정하는 것이 슬라이스를 nil지우는 가장 좋은 방법입니다. nil이동중인 슬라이스는 완벽하게 작동하며 슬라이스를 설정 nil하면 기본 메모리가 가비지 콜렉터에 해제됩니다.

운동장 참조

package main

import (
    "fmt"
)

func dump(letters []string) {
    fmt.Println("letters = ", letters)
    fmt.Println(cap(letters))
    fmt.Println(len(letters))
    for i := range letters {
        fmt.Println(i, letters[i])
    }
}

func main() {
    letters := []string{"a", "b", "c", "d"}
    dump(letters)
    // clear the slice
    letters = nil
    dump(letters)
    // add stuff back to it
    letters = append(letters, "e")
    dump(letters)
}

인쇄물

letters =  [a b c d]
4
4
0 a
1 b
2 c
3 d
letters =  []
0
0
letters =  [e]
1
1
0 e

두 슬라이스가 동일한 기본 메모리를 가리 키도록 슬라이스의 별칭을 쉽게 지정할 수 있습니다. nil해당 앨리어싱을 제거하는 설정 입니다.

이 방법은 용량을 0으로 변경합니다.


I was looking into this issue a bit for my own purposes; I had a slice of structs (including some pointers) and I wanted to make sure I got it right; ended up on this thread, and wanted to share my results.

To practice, I did a little go playground: https://play.golang.org/p/9i4gPx3lnY

which evals to this:

package main

import "fmt"

type Blah struct {
    babyKitten int
    kittenSays *string
}

func main() {
    meow := "meow"
    Blahs := []Blah{}
    fmt.Printf("Blahs: %v\n", Blahs)
    Blahs = append(Blahs, Blah{1, &meow})
    fmt.Printf("Blahs: %v\n", Blahs)
    Blahs = append(Blahs, Blah{2, &meow})
    fmt.Printf("Blahs: %v\n", Blahs)
    //fmt.Printf("kittenSays: %v\n", *Blahs[0].kittenSays)
    Blahs = nil
    meow2 := "nyan"
    fmt.Printf("Blahs: %v\n", Blahs)
    Blahs = append(Blahs, Blah{1, &meow2})
    fmt.Printf("Blahs: %v\n", Blahs)
    fmt.Printf("kittenSays: %v\n", *Blahs[0].kittenSays)
}

Running that code as-is will show the same memory address for both "meow" and "meow2" variables as being the same:

Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
Blahs: []
Blahs: [{1 0x1030e0f0}]
kittenSays: nyan

which I think confirms that the struct is garbage collected. Oddly enough, uncommenting the commented print line, will yield different memory addresses for the meows:

Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
kittenSays: meow
Blahs: []
Blahs: [{1 0x1030e0f8}]
kittenSays: nyan

I think this may be due to the print being deferred in some way (?), but interesting illustration of some memory mgmt behavior, and one more vote for:

[]MyStruct = nil

참고URL : https://stackoverflow.com/questions/16971741/how-do-you-clear-a-slice-in-go

반응형