vehiculos - services flhsmv gov mvcheckweb
En Go, ¿el nombre de la variable receptora es ''auto'' engañoso o una buena práctica? (4)
Además de lo que otros dijeron (especialmente PeterSO
y dskinner
-en su comentario a la respuesta de Peter), tenga en cuenta varias cosas importantes:
Puede llamar a un método como una función simple
En Go, puede llamar a cualquier función de método no como un método en un receptor, sino más bien como una función regular, simplemente calificando su nombre con el nombre del tipo que se define como método y explicándole un argumento de receptor (obteninig una función simple de un método se llama utilizando una expresión de método ).
Demostrar:
package main
import "fmt"
type Foo int
func (f Foo) Bar() {
fmt.Printf("My receiver is %v/n", f)
}
func main() {
a := Foo(46)
a.Bar()
b := Foo(51)
Foo.Bar(b)
}
( Enlace de juegos ) .
Cuando se ejecuta, este programa imprime:
My receiver is 46
My receiver is 51
Como puede ver, el self
pierde aquí su significado sagrado porque acaba de llamar a un método que construye artificialmente el contexto que no tiene nada que ver con el concepto muy citado de "llamar al método de un objeto es pasarle un mensaje a ese objeto".
Para recapitular, en Go, un método es simplemente una función semánticamente vinculada a un tipo particular que recibe un único argumento adicional: su receptor, no importa cómo se llame. A diferencia de muchos otros lenguajes principales, Go no oculta este hecho debajo de la alfombra.
Un receptor no es necesariamente mutable dentro de un método definido en su tipo
Como se demostró en mi ejemplo, he definido un método, Bar()
, en un receptor sin puntero, y si intentas asignar un valor al receptor que tendrá éxito pero no afectará a la persona que llama porque el receptor -Como todo en Go-ha pasado por valor (por lo que ese entero acaba de ser copiado).
Para poder modificar el valor del receptor en el método, debe definirlo en un puntero de tipo apropiado, como
func (f *Foo) Bar() {
// here you can mutate the value via *f, like
*f = 73
}
De nuevo, puedes ver que usar self
significado self
"yo", "mi interior" se vuelve discutible aquí: en mi ejemplo, el método simplemente recibió un valor cuyo tipo conoce. Puede ver que esto está en contraste con muchos OO-languages en los que un objeto es una caja negra que generalmente se pasa por referencia. En Go, puede definir un método en prácticamente cualquier cosa ( incluidos otros métodos , que es el que utiliza el paquete estándar net/http
, por cierto) que erosiona el concepto de "los métodos son para objetos".
Diferentes conjuntos de métodos pueden ser aplicables al mismo valor en diferentes momentos
En Go, los métodos son una forma conveniente de agrupar la funcionalidad alrededor de tipos particulares, y diferentes conjuntos de métodos pueden ser aplicables al mismo valor en diferentes puntos del flujo del programa. Combinado con interfaces y pato-tipado que proporcionan, este concepto realmente florece. La idea es que, en Go, haya un modismo para definir tipos de "soporte" que realicen ciertas operaciones en valores de algún otro tipo.
Un buen ejemplo de esto es la sort
paquete estándar : por ejemplo, proporciona el tipo IntSlice
que le permite ordenar una porción de enteros, un valor de tipo []int
. Para hacer eso, escribe-convierte tu porción a sort.IntSlice
y el valor que obtienes como resultado tiene un conjunto completo de métodos para ordenar tu porción mientras que la representación interna de tu valor no ha cambiado , porque sort.IntSlice
se define como type IntSlice []int
. En cada método de ese tipo de IntSlice
, es difícil conciliar el significado de su valor de receptor con self
mismo porque simplemente existe el tipo para proporcionar un conjunto de métodos para otro tipo; en un sentido filosófico, tales tipos de utilidad no tienen ningún concepto de "uno mismo" ;-)
Conclusión
Así que diría que mantén las cosas simples en tu cabeza y no trates de "sobrecargar" el enfoque claro y simple de Go with semántica que no indica explícitamente que proporciona.
Una nota más Mi percepción personal de los modismos de Go cuando los aprendí es que la propiedad primordial de Go es su practicidad (en oposición al idealismo, etc.) así que si ves algún concepto que "se sienta" antinatural, intenta averiguar por qué está diseñado de esa manera, y la mayoría a menudo descubrirá por qué el concepto "hace clic" en su cerebro y se vuelve natural. (Debo admitir que para asimilar este problema en particular con los métodos de comprensión en Go, una buena familiaridad con C
sería de mucha ayuda).
He visto una buena cantidad de blogs y videos en Go y hasta donde recuerdo, ninguno de los autores usa ''self'' o ''this'' para la variable receiver al escribir métodos. Sin embargo, parece que hay una serie de preguntas sobre el desbordamiento de la pila que hacen esto, y me hizo pensar si esto es engañoso para nombrar a la variable ''yo''.
La lectura de la especificación para conjuntos de métodos no proporciona ninguna evidencia de ninguna manera (en mi interpretación).
Me parece recordar haber encontrado en algún lugar que no era realmente un auto puntero, ¿alguien puede enumerar evidencia o proporcionar razonamiento de cualquier manera, y si hay algún problema / trampa que pueda ocurrir al pensar en él como "propio"?
Un ejemplo rápido:
type MyStruct struct {
Name string
}
¿Qué método es más apropiado, o ambos?
func (m *MyStruct) MyMethod() error {
// do something useful
}
o
func (self *MyStruct) MyMethod() error {
// do something useful
}
El wiki de Go recomienda no usar términos como this
o self
y en su lugar usar abreviaturas derivadas del nombre de tipo: https://github.com/golang/go/wiki/CodeReviewComments#receiver-names
Mire el código fuente para los comandos Go y vaya a los paquetes estándar para ejemplos de buen estilo de programación. El nombre self
no se usa para los receptores del método Go.
El nombre self
es una convención de Python. Go no es Python.
9.4. Comentarios al azar
A menudo, el primer argumento de un método se llama self. Esto no es más que una convención: el nombre sí mismo no tiene ningún significado especial para Python. Sin embargo, tenga en cuenta que, al no seguir la convención, su código puede ser menos legible para otros programadores de Python, y también es concebible que se escriba un programa de navegador de clases que dependa de dicha convención.
No veo ninguna razón particularmente convincente para evitar this
/ self
. Otros comentarios aquí simplemente citan las normas de la comunidad o describen aspectos del envío de métodos que no tienen relación con las convenciones de nombres.
https://github.com/golang/go/wiki/CodeReviewComments#receiver-names rechazan this
o a self
sin dar ningún motivo en absoluto, a menos que pueda leer algo en el reclamo implícito que tenga menos énfasis en los métodos que en otros idiomas.
Una de las ventajas de comprometerse con this
o la self
convención es que ayuda a resaltar las violaciones de la Ley de Demeter . Código como este:
func (w *ChunkWriter) Write(recId uint32, msg []byte) (recs uint64, err error) {
recs = w.chunk.Records
err = w.handle.Write(recId, msg)
if err == nil {
recs++
w.chunk.Records = recs
}
return
}
aparece en la fachada para llegar a los miembros de w
inapropiadamente. De hecho, está accediendo a los miembros de su receptor, lo cual es perfectamente correcto.