Tengo curiosidad por qué Go no se convierte implícitamente []T
a []interface{}
cuándo se convertirá implícitamente T
a interface{}
. ¿Hay algo no trivial en esta conversión que me estoy perdiendo?
Ejemplo:
func foo([]interface{}) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
go build
se queja
no puede usar una (cadena de tipo []) como interfaz de tipo [] {} en el argumento de la función
Y si trato de hacerlo explícitamente, lo mismo: se b := []interface{}(a)
queja
no puede convertir una (cadena de tipo []) a la interfaz de tipo [] {}
Entonces, cada vez que necesito hacer esta conversión (que parece surgir mucho), he estado haciendo algo como esto:
b = make([]interface{}, len(a), len(a))
for i := range a {
b[i] = a[i]
}
¿Hay una mejor manera de hacer esto, o funciones de biblioteca estándar para ayudar con estas conversiones? Parece un poco tonto escribir 4 líneas adicionales de código cada vez que quiero llamar a una función que puede tomar una lista de, por ejemplo, ints o cadenas.
fuente
Respuestas:
En Go, hay una regla general de que la sintaxis no debe ocultar operaciones complejas / costosas. La conversión de a
string
ainterface{}
se realiza en tiempo O (1). La conversión de a[]string
ainterface{}
también se realiza en tiempo O (1) ya que un segmento sigue siendo un valor. Sin embargo, la conversión de a[]string
a[]interface{}
es tiempo O (n) porque cada elemento del segmento debe convertirse a aninterface{}
.La única excepción a esta regla es convertir cadenas. Al convertir un ay
string
desde a[]byte
o a[]rune
, Go funciona O (n) a pesar de que las conversiones son "sintaxis".No hay una función de biblioteca estándar que haga esta conversión por usted. Podrías hacer uno con reflect, pero sería más lento que la opción de tres líneas.
Ejemplo con reflexión:
Sin embargo, su mejor opción es usar las líneas de código que proporcionó en su pregunta:
fuente
map
s también por cierto.channels
también.Converting a []string to an interface{} is also done in O(1) time
?Lo que falta es eso
T
yinterface{}
que tiene el valor deT
tener diferentes representaciones en la memoria, por lo que no se puede convertir trivialmente.Una variable de tipo
T
es solo su valor en la memoria. No hay información de tipo asociada (en Go, cada variable tiene un solo tipo conocido en tiempo de compilación, no en tiempo de ejecución). Se representa en la memoria de esta manera:Una
interface{}
celebración de una variable de tipoT
se representa en la memoria de esta maneraT
Volviendo a su pregunta original: ¿por qué ir no se convierte implícitamente
[]T
a[]interface{}
?La conversión
[]T
a[]interface{}
implicaría crear una nueva porción deinterface {}
valores que es una operación no trivial ya que el diseño en memoria es completamente diferente.fuente
Aquí está la explicación oficial: https://github.com/golang/go/wiki/InterfaceSlice
fuente
[]interface
al tipo que espero como[]map[string]interface{}
?Intenta en su
interface{}
lugar. Para lanzar de nuevo como rebanada, intentefuente
bar
para interpretarlo como "una porción de cualquier tipo"? Tenga en cuenta que su revestimiento de tres crea un[]interface{}
, no[]string
o un trozo de otro tipo de hormigón.func foo(bar []string) { /* ... */ }
interface{}
hará que el compilador no se queje al pasar un argumento como enfoo(a)
. Él podría usar el reflejo o el cambio de tipo ( golang.org/doc/effective_go.html#type_switch ) dentrofoo
.Convierte
interface{}
en cualquier tipo.Sintaxis:
Ejemplo:
fuente
invalid type assertion: potato.([]string) (non-interface type []interface {} on left)
En caso de que necesite acortar más su código, puede crear un nuevo tipo para ayudante
luego
fuente