interface - smart - ¿Qué pasa con el diseño de la memoria significa que[] T no puede convertirse a la interfaz[] en Go?
smart contracts ethereum (2)
Así que he estado leyendo estos dos artículos y esta respuesta
No se puede convertir la cadena [] a [] interfaz {} dice que el diseño de la memoria debe cambiarse.
http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go dice que comprender la memoria subyacente hace que responder a esta pregunta sea fácil, y
http://research.swtch.com/interfaces , explica lo que está sucediendo bajo el capó.
Pero, por mi vida, no puedo pensar en una razón, en términos de la implementación de interfaces, sobre por qué [] T no se puede convertir a la interfaz [].
¿Entonces por qué?
El artículo " InterfaceSlice " trata de detallar:
Una variable con tipo
[]interface{}
no es una interfaz. Es un segmento cuyo tipo de elemento pasa a ser lainterface{}
. Pero incluso dado esto, uno podría decir que el significado es claro.Bueno, ¿verdad? Una variable con tipo
[]interface{}
tiene un diseño de memoria específico, conocido en tiempo de compilación.Cada
interface{}
ocupa dos palabras (una palabra para el tipo de contenido, la otra para los datos contenidos o un puntero a ella). Como consecuencia, un segmento con longitud N y con tipo[]interface{}
está respaldado por un fragmento de datos que tiene N * 2 palabras de longitud.
Ver también " ¿cuál es el significado de la interface{}
en golang? "
Esto es diferente al fragmento de datos que respalda un segmento con el tipo
[]MyType
y la misma longitud. Su porción de datos seráN*sizeof(MyType)
longitud.El resultado es que no se puede asignar rápidamente algo del tipo
[]MyType
a algo de tipo[]interface{}
; los datos detrás de ellos simplemente se ven diferentes.
" por qué []string
no se puede convertir a []interface{}
en Ir " agrega una buena ilustración:
// imagine this is possible
var sliceOfInterface = []interface{}(sliceOfStrings)
// since it''s array of interface{} now - we can do anything
// let''s put integer into the first position
sliceOfInterface[0] = 1
// sliceOfStrings still points to the same array, and now "one" is replaced by 1
fmt.Println(strings.ToUpper(sliceOfStrings[0])) // BANG!
Lea el artículo del blog Las leyes de la reflexión , sección La representación de una interfaz .
Una variable de tipo de interfaz almacena un par: el valor concreto asignado a la variable y el descriptor de tipo de ese valor. Para ser más precisos, el valor es el elemento de datos concretos subyacente que implementa la interfaz y el tipo describe el tipo completo de ese elemento.
Entonces, si tiene un valor de []T
(una porción de T
) donde T
no es una interfaz, los elementos de dicha porción solo almacenan valores de tipo T
, pero no almacena la información de tipo, pertenece a la porción tipo.
Si tiene un valor de tipo []inteface{}
, los elementos de dicho sector contienen los valores concretos y los descriptores de tipo de esos valores.
Por lo tanto, los elementos en una []interface{}
requieren más información (más memoria) que en una interfaz no []T
Y si la memoria ocupada de esas 2 rebanadas no es la misma, no pueden ser simplemente "miradas" de manera diferente (miradas como un tipo de differnet). Producir uno del otro requiere trabajo adicional.