Как вы очищаете кусочек в 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))
}

это правильно?

чтобы уточнить, буфер очищается, поэтому его можно использовать повторно.

пример буфера.Усечь функция в пакете байтов.

обратите внимание, что сброс просто вызывает усечение(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) }
3 89

3 ответа:

все зависит от того, каково ваше определение "ясный". Один из действительных, безусловно, является:

slice = slice[:0]

но есть загвоздка. Если элементы среза имеют тип T:

var slice []T

затем применения len(slice) чтобы быть нулем, с помощью вышеупомянутого "трюка",не сделать любой элемент

slice[:cap(slice)]

право на сбор мусора. Это может быть оптимальным подходом в некоторых сценариях. Но это также может быть причиной "утечки памяти" - память не используется, но потенциально достижимый (после повторного нарезания "среза") и, следовательно, не мусорный "собираемый".

установка среза в nil - это лучший способ очистить нарезать. nil ломтики в go отлично себя ведут и устанавливают ломтик в nil освободит базовую память для сборщика мусора.

смотрите playground

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 удалит это сглаживание.

этот однако метод изменяет емкость до нуля.

Я немного изучал эту проблему для своих собственных целей; у меня был кусочек структур (включая некоторые указатели), и я хотел убедиться, что все правильно; оказался в этой теме и хотел поделиться своими результатами.

чтобы попрактиковаться, я немного сходил на детскую площадку: https://play.golang.org/p/9i4gPx3lnY

который оценивает это:

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

запуск этого кода как есть покажет тот же адрес памяти для переменных" meow "и" meow2", что и будучи тем же самым:

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

что, я думаю, подтверждает, что структура мусора. Как ни странно, раскомментировав комментируемую строку печати, вы получите разные адреса памяти для мяуканья:

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

Я думаю, что это может быть связано с тем, что печать откладывается в некотором роде (?), но интересная иллюстрация некоторого поведения mgmt памяти, и еще один голос за:

[]MyStruct = nil