Slice multi-dimensional
Tags: go, beginners, tutorial
Published: 2020-06-04 21:12:13

Vocês lembram dos slices? Ele se parece com uma linha.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ctvp3tunyudvld4vcemb.png)

Agora imagine uma pilha com vários slices, um em cima do outro.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/i0lb5ux5nki9yqy44t6x.jpg)

Esse exemplo é de um slice com duas dimensões, e é dele que vamos falar hoje. 

Olhando para foto é possível perceber que um slice 2d é semelhante a uma tabela, com linhas e colunas, assim como no Excel. Não podemos esquecer disso.

##Declarando um slice multi-dimensional

```golang
var tabela = [][]int{
    []int{1, 2, 3, 4},
    []int{5, 6, 7, 8},
    []int{9, 10, 11, 12},
}

var sl = []int{40, 41, 42, 43} //Slice comum 
```
A declaração não é tão diferente. Temos o nome da nossa variável, os colchetes e o tipo dos valores que serão armazenados. 

A primeira diferença é que temos dois pares de colchetes ``[][]int``. Isso irá indicar que nosso slice tem duas dimensões, podemos colocar várias outras.  

Um slice 2d é composto por vários slices comuns empilhados, semelhante a uma tabela. E é exatamente isso que foi feito, colocamos vários slices dentro do nosso slice bidimensional.  

É assim que devemos enxergar a tabela que criamos:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/igm9gkuqjmr4kexgb796.PNG)

Essa tabela possui linhas e colunas. Através delas conseguiremos pegar um elemento de forma individual. 
 
```golang
var tabela = [][]int{
    
     colunas:  0  1  2  3
linha: 0 []int{1, 2, 3, 4},
linha: 1 []int{5, 6, 7, 8},
linha: 2 []int{9, 10, 11, 12},
} 
```

Para identificar um único valor, vamos utilizar o padrão:
**``[linha][coluna]``**.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7572a5bmj2qfek4sqhyu.PNG)

```golang
var tabela = [][]int{
    
    []int{1, 2, 3, 4},
    []int{5, 6, 7, 8},
    []int{9, 10, 11, 12},
} 

fmt.Println(tabela[0][2], tabela[2][3])

//Resultado: 3 12
```

##Loops

Vamos testar o **for range** na nossa tabela.

```golang
var tabela = [][]int{

    []int{1, 2, 3, 4},
    []int{5, 6, 7, 8},
    []int{9, 10, 11, 12},
} 

for indice, valor := range tabela{
    fmt.Println(indice, valor)
}

/*Resultado: 
0 [1 2 3 4]
1 [5 6 7 8]
2 [9 10 11 12]
*/
```

O índice retorna o índice das linhas, já o valor retorna todo o slice que corresponde aquele índice. 

*E se quisermos demonstrar cada valor de cada slice de forma individual?*

Vamos ter que fazer outro loop, desta vez percorrendo elemento por elemento de cada slice. 

Sabe quem retorna todos os elemento unidos da slice? O ``valor``. Só que ele retorna todos os valores juntos, por isso vamos fazer um loop ``for`` nele. 

```golang
var tabela = [][]int{

    []int{1, 2, 3, 4},
    []int{5, 6, 7, 8},
    []int{9, 10, 11, 12},
} 

for indice, valor := range tabela{
    fmt.Println("Linha:",indice)

    for i, numero := range valor{
        fmt.Println("\tcoluna:", i, "Numero:", numero)
    }
}

/*Resultado: 
Linha: 0
        coluna: 0 Numero: 1
        coluna: 1 Numero: 2
        coluna: 2 Numero: 3
        coluna: 3 Numero: 4
Linha: 1
        coluna: 0 Numero: 5
        coluna: 1 Numero: 6
        coluna: 2 Numero: 7
        coluna: 3 Numero: 8
Linha: 2
        coluna: 0 Numero: 9
        coluna: 1 Numero: 10
        coluna: 2 Numero: 11
        coluna: 3 Numero: 12
*/
```

Também conseguimos fazer com o **for normal**.
```golang
var tabela = [][]int{

    []int{1, 2, 3, 4},
    []int{5, 6, 7, 8},
    []int{9, 10, 11, 12},
} 

for indice := 0; indice < len(tabela); indice++ {
	fmt.Println(indice, tabela[indice])	
}

/*Resultado: 
0 [1 2 3 4]
1 [5 6 7 8]
2 [9 10 11 12]
*/
```

