Clique sobre os tópicos listados abaixo para navegar até o conteúdo desejado.

  1. Entender Declaração de um matriz
  2. Entender o acesso/alteração aos elementos
  3. Entender como percorrer um matriz
  4. Entender como copiar um matriz
  5. Entender como copiar uma matriz por referencia
  6. Entender como descobrir o tamanho de um matriz
  7. Entender como usar matriz como parâmetro, argumento e retorno

Matriz é um tipo de dados derivado estático que armazenam dados, de diferentes tipos, de forma sequencial em memória. Em Go:Tipos de Dados e Go: Variáveis vimos o básico sobre o o tipo. Nesta parte do tutorial vamos estudar as operações sobre matrizes.

Como uma matriz é uma vetor de vetor, as funções vistas em Go: Vetor podem ser utilizados.

Matriz de ponteiros pode ser visto em Vetor de Ponteiro.

Ponteiro para matriz pode ser visto em Ponteiro para Matriz.

O tipo de dado matriz armazenam dados de forma justaposta. O nome Matriz não é palavras reconhecidas pela linguagem Go sendo um apelido para o termo array 2d, vetor bidimensional ou vetor de vetores. Uma matriz é um tipo de dado derivados de outros tipos de dados primitivos ou não.

Tab. 1: Matriz de int
L/C 0 1 2
0 10 20 30
1 40 50 60
2 70 80 90

Para cada elemento de um determinado tipo de dado contido em uma matriz, temos uma linha e coluna associadas as quais utilizamos para acessá-lo.

Matriz em Go, armazenam dados de forma estática. Sendo assim, não podemos aumentar ou dimimuir suas dimensões após a declaração.

A declaração de um vetor na linguagem Go é feita utilizando um tipo de dado desejado, sendo primitivo ou complexo, e suas dimensões entre [ e ].

Sintaxe A
var nome_matriz[linhas][colunas] tipo_dado
Sintaxe B
var nome_matriz = [linhas][colunas] tipo_dado { {el1, el2 , elN }, //linha 1
                                               {el3, el4 , elN} , //linha 2 
                                               {elM, elM, elM}    //Linha N
                                             }
var nome_matriz = [][] tipo_dado { {el1, el2 , elN }, //linha 1
                                   {el3, el4 , elN} , //linha 2 
                                   {elM, elM, elM}    //Linha N
                                 }
Onde
linhas: número de linhas
linhas: número de linhas
tipo_dado: Tipo de dado dos elementos armazenados
el1...N: Elementos do tipo tipo_dado que iniciam nome_matriz

Umma matriz com valores iniciados devem ter seus valores, baseados no tipo de dado utilizado, delimitados por { e } e separados por (,) para cada linha.

A linguagem Go não permite utilizar uma variáveis como dimensão ao declarar uma matriz. Apenas constantes são aceitas.

As matrizes, quando não iniciados, tem seu elementos iniciados automaticamente utilizando seus valores padrão aceitos de acordo com o tipo utilizado.

Exemplo 1
package main

func main() {
	var mint [2][2]int 
	mint = [2][2]int{{1, 2}, {3, 4}}
}
Saída
./prog.go:4:6: vint declared and not used

O acesso aos elementos de vetor é feita utilizando o suas dimensões linha e coluna entre o indexador [], assim como em várias outras linguagens como C, C++, Java e etc.

Ponteiros também podem ser utilizados, mas esse assunto será visto em Ponteiros.

Sintaxe C: Atribuição
nome_matriz[linha][coluna] = valor
Sintaxe D: Recuperação
nome_matriz[linha][coluna];
Onde
linha: Linha do elemento
coluna: Coluna do elemento
Exemplo 2
package main
import "fmt"

func main() {
	var mint [2][2]int 
	vint = [2][2]int{{1, 2}, {3, 4}}

    fmt.Println(mint)

    vint[0][0] = 777

	fmt.Println(mint)
}
            
Saída
[1 2]
[3 4]
[777 2]
[3 4]

Para percorrermos ou iterarmos matrizes na linguagem Go, podemos utilizar o comando for ou for + comando range que foram vistos em Go: Comandos de repetição.

Exemplo 3: for + range
package main
import "fmt"

func main() {

	var mint = [2][3]int{{1, 2, 3}, {4, 5, 6}}

	for indice, valor := range mint {
		fmt.Println(indice, valor) 
	}
}
Saída
0 [1 2 3]
1 [4 5 6]
Exemplo 4: for
package main

import "fmt"

