Qual é a maneira apropriada de limpar uma fatia no Go?
Aqui está o que eu encontrei nos fóruns 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))
}
Isso está correto?
Para esclarecer, o buffer é limpo para que possa ser reutilizado.
Um exemplo é a função Buffer.Truncate no pacote de bytes.
Observe que a redefinição apenas chama Truncate (0). Portanto, parece que neste caso a linha 70 avaliaria: 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) }
Respostas:
Tudo depende de qual é a sua definição de 'claro'. Um dos válidos certamente é:
Mas há um problema. Se os elementos de fatia forem do tipo T:
forçar
len(slice)
a zero, pelo "truque" acima, não cria nenhum elemento deelegíveis para coleta de lixo. Essa pode ser a abordagem ideal em alguns cenários. Mas também pode ser uma causa de "vazamentos de memória" - memória não usada, mas potencialmente acessível (após o re-fatiamento de 'fatia') e, portanto, não "lixo" colecionável.
fonte
Definir a fatia como
nil
é a melhor maneira de limpar uma fatia.nil
as fatias em movimento são perfeitamente bem comportadas e a configuração da fatianil
liberará a memória subjacente para o coletor de lixo.Ver parque infantil
Impressões
Observe que as fatias podem ser facilmente alteradas para que duas fatias aponte para a mesma memória subjacente. A configuração para
nil
removerá o alias.Este método altera a capacidade para zero embora.
fonte
append
nil
sempre uma fatia funcionou no Go?Eu estava analisando esse problema um pouco para meus próprios propósitos; Eu tinha uma fatia de estruturas (incluindo alguns ponteiros) e queria ter certeza de que estava certo; terminou neste tópico e queria compartilhar meus resultados.
Para praticar, fiz um pequeno playground: https://play.golang.org/p/9i4gPx3lnY
que avalia isso:
A execução desse código como está exibirá o mesmo endereço de memória para as variáveis "meow" e "meow2" como sendo o mesmo:
o que eu acho que confirma que a estrutura é um lixo coletado. Curiosamente, descomentar a linha de impressão comentada, produzirá endereços de memória diferentes para os miados:
Eu acho que isso pode ser devido à impressão ser adiada de alguma forma (?), Mas ilustração interessante de algum comportamento de gerenciamento de memória e mais um voto para:
fonte
0x1030e0c0
não é igual a0x1030e0f0
(o primeiro termina emc0
, o último emf0
).meow2
cada corrida ...