O ``len(tabela)`` vai percorrer os índices das linhas, por isso que ``tabela[indice]`` retorna o slice completo. Se quisermos percorrer elemento por elemento, vamos ter que fazer outro loop.  

```golang
var tabela = [][]int{

    []int{1, 2, 3, 4},
    []int{5, 6, 7, 8},
    []int{9, 10, 11, 12},
} 

for indice := 0; indice < len(tabela); indice++ {
	fmt.Println("Linha:", indice)

	for c := 0; c < len(tabela[indice]); c++ {
		fmt.Println("\tcoluna:", i, "Numero:", tabela[indice][i])
	}
}

/*Resultado: 
Linha: 0
        coluna: 0 Numero: 1
        coluna: 1 Numero: 2
        coluna: 2 Numero: 3
        coluna: 3 Numero: 4
Linha: 1
        coluna: 0 Numero: 5
        coluna: 1 Numero: 6
        coluna: 2 Numero: 7
        coluna: 3 Numero: 8
Linha: 2
        coluna: 0 Numero: 9
        coluna: 1 Numero: 10
        coluna: 2 Numero: 11
        coluna: 3 Numero: 12
*/
```

A ``tabela[indice]`` contém todo o nosso slice, então fizemos um loop com o seu length, ``len(tabela[indice])``. 

Para selecionar um elemento do loop devemos ter a informação da linha e da coluna ``tabela[linha][coluna]``. A linha esta contida no indice, ``tabela[indice]``, a coluna irá ser "c", ``tabela[indice][c]``. 

Caso fiquem confusos com tanto loop 👇🏼
{% link https://dev.to/linivecristine/loop-for-range-em-go-39n7 %}

##Make

Caso não tenha lido o post sobre slices, basicamente o make nos permite criar slices com uma capacidade máxima. 

```golang
var tabela = make([][]int, 3, 10)

fmt.Println(tabela, len(tabela), cap(tabela))

//Resultado: [[] [] []] 3 10
```
``make([][]int, 3, 10)``. Esse 3 será o length das linhas, ele já criou espaço para 3 slices no meu slice 2d. Mas como ainda não atribuímos nenhum valor, eles estão vazios. 

Existem algumas formas de atribuir valor:

```golang
var tabela = make([][]int, 3, 10)

//Primeira
sl:= []int{1, 2, 3, 4}
tabela[0] = sl

//Segunda
tabela[1] = []int{5, 6, 7, 8}

fmt.Println(tabela, len(tabela), cap(tabela))

//Resultado: [[1 2 3 4] [5 6 7 8] []] 3 10
```

Vamos supor que já preenchemos nossos espaços disponível, agora vamos ter que adicionar novos elementos com o ``append``.

Lembrando que uma slice 2d é formado por outras slices, então não podemos dar um append em números isolados ``int``. Nossa tabela só receberá elementos do tipo ``[]int``, slice of int.

```golang
var tabela = make([][]int, 3, 10)

tabela[0] = []int{1, 2, 3, 4}
tabela[1] = []int{1, 2, 3, 4}
tabela[2] = []int{5, 6, 7, 8}
fmt.Println(tabela, len(tabela), cap(tabela))

sl := []int{9, 10, 11, 12}
tabela = append(tabela, sl)
fmt.Println(tabela, len(tabela), cap(tabela))

tabela = append(tabela,[]int{13, 14, 15, 16})
fmt.Println(tabela, len(tabela), cap(tabela))

/*Resultado: 
[[1 2 3 4] [1 2 3 4] [5 6 7 8]] 3 10
[[1 2 3 4] [1 2 3 4] [5 6 7 8] [9 10 11 12]] 4 10
[[1 2 3 4] [1 2 3 4] [5 6 7 8] [9 10 11 12][13 14 15 16]] 5 10
*/
```
Por hoje é isso, espero que tenham entendido e testem bastante. 

**Caso queiram se aprofundar em go 👉🏼 [vamo nessa](https://youtu.be/WiGU_ZB-u0w)**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2skckoe9myme7d2bvbhc.gif)