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