La traducción del artículo fue preparada específicamente para los estudiantes del curso Golang Developer , cuyas clases comienzan hoy.
Al principio, es fácil percibir matrices y sectores como uno solo, pero con nombres diferentes: ambos son una estructura de datos para representar colecciones. Sin embargo, en realidad son muy diferentes entre sí.
En este artículo, veremos sus diferencias e implementaciones en Go.
Pasaremos a los ejemplos para que pueda tomar una decisión más informada sobre dónde aplicarlos.
Matrices
Una matriz es una colección de tamaño fijo. El énfasis aquí se pone en un tamaño fijo, porque tan pronto como establezca la longitud de la matriz, más tarde no podrá cambiarla.
Veamos un ejemplo. Crearemos una matriz de cuatro valores enteros:
arr := [4]int{3, 2, 5, 4}
Longitud y Tipo
En el ejemplo anterior, la variable
arr
define como una matriz de tipo
[4]int
, lo que significa que la matriz consta de cuatro elementos. Es importante tener en cuenta que el tamaño
4
incluido en la definición del tipo.
De esto se deduce que, de hecho, las matrices de diferentes longitudes son matrices de diferentes tipos. No puede igualar matrices de diferentes longitudes entre sí y no puede asignar el valor de una matriz a otra en este caso:
longerArr := [5]int{5, 7, 1, 2, 0} longerArr = arr
Descubrí que es fácil hablar de matrices en términos de estructuras. Si intentas crear una
estructura similar a una matriz, lo más probable es que obtengas lo siguiente:
En realidad, esto no se recomienda, pero esta es una buena manera de tener una idea de por qué las matrices de diferentes longitudes son matrices de diferentes tipos.
Representación de la memoria
La matriz se almacena como una secuencia de
n
bloques de cierto tipo:

Esta memoria se asigna cuando inicializa una variable de matriz.
Pasar por enlace
Go no tiene tal cosa como pasar por referencia; en cambio, todo se pasa por valor. Si asigna el valor de la matriz a otra variable, simplemente se copiará el valor asignado.

Si desea pasar solo una "referencia" a la matriz, use punteros:

Al asignar memoria y en una función, una matriz es en realidad un tipo de datos simple y funciona de la misma manera que las estructuras.
Rebanadas
Los cortes se pueden considerar como una implementación extendida de arreglos.
Los cortes se implementaron en Go para cubrir algunos de los casos de uso extremadamente comunes que los desarrolladores encuentran al trabajar con colecciones, como el cambio dinámico del tamaño de las colecciones.
Una declaración de segmento es muy similar a una declaración de matriz, excepto que se omite el especificador de longitud:
slice := []int{4, 5, 3}
Si solo observa el código, parece que los segmentos y las matrices son bastante similares, pero su principal diferencia radica en la implementación y las condiciones de uso.
Representación de la memoria
Un segmento se asigna de manera diferente a una matriz, y es esencialmente un puntero modificado. Cada segmento contiene tres bloques de información:
- Puntero a una secuencia de datos.
- La longitud, que determina el número de elementos que están actualmente contenidos en el segmento.
- Capacidad (capacidad), que determina el número total de celdas de memoria proporcionadas.

De esto se deduce que se pueden asignar segmentos de diferentes longitudes. Son del mismo tipo, y el puntero, la longitud y el volumen pueden variar:
slice1 := []int{6, 1, 2} slice2 := []int{9, 3}
Un segmento, a diferencia de una matriz, no asigna memoria durante la inicialización. De hecho, los sectores se inicializan con un valor
nil
.
Pasar por enlace
Cuando asigna un segmento a otra variable, todavía está pasando el valor. Aquí, el valor se refiere solo al puntero, la longitud y el volumen, y no a la memoria ocupada por los propios elementos.

Agregar nuevos elementos
Para agregar nuevos elementos al segmento, debe usar la función
append
.
nums := []int{8, 0} nums = append(nums, 8)
Debajo del capó, se verá como asignar un valor especificado para un nuevo elemento, y después de eso, devolver un nuevo segmento. La longitud de la nueva porción será una más.

Si, al agregar un elemento, la longitud aumenta en uno y, por lo tanto, excede el volumen declarado, es necesario proporcionar un nuevo volumen (en este caso, el volumen actual generalmente se duplica).
Es por eso que a menudo se recomienda crear un segmento con la longitud y el volumen especificados de antemano (especialmente si tiene una idea clara del tamaño del segmento que necesita):
arr := make([]int, 0, 5)
¿Qué usar: matrices o rodajas?
Las matrices y los cortes son cosas completamente diferentes y, por lo tanto, sus casos de uso también varían.
Veamos algunos ejemplos de código abierto y la biblioteca estándar Go para comprender qué usar y cuándo.
Caso 1: UUID
Los UUID son datos de 128 bits que a menudo se usan para marcar un objeto o entidad. Por lo general, se representan como valores hexadecimales, separados por guiones:
e39bdaf4-710d-42ea-a29b-58c368b0c53c
En la biblioteca de
UUID de Google , el UUID se representa como una matriz de 16 bytes:
type UUID [16]byte
Esto tiene sentido ya que sabemos que el UUID consta de 128 bits (16 bytes). No vamos a agregar ni eliminar ningún byte del UUID y, por lo tanto, el uso de la matriz para representarlo será.
Caso 2: Ordenar valores enteros
En este ejemplo, utilizaremos la función
sort.Ints
de
la biblioteca estándar de clasificación :
s := []int{5, 2, 6, 3, 1, 4}
La función
sort.Ints
toma una porción de enteros y los ordena en orden ascendente de valores. Las rebanadas son preferibles de usar aquí por dos razones:
- No se especifica el número de enteros (el número de enteros para ordenar puede ser cualquiera);
- Los números deben ordenarse en orden ascendente. El uso de una matriz asegurará que toda la colección de enteros se pase como un valor, por lo que la función ordenará su propia copia, no la colección que se le pasó.
Conclusión
Ahora que hemos analizado las diferencias clave entre matrices y sectores, así como sus casos de uso, quiero darle algunos consejos para que le resulte más fácil decidir qué diseño usar:
- Si una entidad se describe mediante un conjunto de elementos no vacíos de una longitud fija, use matrices.
- Cuando describa una colección a la que desea agregar o desde la cual eliminar elementos, use sectores.
- Si la colección puede contener cualquier cantidad de elementos, use cortes.
- ¿Cambiarás la colección de alguna manera? Si es así, entonces se deben usar rebanadas.
Como puede ver, los sectores cubren la mayoría de los escenarios para crear aplicaciones Go. Sin embargo, las matrices tienen derecho a existir y, además, son increíblemente útiles, especialmente cuando aparece un caso de uso adecuado.