pointers - Cortar un puntero de corte pasado como argumento
go slice (1)
Tengo el siguiente código:
func main() {
var buf []byte{1, 2, 3, 4, 5}
buf = buf[2:]
fmt.Println(buf)
panic(1)
}
Sin embargo, quiero pasar un puntero al segmento de bytes de
buf
a otra función, y cortarlo allí, así que algo así como:
func main() {
var buf []byte{1, 2, 3, 4, 5}
sliceArr(&buf, 2)
fmt.Println(buf)
panic(1)
}
func sliceArr(buf *[]byte, i int) {
*buf = *buf[i:]
}
Me da un error que no puedo usar el tipo
[]byte
como tipo
*[]byte
en argumento para la función
sliceArr()
, y que no puedo cortar el tipo
*[]byte
.
Que pasa
¿Las rebanadas no se pasan por referencia por defecto?
Intenté hacer esto sin un puntero, pero no funciona: la matriz se está copiando.
¿Cómo puedo hacer esto?
El error
cannot use type []byte as type *[]byte in argument to sliceArr()
proviene de un error tipográfico que no ha publicado (intentó pasar un segmento y no un puntero a un segmento a
sliceArr()
).
En cuanto al otro error (
cannot slice type *[]byte
), solo necesita usar paréntesis para agrupar la referencia del puntero:
*buf = (*buf)[i:]
Y accidentalmente omitió un signo
=
de la declaración de variable.
Aparte de eso, todo funciona como lo escribiste:
func main() {
var buf = []byte{1, 2, 3, 4, 5}
sliceArr(&buf, 2)
fmt.Println(buf)
}
func sliceArr(buf *[]byte, i int) {
*buf = (*buf)[i:]
}
Salida (pruébalo en Go Playground ):
[3 4 5]
Nota:
Tenga en cuenta que la
especificación establece
que si
p
es un puntero a una
matriz
,
p[low:high]
es la abreviatura de
(*p)[low:high]
, es decir, el puntero se desreferencia automáticamente para usted.
Esto no sucede automáticamente si
p
es un puntero a un
segmento
,
p[low:high]
no es válido ya que no puede cortar un puntero.
Por lo tanto, debe desreferenciar el puntero manualmente en caso de punteros a sectores.
La razón de esta desviación es que un puntero a un segmento es muy raro ya que los segmentos ya son descriptores "justos" (a una parte contigua de una matriz subyacente), y los segmentos se pasan sin un puntero la mayor parte del tiempo, así que si es raro caso (como este) necesita pasar un puntero, debe ser explícito sobre cómo manejarlo. Las matrices, por otro lado, representan todos los elementos; asignar o pasar matrices copia todos los valores, por lo que es mucho más común usar punteros a matrices (que punteros a sectores); por lo tanto, se justifica tener más soporte de lenguaje para trabajar con punteros de matriz.
También tenga en cuenta que su tarea podría lograrse requiriendo solo un segmento (sin puntero) como tipo de parámetro y devolviendo el nuevo valor de segmento, que por supuesto debe asignarse a la persona que llama (un buen ejemplo de esto es la función incorporada
append()
)
Nota 2:
Si el tipo de parámetro es un segmento (y no un puntero a un segmento), y pasa un segmento, la matriz subyacente no se copia, solo el encabezado del segmento. Pero en este caso, si corta el argumento (que es una copia del encabezado del corte) y asigna de nuevo el nuevo corte (encabezado del corte) al argumento, simplemente está cambiando el valor del parámetro (una variable local) y no el valor original (variable) que se pasó, es por eso que no funcionará.
Lea las siguientes publicaciones de blog para obtener más detalles sobre los sectores: