Cómo implementar arrays redimensionables en Go


Vengo de un fondo de C++ y estoy acostumbrado a usar la clase std::vector para cosas como esta. Supongamos que quiero una matriz dinámica de estos:

type a struct {
    b int
    c string
}

¿Cuál es la forma estándar de hacer esto?

Un fragmento sería muy útil

 47
go
Author: cthom06, 2010-08-02

5 answers

Use el append() incorporado

Ejemplo:

type mytype struct {
  a, b int
}

func main() {
  a := []mytype{mytype{1, 2}, mytype{3, 4}}
  a = append(a, mytype{5, 6})
}

Consulte la especificación para obtener más información sobre anexar.

 48
Author: cthom06,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-08 19:53:07

Un Go Slice contiene tres elementos: datos, longitud y capacidad.

s := make([]int, 0, 10)

La variable s es un corte de ints con una longitud de 0 y una capacidad de 10. Las funciones integradas len() y cap() te permiten obtener la longitud y la capacidad de un slice:

len(s) == 0
cap(s) == 10

Para aumentar la longitud de un corte, simplemente vuelva a cortar:

s = s[0:5]
// len(s) == 5
// cap(s) == 10

Para disminuir la longitud, puedes tomar una sub-rebanada:

s = s[0:1]
// len(s) == 1

Hay algunas formas más cortas de invocar make ():

a := make([]int, 10) 
// len(a) == cap(a) == 10

b := make([]int)
// len(b) == cap(b) == 0

Eso está bien y bueno, pero lo que si usted necesita para aumentar la longitud de una rebanada más allá de su capacidad? Para hacer eso, debe asignar un nuevo segmento y copiar el contenido del segmento anterior al nuevo. (La función "copiar" es otra incorporada.)

t := make([]int, len(s), 20)
copy(t, s)

El Effective Go document lleva este ejemplo un poco más allá, implementando una función Append que agrega un segmento a otro, redimensionándolo si es necesario.

Los sectores están respaldados por arrays; cuando haces () un sector de una capacidad específica, un array de esa capacidad se asigna en segundo plano. El slice efectivamente se convierte en un "puntero inteligente" a esa matriz. Si usted pasa la corte (o un subsector de ese sector) a otra función, se pasa como un puntero a la misma matriz. Esto hace que los sub-slices sean muy baratos de crear - es la asignación de la matriz de respaldo lo que es costoso.

La biblioteca estándar Go incluye una serie de paquetes contenedores - vector, por ejemplo - que eliminan la necesidad de administrar manualmente los sectores. Utilizar rebanadas para la velocidad, y clases de contenedores más elaboradas para mayor comodidad. (Dicho esto, todavía uso rebanadas para la mayoría de las cosas.)

Puede que te estés preguntando por qué necesitas ir a todo este problema. Después de todo, muchos lenguajes proporcionan matrices dinámicamente redimensionadas como primitivas. La razón de esto está ligada a la filosofía de Go. Los diseñadores de idiomas no presumen de saber cuál es la política de asignación adecuada para su programa; en su lugar, le brindan las herramientas que necesita para crear sus propios datos estructura.

 52
Author: Andrew Gerrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-12 11:48:13

La forma idiomática de hacer esto ha cambiado. La adición de la función incorporada append () significa que puedes extender un slice así:

type a struct {
    b int
    c string
}

func main(){
    var mySlice []a
    mySlice = append(mySlice,a{5,"pizza"})
}

Append() añadirá el elemento dado al segmento si hay espacio o extenderá el segmento si no es lo suficientemente grande.

Más información sobre append() está aquí http://golang.org/doc/go_spec.html#Appending_and_copying_slices

 16
Author: Jessta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-13 20:07:27

Hola simplemente podemos hacer esto de dos maneras

type mytype struct {
  a, b int
}

Solo haz esto

  1. Sin añadir

__

a := []mytype{mytype{1, 2}, mytype{3, 4}, mytype{4, 5}}
  1. Con anexar

__

a:=  append([]mytype{}, mytype{1, 2}, mytype{3, 4}, mytype{4, 5})

Agrega todo lo que quieras. El primero es una manera fácil de hacer esto. Espero que esto te ayude.

 2
Author: amku91,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-05 08:47:34

Usted también podría ser capaz de conformarse con una rebanada. que es una matriz que conoce su longitud actual. Y puede tener una longitud de corriente separada y una capacidad máxima. Tenga en cuenta que los valores pasados para el tamaño y la capacidad iniciales no tienen que ser constantes, por lo que puede crear una función que construya y devuelva segmentos de diferentes longitudes en función de sus parámetros.

El lado positivo es que un slice []Int puede ser indexado como una matriz, y devolverá ints cuando se use de esta manera.

El la desventaja es que no crecerá automáticamente alrededor de su capacidad declarada. Effective Go tiene un ejemplo de cómo manejaría la reasignación.

El código sería

type mytype struct {
   a, b int
}




func main() {

  sl := make([]mytype, 10, 50) //slice of 10 items, max capacity 50 these do not have to be constant expressions.
  sl[0] = mytype{1,2}
   //...
  for i, value := range sl {
  // ... do stuff with value
  }
}
 1
Author: user414731,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-09 05:53:16