Go, al igual que otros lenguajes de programación, maneja estructuras de datos como los arrays y slices. Un array es una colección de elementos del mismo tipo y tiene dimensiones fijas que se definen al momento de su creación. Aquí te mostramos cómo se declaran:
var array [4]int
Cuando se inicializa un array en Go, los elementos se llenan con el valor cero del tipo de dato especificado. En este caso, los enteros son inicializados con 0.
¿Cuál es la naturaleza inmutable de los arrays?
Los arrays en Go son inmutables, lo que significa que no podemos cambiar su tamaño una vez definidos. Sin embargo, podemos modificar los valores de los elementos existentes:
array[0]=1array[1]=2
Esto significa que podemos asignar nuevos valores a los índices específicos del array, pero no podemos agregar nuevos elementos.
¿Cómo funcionan los slices en Go?
A diferencia de los arrays, los slices en Go son dinámicos y permiten crecer en tamaño. Al igual que los arrays, los slices están compuestos de elementos del mismo tipo, pero no requieren la especificación del tamaño al ser declarados:
slice :=[]int{0,1,2,3,4,5,6}
Cuando ejecutamos len(slice) obtenemos el número de elementos del slice, y cap(slice) nos indica la capacidad total para alojar elementos.
¿Qué es el slicing y cómo se usa?
El slicing es una poderosa herramienta para manipular arrays y slices. Nos permite seleccionar un subconjunto de elementos:
Imprimir el elemento en una posición específica:
fmt.Println(slice[0])// Resultado: 0
Imprimir elementos desde el inicio hasta una posición (excluido el índice final):
fmt.Println(slice[:3])// Resultado: [0 1 2]
Imprimir una parte específica del slice:
fmt.Println(slice[2:4])// Resultado: [2 3]
Desde una posición específica hasta el final:
fmt.Println(slice[4:])// Resultado: [4 5 6]
¿Cómo podemos añadir elementos a los slices?
La flexibilidad de los slices permite agregar elementos adicionales con el método append:
slice =append(slice,7)
Para añadir una lista completa de elementos, se aplica append con una sintaxis especial que descompone el slice insertado:
Este uso de ... literalmente expande los elementos del extraSlice y los añade individualmente al slice original.
En resumen, Go ofrece herramientas eficaces y flexibles para manejar arrays y slices, con sus propias características y usos. Los arrays son más eficientes en situaciones donde los datos no cambiarán, mientras que los slices proporcionan la flexibilidad necesaria para crecer dinámicamente. ¡Explora y experimenta con estas estructuras, y verás cómo se pueden adaptar a tus necesidades de programación!
Manejo de Arrays y Slices en Go: Declaración y Modificación
Investigando:
La diferencia principal entre los arrays es que estos tienen una longitud fija e invariable y deben declarase especifiandola
x:=[5]int{0,1,2,3,4}
mientras que los Slices tienen una longitud variable y no hay que especificarla en la declaración
var x []float64
en este caso se crea un Slice con una longitud de cero
Si queremos crear un slice deberiamos usar la funcion make:
x:=make([]float64,5)
esto crea un Slice asociado a un array subjacente de longitud 5.
Los Slices siempre están asociados a un array y aunque nunca pueden ser mas largos que el aray, pueden ser mas cortos.
La función make también permite un tercer parámetro, que representa la capacidad del array, por lo que
x:=make([]float64,5,10)
representa un Slice de longitud 5 y capacidad de 10
Grax :3
Sí quieren saber más detalladamente la información compartida por Mario, pueden leer este post de
Se puede acceder a un slice especificando dos índices, un límite bajo y uno alto, separados por dos puntos slice[low : high]. Esto selecciona un rango semiabierto que incluye el primer elemento, pero excluye el último.
Aquí pueden leer mas sobre slices
Gracias bro
En Go, los arrays poseen un tamaño fijo y son inmutables, mientras que en los slices su tamaño es dinámico y los puedes modificar.
package main
import"fmt"func main(){var array [4]int
array[0]=1 array[1]=2 fmt.Println(array,len(array),cap(array))// Sliceslice:=[]int{0,1,2,3,4,5,6,7,8} fmt.Println(slice,len(slice),cap(slice))// Métodos en el slice fmt.Println(slice[0]) fmt.Println(slice[:3]) fmt.Println(slice[2:4]) fmt.Println(slice[4:])// Append slice =append(slice,11) fmt.Println(slice)// AppendnewSlice:=[]int{12,13,14} slice =append(slice, newSlice...) fmt.Println(slice)}
Aparentemente las funciones len y cap no tienen diferencia, sin embargo, en este ejemplo se logra ver la diferencia:
nombresArray:=[5]string{"Ana","José","Daniel","María","Carlos"}nombresSlice:= nombresArray[0:3]fmt.Println(nombresSlice)// [Ana José Daniel]fmt.Println(len(nombresSlice))// 3fmt.Println(cap(nombresSlice))// 5
No se explica bien en la clase la verdad. Trataré de resumir lo que encontré:
Arrays: Son inmutables, su length y capacity serán siempre las mismas.
Slices: Debido a que no son inmutables y su tamaño es dinámico, puedes tener un tamaño distinto a su capacidad, pero su capacidad siempre va a ser más grande que su tamaño.
Es decir, puedes tener un slice de tamaño 3 y capacidad 5, pero no uno de tamaño 5 y capacidad 3. Cuando usas append y te quedas sin capacidad, ya que los slices usan arrays para almacenar los datos, la función le va a asignar un nuevo array más grande y moverá los datos existentes más los nuevos a éste. El array siempre será del doble de tamaño que el anterior.
En otras palabras, digamos que tienes un slice de 5 elementos (capacidad y tamaño), y usas append para poner otro elemento más, el slice resultante va a tener tamaño 6 (por el nuevo elemento) y la capacidad subirá a 10 (el doble de la capacidad del array anterior).
Si ya estás algo familiarizado con programación, esto funciona porque un slice tiene 3 atributos, un pointer al array donde se almacena la info, el dato del tamaño y el dato de la capacidad. Cuando el slice crece, se crea otro array más grande, se copia la info vieja a ese nuevo array, y el pointer del slice cambia al array nuevo.
Diferencia del cap y len se percibe mas en los slice, ya que en lo inmutables no.
Para tener en cuenta que si haces un slice copiando otro y modicas la copia, modificas el principal también
package main
import"fmt"func main(){list:=[]int{0,1,2,3,4,5}showNumberArray(list)list1:= list[3:]showNumberArray(list1) list1[0]=100showNumberArray(list)showNumberArray(list1) list[0]=200showNumberArray(list)showNumberArray(list1) list =append(list[:3], list[4:]...)showNumberArray(list)showNumberArray(list1)}func showNumberArray(array []int){ fmt.Println(array)}
Estuve investigando y tanto arrays como slices se pasan por valor, no por referencia. Pero los slices se construyen sobre los arrays, básicamente describen sus propiedades, tienen un pointer al array donde se almacena la información, su tamaño y su capacidad. El tema es que si copias un slice a otro, copias también el pointer, y ya que ambos slices están haciendo referencia al mismo array para almacenar la información, cuando modificas uno, estás modificando un mismo array compartido en ambos.
Cual podria ser una posible solucion para evitar esto?
Mis apuntes en el código
package main
import"fmt"func main(){//ARRAYSvar array [4]int // arrays are immutable in Go, you cannot add or delete elements fmt.Println(array) array[0]=1 array[1]=1//SLICE//Basic Declaration{var _ =[]int{}//Its length is automatically 0//Creating a slice with a specific length and capacityvar x =make([]float64,5,10) fmt.Println(len(x)) fmt.Println(cap(x))}slice:=[]int{1,2,3,4,5,6} fmt.Println(slice)//METHODS OF SLICE fmt.Println(slice[0]) fmt.Println(slice[:5])//elements from the beginning to the element 5 fmt.Println(slice[2:5])//elements between the exclusive interval [2,5] fmt.Println(slice[2:])//elements from 2 to the end//LEN FUNCTION fmt.Println(len(slice))//Returns the length of the structure fmt.Println(len(array))//CAP FUNCTION fmt.Println(cap(slice))//Returns the capacity of elements of the structure fmt.Println(cap(array))//APPEND FUNCTION slice =append(slice,10)//It receives two arguments; first the slice that it is going to modify, slice =append(slice,0)//then the element that it will receive slice =append(slice,7) fmt.Println(slice)//APPEND A NEW LISTvar slice2 =[]int{8,9,11} slice =append(slice, slice2...)//The spread operator references every one of the elements in the called slice fmt.Println(slice)//DIFFERENCES BETWEEN SLICE AND ARRAY//ARRAY//- Immutable//- More effience//- Length must be specified when declared//SLICE//- Mutable//- Length can vary and it could not be specified when declared}
Muchas gracias
También se puede aplicar el método de slices con los arrays para obtener parte del array. array[2:3]
Así es compañero! sin embargo hay que tener presente que se regresa un slice cuyo tamaño puede modificarse.
Los arrays pueden tener varios tipos de datos?
No, fíjate que se declara de qué tipo va a ser el array al momento de declararlo.
me parece extraño que se indique que los array son inmutables y en seguida se indique que se pueden editar sus valores. La definición de inmutable es precisamente que no se puede modificar. En este caso lo que entiendo es que en los arrays la longitud y tipo de datos que almacena es fija, pero si se pueden modificar sus valores.
Lo decía respecto a tamaño, si quieres un array que sea complatemente inmutable tienes que declararlo como una constante
¡Para tener en cuenta!
Los Slices no son más que una abstracción que agrega algunas funcionalidades a los Arrays.
Uno de los significados de la palabra "slice" es "rebanada". Por ende, un Slice es una rebanada o una porción de un Array.
Un Arrays es una estructura de datos que representa una lista de elementos cuya hubicación en memoria es contigua, es decir, cada elemento está hubicado al lado del otro. Y debido a que tenemos las direcciones de memoria de cada elemento(los indices) podemos acceder a cualquiera de inmediato. Sin embargo, añadir un elemento es una operación costosa pues, a no ser que el siguiente espacio en memoria esté libre, tendrémos que mover todo el array a un lugar a donde quepa completo, tanto los elementos que ya estaban, más el o los que estamos agregando.
Teniendo en cuenta lo anterior, los Slices los creamos de arrays existentes, tomando una porción y referenciándo el array subyacente(no se crea uno nuevo). Este es un ejemplo:
También podemos crear un Slice desde cero de la siguiente manera:
En este caso, Go creará un nuevo Array que será el array subyacente al que hará referencia este Slice.
Esto tiene varias implicaciones a considerar. La primera es que incluso aunque pareciera fácil añadir elementos a un Slice, en realidad esta operación podría ser costosa. Los Slices actuan como Array dinámicos, o sea, que pueden aumentar o disminuir en tamaño, y esto lo logran apartando más espacios de memoria de los que en un principio se dice que se van a necesitar(esto debes hacerlo explicitamente especificando la propiedad "capacity", de lo contrario, solo tendrá el tamaño que infiera de la cantidad de elementos con que lo inicialices). Por ende, es posible que cuando quieras añadir un nuevo elemento, Go tenga que rehubicar todo el Slice y esto no es eficiente. De ahí que si lo que necesitas de tu lista es que se le puedan añadir o quitar elementos de manera fácil y eficiente, puede que ni los Arrays ni los Slices sean la mejor opción.
Por otro lado, al ser los Slices una referencia a un Array, si creas varios de un mismo array y luego· modificas uno de esos valores directamente en el Array padre, el cambio se verá reflejado en todos los Slices hijos y esto pudiera causar comportamientos inesperados. Eh aquí un ejemplo:
¿hay una forma de comentar varias lineas al mismo tiempo ?
Eso depende del editor que se este utilizando.
Hola :)
Si estás usando VSCode puedes seleccionar todas las líneas que quieres y usar el shortcut Ctrl + /
¿Cuál es la diferencia entre el tamaño y la capacidad de un array y slice? ¿para que sirve la capacidad?
La diferencia radica en si son fijos o variables. Para un array su tamaño es fijo, mientras que para un slice es una secuencia de tamaño variable. :D
Creo que la pregunta se refiere a la diferencia entre cap() y len(), no a la diferencia entre slice y array... Lo digo porque también tengo la duda.
Hola a todos, porque el cap para un slice retorna el valor total de los elementos que posee el mismo si el slice tiene un tamano indefinido?
Eso es porque cuando creas un slice, Go lo crea con una cantidad definida para optimizar la memoria. En caso de superar una cantidad de elementos definida, Go aumenta de nuevo a esa cantidad. Todo esto con la finalidad de no crear un slice con el tamaño máximo siempre para así optimizar la memoria.
Aclaración:
Los arrays NO son inmutables ya que su contenido se puede cambiar.
Lo que no se puede alterar en los arrays es su tamaño.
creo que cometio un pequeño error.
Los elementos que son excluidos son los primeros, pero se esta confundiendo por no contar el 0.
ej el [:3] 0 1 2 siendo 2 el tercer elemento pero en [2:4] el segundo elemento es el 1 y no lo incluye ya que es 0 1 pero empieza por el 2 y el cuarto elemento es el 3 que si lo incluye
Hay un concepto que se esta perdiendo un poco, un slice es una referencia a un array, siempre que se declara un slice implícitamente se declara un array y como tal los slices no almacenan datos.
En resumen, un slice es una herramienta para trabajar con los arrays, esto es porque los arrays son inmutables en tamaño