Как вы очистите кусочек в 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) }
Ответы
Ответ 1
Все зависит от того, каково ваше определение "ясно". Одно из правильных - это:
slice = slice[:0]
Но есть улов. Если элементы среза имеют тип T:
var slice []T
а затем принудительно применяя len(slice)
к нулю, по вышеуказанному "трюку", не делает никакого элемента
slice[:cap(slice)]
имеет право на сбор мусора. Это может быть оптимальный подход в некоторых сценариях. Но это также может быть причиной "утечек памяти" - память не используется, но потенциально доступна (после повторного нарезки "среза" ) и, следовательно, не мусор "коллекционируется".
Ответ 2
Настройка среза на nil
- лучший способ очистить срез. nil
ломтики в go отлично хорошо себя ведут и установка среза на 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
удалит это сглаживание.
Этот метод изменяет емкость до нуля.
Ответ 3
Я изучал этот вопрос немного для своих целей; У меня был фрагмент структур (включая некоторые указатели), и я хотел убедиться, что я понял это правильно; закончил эту тему и хотел поделиться своими результатами.
Чтобы тренироваться, я немного поиграл на детской площадке:
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)
}
Запуск этого кода as-is покажет тот же адрес памяти для переменных "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
Я думаю, что это может быть связано с тем, что отпечаток откладывается каким-то образом (?), но интересная иллюстрация некоторого поведения в поведении памяти и еще одно голосование за:
[]MyStruct = nil