func main() {
	var mint [2][3]int 
	vint = [2][3]int{{1, 2, 3}, {3, 4, 5}}

	for i := 0; i < 2; i++ {
		for j := 0; j < 3; j++ {
			fmt.Printf("%d ", mint[i][j])
		}
		fmt.Printf("\n")
	}
}
Saída
1 2 3
3 4 5

A linguagem Go, não fornece nativamente uma função para que seja possível realizar a cópia de matrizes, mas podemos copiar os elemento de uma matriz utilizando o operador (:=).

Sintaxe E
matriz_destino := matriz_origem
Exemplo 5
package main
import "fmt"

func main() {

	origem := [2][2]int{{1, 2}, {3, 4}}

	destino := origem

	fmt.Println("orig:", origem)
	fmt.Println("dest:", destino)

	origem[0][0] = 777

	fmt.Println("orig:", origem)
	fmt.Println("dest:", destino)
}
Saída
orig: [[1 2 0] [3 4 0]]
dest: [[1 2 0] [3 4 0]]
orig: [[777 2 0] [3 4 0]]
dest: [[1 2 0] [3 4 0]]

A forma mais básica de passarmos uma matriz como argumento para uma função é por valor. Vale lembrar que quando essa abordagem é utilizada, alterando o valor de um elemento da matriz não irá refletir na variável que foi passada como argumento.

Sintaxe F
func nome_funcao(param [linha][coluna] tipo_dado,linhas tipo_dado, colunas tipo_dado) (tipo_retorno){ /*corpo*/}
Sintaxe G
nome_funcao(nome_matriz)

As sintaxe F e G acima mostram a declaração de um protótipo de uma função e a passagem de uma matriz como argumento respectivamente.

Exemplo 6
package main
import "fmt"

func funcao(mat [2][3]int, linhas int , colunas int) {

	for i := 0; i < linhas; i++ {

		for j := 0; j < colunas; j++ {
			fmt.Printf("%d", mat[i][j])
		}

		fmt.Printf("\n")
	}
}

func main() {
	var vint [2][3]int 
	vint = [2][3]int{{1, 2, 3}, {3, 4, 5}}

	funcao(vint,2,3)
}
Saída
123
345

Para que seja possível a persistência de uma alteração feita em uma matriz, sendo esse acessado dentro de uma função ou método, é necessário fazer a passagem da matriz por referência utilizando o operador (&).

Sintaxe H
func nome_funcao(param *[linhas][colunas]tipo_dado, linhas tipo_dado, colunas tipo_dado) (tipo_retorno){ /*corpo*/}
Sintaxe I
nome_funcao(&nome_vetor,linhas,colunas)

As sintaxe H e I acima mostram a declaração de um protótipo de uma função e a passagem de uma matriz como argumento respectivamente.

Exemplo 7
package main
import "fmt"

func funcao(mat *[2][3]int, linhas int, colunas int) {

	for i := 0; i < linhas; i++ {
		for j := 0; j < colunas; j++ {
			mat[i][j] *= 2
		}
	}
}

func main() {
	var mint [2][3]int
	vint = [2][3]int{{1, 2, 3}, {3, 4, 5}}

	fmt.Println("antes:", mint)
	funcao(&mint, 2, 3)
	fmt.Println("depois:", mint)
}
Saída
antes: [[1 2 3] [3 4 5]]
depois: [[2 4 6] [6 8 10]]

O retorno de vetores em funções é feito da mesma forma como qualquer outro tipo de dado já visto. Declaramos o tipo de retorno no protótipo da função como matriz com ou sem sua dimensão.

Sintaxe J
func nome_funcao(parametros) (nome_retorno [linhas][colunas]tipo_dado)
func nome_funcao(parametros) ([linhas][colunas]tipo_dado)
func nome_funcao(parametros) ([][]tipo_dado)
Exemplo 8
package main

import "fmt"

func funcao1() (mat [][]int) {
	mat = [][]int{{1, 2}, {3, 4}}
	return
}
func funcao2() [2][2]int {
	mat := [2][2]int{{1, 2}, {3, 4}}
	return mat
}

func funcao3() [][]int {
	mat := [][]int{{1, 2}, {3, 4}}
	return mat
}

func main() {

	mint1 := funcao1()
	fmt.Println(mint1)
	mint2 := funcao2()
	fmt.Println(mint2)
	mint3 := funcao3()
	fmt.Println(mint3)
}
            
Saída
[[1 2] [3 4]]
[[1 2] [3 4]]
[[1 2] [3 4]]

  1. 17/09/2024 - revisão 2 - Correção em nome de sintaxes/numéro de exemplos; ajustes gramaticais pontuais
  2. 02/10/2023 - revisão 1 - Correção em referências, erros gramaticais
  3. 21/08/2023 - versão inicial