type tutorial language golang go embedding

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 , y T 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 un Bitmap 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 de Renderer :

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