En el lenguaje de programación Go; ¿Cómo pueden ser útiles los punteros a los indicadores?¿Para qué sirven los punteros?
(¿Por qué no ilegal si no son realmente útiles?)
En el lenguaje de programación Go; ¿Cómo pueden ser útiles los punteros a los indicadores?¿Para qué sirven los punteros?
(¿Por qué no ilegal si no son realmente útiles?)
La utilidad de cualquier tipo de datos depende del problema a resolver y del método utilizado para resolver el problema. Si un tipo de datos no se ajusta al problema, simplemente no se ajusta al problema, y no hay nada más.
El lenguaje de programación Go (así como la mayoría de los demás lenguajes de programación) se basa en reglas simples que el programador puede usar para crear nuevos tipos de datos. Algunas de estas reglas son:
*T
: crear un nuevo tipo de datos que es un puntero a T[10]T
: una matriz de Tsstruct { t T; u U ... }
: una estructura que contiene una T como un componenteEl programador puede crear tipos de datos complejos mediante la composición de estas sencillas reglas. La cantidad total de tipos de datos posibles excede la cantidad de tipos de datos útiles. Claramente, existen (y deben existir) tipos de datos que no son útiles en absoluto. Esto es solo una consecuencia natural del hecho de que las reglas para construir nuevos tipos de datos son simples.
El tipo **T
entra en la categoría de tipos que son menos probables de aparecer en un programa. El hecho de que sea posible escribir *****T
no implica que dicho tipo tenga que ser inmensamente útil.
Y, por último, la respuesta a su pregunta:
El tipo **T
suele aparecer en contextos en los que queremos redirigir a los usuarios de un valor de tipo T
a otro valor de tipo T
, pero para alguna razón por la que no tiene acceso a todos los usuarios del valor o la búsqueda de los usuarios costaría demasiado tiempo:
T
(por alguna razón)T
para acceder al valor a través de un punteroT
a otro valoren tal situación, el uso de **T
es natural, ya que nos permite implementar la tercera etapa en O (1):
type User_of_T struct {
Value **T
}
// Redirect all users of a particular value of type T
// to another value of type T.
func (u *User_of_T) Redirect(t *T) {
*(u.Value) = t
}
Esa es una solución inteligente, sin embargo. – Tarik
En C, los punteros a los punteros son bastante comunes.Por ejemplo: arrays
char** argv
podría ser el ejemplo más destacado aquí)En Go sin embargo, punteros a punteros son Bastante raro. En lugar de acceder a las matrices con un puntero, hay un tipo de sector (que también almacena un puntero internamente). Por lo tanto, aún puede obtener el mismo tipo de indirección mediante el uso de una porción de sectores en Ir, pero normalmente no verá algo como **int
aquí.
Sin embargo, el segundo ejemplo podría aplicarse a los programas Go. Supongamos que tiene una función que debería poder cambiar un puntero pasado como parámetro. En ese caso, deberá pasar un puntero a ese puntero para que pueda cambiar el puntero original. Eso es extremadamente común en C, porque las funciones solo pueden devolver un valor (que a menudo es algún tipo de código de error) y si desea devolver un puntero adicional, deberá usar un puntero a ese puntero como parámetro de salida. Sin embargo, una función en Go puede devolver múltiples valores, por lo que las ocurrencias de punteros a punteros también son raras. Pero aún podrían ser útiles y, en algunos casos, podrían conducir a una API más agradable.
Por ejemplo, la función atomic.StorePointer puede ser uno de esos casos de uso raros pero bien escondidos para punteros a punteros en la biblioteca estándar.
Cuando pasa un puntero a la función, la función obtiene una copia de la misma. Así asignar un nuevo valor al puntero, dados no dará lugar a asignarlo a la original:
type Smartphone struct {
name string
}
type Geek struct {
smartphone *Smartphone
}
func replaceByNG(s **Smartphone) {
*s = &Smartphone{"Galaxy Nexus"}
}
func replaceByIPhone(s *Smartphone) {
s = &Smartphone{"IPhone 4S"}
}
func main() {
geek := Geek{&Smartphone{"Nexus S"}}
println(geek.smartphone.name)
replaceByIPhone(geek.smartphone)
println(geek.smartphone.name)
replaceByNG(&geek.smartphone)
println(geek.smartphone.name)
}
la salida es:
Nexus S
Nexus S
Galaxy Nexus
la respuesta realmente útil, esto es lo que encontré tratando de modificar slice en otra función –
He aquí un ejemplo que implica ** justo en la biblioteca estándar:
http://code.google.com/p/go/source/browse/src/pkg/encoding/gob/decoder.go#23
Linus Torvalds mencionó recientemente cómo punteros a punteros llevan a codificar con buen gusto (en C). Ver (entre otros) Brian Barto's blog post.
Puntero a cualquier dato útil. Los punteros son datos. Así que los punteros a los punteros son útiles, y también lo son los punteros a punteros, ... –
Estoy de acuerdo, pero dado que no hay aritmética de puntero ni nada que ver con punteros más que punteros en Go, de hecho son un poco inútiles. – thwd
Hay una aritmética de puntero en Go. Puede usar el paquete 'inseguro' para obtener un' uintptr' que puede usar libremente. En algunos casos, este enfoque puede conducir a un código más eficiente, pero en general, debe evitarse. – tux21b