¿Cuál es la forma adecuada de borrar un segmento en Go?
Esto es lo que he encontrado en los foros de 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))
}
¿Es esto correcto?
Para aclarar, el búfer se borra para que pueda reutilizarse.
Un ejemplo es la función Buffer.Truncate en el paquete de bytes.
Tenga en cuenta que Reset solo llama a Truncate (0). Entonces parece que en este caso la línea 70 evaluaría: 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) }
Respuestas:
Todo depende de cuál sea su definición de 'claro'. Uno de los válidos ciertamente es:
Pero hay una trampa. Si los elementos de corte son de tipo T:
entonces hacer cumplir
len(slice)
cero, por el "truco" anterior, no hace ningún elemento deelegible para recolección de basura. Este podría ser el enfoque óptimo en algunos escenarios. Pero también podría ser una causa de "pérdidas de memoria": memoria no utilizada, pero potencialmente accesible (después de volver a cortar el 'corte') y, por lo tanto, no basura "recolectable".
fuente
Establecer el corte en
nil
es la mejor manera de borrar un corte.nil
los cortes en marcha se comportan perfectamente bien y establecer el corte ennil
liberará la memoria subyacente al recolector de basura.Ver patio de recreo
Huellas dactilares
Tenga en cuenta que los sectores pueden alias fácilmente para que dos sectores apunten a la misma memoria subyacente. La configuración de
nil
eliminará ese alias.Sin embargo, este método cambia la capacidad a cero.
fuente
append
nil
¿Ir a un sector siempre ha funcionado en Go?Estaba investigando este tema un poco para mis propios fines; Tenía una porción de estructuras (incluidos algunos punteros) y quería asegurarme de que estaba bien; terminé en este hilo y quería compartir mis resultados.
Para practicar, hice un pequeño patio de recreo: https://play.golang.org/p/9i4gPx3lnY
que evalúa esto:
Ejecutar ese código tal cual mostrará la misma dirección de memoria para las variables "miau" y "miau2" como la misma:
lo cual creo que confirma que la estructura es basura recolectada. Curiosamente, al descomentar la línea de impresión comentada, se obtendrán diferentes direcciones de memoria para los maullidos:
Creo que esto puede deberse a que la impresión se difiere de alguna manera (?), Pero es una ilustración interesante de algún comportamiento de gestión de memoria y un voto más por:
fuente
0x1030e0c0
no es igual a0x1030e0f0
(la primera termina enc0
, la segunda enf0
).meow2
cada corrida ...