tutorial - manual go
Incrustar cuándo usar el puntero (1)
Cuando quiero insertar una estructura dentro de otra estructura, ¿debo usar un puntero o valor?
Por ejemplo
type Job struct {
Command string
*log.Logger
}
o
type Job struct {
Command string
log.Logger
}
Puede usar uno u otro: para el tipo de estructura , la especificación menciona:
Un campo declarado con un tipo pero sin un nombre de campo explícito es un campo anónimo , también llamado campo incrustado o una incrustación del tipo en la estructura.
Un tipo incrustado debe especificarse como un nombre de tipo
T
o como un puntero a un nombre de tipo que no sea de interfaz*T
, yT
mismo puede no ser un tipo de puntero.
Como log.Logger
no es una interfaz, puede usar el tipo o un puntero al tipo para el registrador de campo anónimo.
El artículo " Embedding in Go " para Eric Urban ( hydrogen18
) llama a insertar un puntero " embed by-pointer ":
- La primera ventaja de esto es que puede confiar en las funciones que usan la expresión
NewX
devolviendo una estructura by-puntero para hacer la inicialización.- La segunda ventaja es que puede incrustar toda la funcionalidad de un tipo sin necesidad de saber cuándo se crea una instancia .
El puntero incrustado en unBitmap
no es diferente de cualquier otro puntero en ir, por lo que se puede asignar varias veces.
Al hacer esto, puede cambiar qué instancia está extendiendo dinámicamente en tiempo de ejecución.
Por ejemplo, con:
type Bitmap struct{
data [4][5]bool
}
type Renderer struct{
*Bitmap //Embed by pointer
on uint8
off uint8
}
El tipo Renderer
incluye un Bitmap
de Bitmap
by-pointer.
Una sola instancia de
Bitmap
puede actuar como la instancia incorporada de muchas instancias deRenderer
:
var renderA,renderB Renderer
renderA.on = ''X''
renderA.off = ''O''
renderB.on = ''@''
renderB.off = ''.''
var pic Bitmap
pic.data[0][6] = true
pic.data[0][7] = true
pic.data[1][8] = true
pic.data[2][9] = true
pic.data[3][10] = true
renderA.Bitmap = &pic
renderB.Bitmap = &pic
renderA.render()
renderB.render()
Esto comparte la misma instancia de
Bitmap
a dos renderizadores diferentes.
Cada renderizador tiene su propio conjunto de caracteres, lo que permite imprimir dos representaciones del mapa de bits.
Así es como se ve el resultado:
OXXO
OXOO
OXOO
OXOO
.@@.
.@..
.@..
.@..
Este ejemplo demuestra el patrón Flyweight .
Aunque no tiene importancia para el consumo de memoria en este ejemplo, tener muchos miles de instancias que comparten una única estructura de datos subyacente puede ser muy importante para reducir el consumo de memoria de los sistemas.
Como se menciona en este hilo :
La razón por la que no puede tener puntero a puntero y puntero para interactuar con campos anónimos es que estos tipos no tienen métodos.
El objetivo de los campos anónimos es promover los métodos .Ya expliqué por qué las interfaces no tienen métodos: mucha gente utilizaba punteros a las interfaces de forma incorrecta e innecesaria, y no había ningún uso válido conocido, por lo que se modificó el idioma para desalentar activamente este uso haciendo que los punteros a las interfaces tengan sin métodos