Langage Go : tableaux multidimensionnels
Un tableau multidimensionnel est un tableau de tableaux. Considérez-le comme unetable de donnéesoumatrice, où chaque élément peut être accédé via plusieurs indices.
Les tableaux multidimensionnels en Go peuvent servir à gérer des informations structurées telles que des données tabulaires, des opérations matricielles ou des plateaux de jeu.
Concepts de base
- Tableau unidimensionnel: comme des points sur une ligne droite, une seule coordonnée (indice) est nécessaire pour trouver un élément spécifique
- Tableau à deux dimensions: comme une table, nécessitant deux coordonnées : ligne et colonne
- Tableau à trois dimensions: comme un cube, nécessitant trois coordonnées : longueur, largeur et hauteur
- Dimensions supérieures: peuvent théoriquement avoir de nombreuses dimensions, mais en pratique les tableaux à deux et trois dimensions sont les plus couramment utilisés
Cela peut être comparé à nos places de parking du quotidien :
- Tableau à une dimension= une rangée de places de parking (il suffit du numéro de place)
- Tableau à deux dimensions= un parking à plusieurs étages (il faut l'étage et le numéro de place)
- Tableau à trois dimensions= plusieurs parkings à plusieurs étages (il faut le numéro du parking, l'étage et le numéro de place)
Go prend en charge les tableaux multidimensionnels. Voici les façons courantes de déclarer des tableaux multidimensionnels :
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
Déclaration et initialisation :
// Déclarer un tableau à deux dimensions var arrayName [rows][cols]elementType // Déclarer et initialiser var arrayName [rows][cols]elementType = [rows][cols]elementType{initialValues}L'exemple suivant déclare un tableau d'entiers à trois dimensions :
var threedim [5][10][4]int
Tableau à deux dimensions
Un tableau à deux dimensions est le plus simple des tableaux multidimensionnels. Un tableau à deux dimensions est essentiellement composé de tableaux à une dimension. La façon de définir un tableau à deux dimensions est la suivante :
var arrayName [ x ][ y ] variable_type
variable_type est le type de données en Go, arrayName est le nom du tableau. Un tableau à deux dimensions peut être considéré comme une table, avec x pour les lignes et y pour les colonnes. Le diagramme suivant montre un tableau à deux dimensions a avec trois lignes et quatre colonnes :

Les éléments d'un tableau à deux dimensions sont accessibles viaa[ i ][ j ]pour accéder.
Exemple
import "fmt"
func main() {
// Étape 1 : Créer un tableau
values := [][]int{}
// Étape 2 : Utiliser la fonction append() pour ajouter deux lignes de tableaux à une dimension à un tableau à deux dimensions vide
row1 := []int{1, 2, 3}
row2 := []int{4, 5, 6}
values = append(values, row1)
values = append(values, row2)
// Étape 3 : Afficher deux lignes de données
fmt.Println("Ligne 1")
fmt.Println(values[0])
fmt.Println("Ligne 2")
fmt.Println(values[1])
// Étape 4 : accéder au premier élément
fmt.Println("Premier élément :")
fmt.Println(values[0][0])
}
La sortie de l'exemple ci-dessus est :
Row 1 [1 2 3] Row 2 [4 5 6] 第一个元素为: 1
Initialisation d'un tableau à deux dimensions
Les tableaux multidimensionnels peuvent être initialisés avec des accolades. L'exemple suivant est un tableau à deux dimensions avec 3 lignes et 4 colonnes :
a := [3][4]int{
{0, 1, 2, 3} , /* 第一行索引为 0 */
{4, 5, 6, 7} , /* 第二行索引为 1 */
{8, 9, 10, 11}, /* 第三行索引为 2 */
}
Remarque :Dans le code ci-dessus, l'avant-dernière ligne}doit avoir une virgule, car la dernière ligne}n'a pas besoin d'être sur une seule ligne ; elle peut aussi être écrite comme ceci :a := [3][4]int{
{0, 1, 2, 3} , /* 第一行索引为 0 */
{4, 5, 6, 7} , /* 第二行索引为 1 */
{8, 9, 10, 11}} /* 第三行索引为 2 */
L'exemple suivant initialise un tableau à deux dimensions avec 2 lignes et 2 colonnes :
Exemple
import "fmt"
func main() {
// Créer un tableau à deux dimensions
sites := [2][2]string{}
// Ajouter des éléments au tableau à deux dimensions
sites[0][0] = "Google"
sites[0][1] = "Exemple"
sites[1][0] = "Taobao"
sites[1][1] = "Weibo"
// Afficher le résultat
fmt.Println(sites)
}
La sortie de l'exemple ci-dessus est :
[[Google Example] [Taobao Weibo]]
Accès à un tableau à deux dimensions
On accède à un tableau à deux dimensions en spécifiant des coordonnées, telles que l'indice de ligne et l'indice de colonne dans le tableau. Par exemple :
val := a[2][3] ou var value int = a[2][3]
L'exemple ci-dessus a accédé au quatrième élément de la troisième ligne du tableau à deux dimensions val.
Un tableau à deux dimensions peut utiliser des boucles imbriquées pour afficher des éléments :
Exemple
import "fmt"
func main() {
/* Tableau - 5 lignes 2 colonnes*/
var a = [5][2]int{ {0,0}, {1,2}, {2,4}, {3,6},{4,8}}
var i, j int
/* afficher les éléments du tableau */
for i = 0; i < 5; i++ {
for j = 0; j < 2; j++ {
fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )
}
}
}
La sortie de l'exemple ci-dessus est :
a[0][0] = 0 a[0][1] = 0 a[1][0] = 1 a[1][1] = 2 a[2][0] = 2 a[2][1] = 4 a[3][0] = 3 a[3][1] = 6 a[4][0] = 4 a[4][1] = 8
L'exemple suivant crée un tableau multidimensionnel où le nombre d'éléments dans chaque dimension est incohérent :
Exemple
import "fmt"
func main() {
// Créer un tableau à deux dimensions vide
animals := [][]string{}
// Créez trois tableaux à une dimension, chacun avec des longueurs différentes
row1 := []string{"fish", "shark", "eel"}
row2 := []string{"bird"}
row3 := []string{"lizard", "salamander"}
// Utilisez la fonction append() pour ajouter un tableau à une dimension au tableau à deux dimensions
animals = append(animals, row1)
animals = append(animals, row2)
animals = append(animals, row3)
// Boucle pour afficher
for i := range animals {
fmt.Printf("Row: %v\n", i)
fmt.Println(animals[i])
}
}
La sortie de l'exemple ci-dessus est :
Row: 0 [fish shark eel] Row: 1 [bird] Row: 2 [lizard salamander]
Accès et modification des éléments d'un tableau
Accéder aux éléments
Exemple
import "fmt"
func main() {
// Créer une matrice 3x3
matrix := [3][3]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
// Accéder à un élément
fmt.Println("Ligne 1, Colonne 2 :", matrix[0][1]) // Sortie : 2
fmt.Println("Ligne 3, Colonne 3 :", matrix[2][2]) // Sortie : 9
// Accéder à la ligne entière
fmt.Println("Ligne 2 :", matrix[1]) // Sortie : [4 5 6]
// Parcourir tous les éléments
fmt.Println("\nParcourir tous les éléments :")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j])
}
}
}
modifier les éléments
Exemple
import "fmt"
func main() {
// Créer une matrice nulle 2x2
var grid [2][2]int
fmt.Println("Matrice avant modification :", grid)
// Modifier l'élément à une position spécifique
grid[0][0] = 10
grid[0][1] = 20
grid[1][0] = 30
grid[1][1] = 40
fmt.Println("Matrice après modification :", grid)
// Modifier une ligne en lot
grid[0] = [2]int{100, 200}
fmt.Println("Après modification de la première ligne :", grid)
}
Tableaux tridimensionnels et de dimensions supérieures
Exemple de tableau tridimensionnel
Exemple
import "fmt"
func main() {
// Déclarer un tableau tridimensionnel 2x3x4
// Peut être compris comme : 2 plans, chacun avec 3 lignes et 4 colonnes
var cube [2][3][4]int
// Initialiser un tableau 3D
cube = [2][3][4]int{
{ // Le premier plan
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
},
{ // Le deuxième plan
{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24},
},
}
// Accéder aux éléments d'un tableau 3D
fmt.Println("cube[0][1][2] =", cube[0][1][2]) // Sortie : 7
fmt.Println("cube[1][2][3] =", cube[1][2][3]) // Sortie : 24
// Parcourir un tableau 3D
fmt.Println("\nContenu du tableau tridimensionnel :)
for i := 0; i < 2; i++ {
fmt.Printf("Plan %d :\n", i)
for j := 0; j < 3; j++ {
for k := 0; k < 4; k++ {
fmt.Printf("%3d ", cube[i][j][k])
}
fmt.Println()
}
fmt.Println()
}
}
voir la figure ci-dessous :

Opérations courantes sur les tableaux multidimensionnels
1. Itération avec range
Exemple
import "fmt"
func main() {
// Créer un tableau 2D
scores := [3][4]int{
{85, 90, 78, 92},
{88, 76, 95, 89},
{92, 85, 88, 90},
}
fmt.Println("Tableau des notes des étudiants :")
// Utiliser range pour parcourir le tableau 2D
for i, row := range scores {
fmt.Printf("Notes de l'étudiant %d : ", i+1)
for j, score := range row {
fmt.Printf("%d ", score)
// Si vous avez besoin à la fois de l'index et de la valeur
_ = j // Éviter l'avertissement de variable inutilisée
}
fmt.Println()
}
// Seule la valeur importe, pas l'index
total := 0
count := 0
for _, row := range scores {
for _, score := range row {
total += score
count++
}
}
fmt.Printf("\nScore moyen : %.2f\n", float64(total)/float64(count))
}
2. Obtenir la longueur du tableau
Exemple
import "fmt"
func main() {
// Créer un tableau multidimensionnel irrégulier
jagged := [3][3]int{
{1, 2, 3},
{4, 5},
{6, 7, 8, 9}, // Remarque : Cela provoquera une erreur de compilation car chaque ligne doit avoir la même longueur
}
// Exemple correct : Obtenir les dimensions du tableau
matrix := [4][5]int{}
// Obtenir le nombre de lignes
rows := len(matrix)
fmt.Println("Lignes :", rows) // Sortie : 4
// Obtenir le nombre de colonnes dans la première ligne (toutes les lignes ont la même longueur)
cols := len(matrix[0])
fmt.Println("Colonnes :", cols) // Sortie : 5
// Obtenir le nombre total d'éléments
totalElements := rows * cols
fmt.Println("Total des éléments :", totalElements) // Sortie : 20
}
3. Comparaison de tableaux
Exemple
import "fmt"
func main() {
// Créer deux tableaux 2D identiques
a := [2][2]int{{1, 2}, {3, 4}}
b := [2][2]int{{1, 2}, {3, 4}}
c := [2][2]int{{1, 2}, {3, 5}}
// Les tableaux peuvent être comparés directement (uniquement lorsque les dimensions sont exactement les mêmes)
fmt.Println("a == b:", a == b) // Sortie : true
fmt.Println("a == c:", a == c) // Sortie : false
// Remarque : des tableaux de dimensions différentes ne peuvent pas être comparés
// d := [2][3]int{{1, 2, 3}, {4, 5, 6}}
// fmt.Println(a == d) // Erreur de compilation : types incompatibles
}
Scénarios d'application pratiques
Scénario 1 : plateau de jeu (Tic-Tac-Toe)
Exemple
import "fmt"
func main() {
// Initialiser un plateau de tic-tac-toe 3x3
var board [3][3]string
// Initialiser à vide
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
board[i][j] = " "
}
}
// Simuler les coups
board[0][0] = "X"
board[1][1] = "O"
board[2][2] = "X"
// Afficher le plateau
fmt.Println("Plateau de tic-tac-toe :")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf(" %s ", tableau[i][j])
if j < 2 {
fmt.Printf("|")
}
}
fmt.Println()
if i < 2 {
fmt.Println("---+---+---")
}
}
}
Scénario 2 : Système de gestion des notes des étudiants
Exemple
import "fmt"
func main() {
// Définir : 3 étudiants, chaque étudiant a 4 cours
var grades [3][4]float64
// Saisir les notes des étudiants
grades = [3][4]float64{
{85.5, 90.0, 78.5, 92.0}, // Notes de l'étudiant 1
{88.0, 76.5, 95.0, 89.5}, // Notes de l'étudiant 2
{92.5, 85.0, 88.5, 90.0}, // Notes de l'étudiant 3
}
// Calculer la moyenne de chaque étudiant
fmt.Println("Statistiques des notes des étudiants :")
for i, studentGrades := range grades {
sum := 0.0
for _, grade := range studentGrades {
sum += grade
}
average := sum / float64(len(studentGrades))
fmt.Printf("Étudiant %d : score moyen = %.2f\n", i+1, average)
}
// Calculer la moyenne de chaque cours
fmt.Println("\nMoyenne du cours :")
for j := 0; j < 4; j++ {
sum := 0.0
for i := 0; i < 3; i++ {
sum += grades[i][j]
}
average := sum / 3.0
fmt.Printf("Cours %d : score moyen = %.2f\n", j+1, average)
}
}
Scénario 3 : Traitement des pixels d'image
Exemple
import "fmt"
func main() {
// Simuler une simple image en niveaux de gris 3x3
// Plage de valeurs de chaque pixel : 0(noir) ~ 255(blanc)
var image [3][3]int
// Initialiser l'image (un dégradé simple)
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
image[i][j] = (i + j) * 50
}
}
// Afficher l'image originale
fmt.Println("Image originale :")
displayImage(image)
// Traitement d'image : augmenter la luminosité
fmt.Println("\nImage après augmentation de la luminosité :")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
// Augmenter la luminosité, mais ne pas dépasser 255
newValue := image[i][j] + 50
if newValue > 255 {
newValue = 255
}
image[i][j] = newValue
}
}
displayImage(image)
}
func displayImage(img [3][3]int) {
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("%3d ", img[i][j])
}
fmt.Println()
}
}
Notes et bonnes pratiques
1. La longueur d'un tableau fait partie du type
Exemple
import "fmt"
func main() {
// Ces deux ont des types différents !
var a [2][3]int
var b [3][2]int
// Le code suivant provoquera une erreur de compilation
// a = b // erreur : incompatibilité de type
fmt.Printf("type de a : %T\n", a) // [2][3]int
fmt.Printf("type de b : %T\n", b) // [3][2]int
}
2. Type valeur vs type référence
Exemple
import "fmt"
func main() {
// Les tableaux sont des types valeur
original := [2][2]int{{1, 2}, {3, 4}}
// L'affectation crée une copie
copy := original
// Modifier la copie n'affecte pas le tableau d'origine
copy[0][0] = 100
fmt.Println("Tableau d'origine :", original) // [[1 2] [3 4]]
fmt.Println("Tableau copié :", copy) // [[100 2] [3 4]]
// Si vous avez besoin d'une sémantique de référence, vous pouvez utiliser des slices (introduites dans des articles ultérieurs)
}
3. Considérations sur les performances
- Mémoire contiguë: les tableaux multidimensionnels sont stockés de manière contiguë en mémoire, offrant un accès rapide
- Taille fixe: la longueur d'un tableau est déterminée à la compilation et ne peut pas être modifiée dynamiquement
- Scénarios adaptés: lorsque la taille des données est connue et fixe, les tableaux sont le meilleur choix
Questions fréquentes
Q1 : Quelle est la différence entre un tableau multidimensionnel et une slice imbriquée ?
| Fonctionnalités | Tableaux multidimensionnels | Slices imbriquées |
|---|---|---|
| Size | Fixe, déterminé à la compilation | Dynamique, variable à l'exécution |
| Mémoire | Allocation contiguë | Éventuellement non contiguë |
| Performance | Vitesse d'accès rapide | Légèrement plus lent, présente un surcoût |
| Cas d'utilisation | Taille des données connue | Taille des données variable |
Q2 : Comment créer un tableau à deux dimensions irrégulier ?
Les tableaux Go exigent que chaque ligne ait la même longueur. Si vous avez besoin d'une structure irrégulière, vous devez utiliser des slices :
Exemple
irregular := [][]int{
{1, 2, 3},
{4, 5}, // Cette ligne n'a que 2 éléments
{6, 7, 8, 9}, // Cette ligne a 4 éléments
}
Q3 : Un tableau multidimensionnel peut-il être utilisé comme paramètre de fonction ?
Oui, mais notez que les tableaux sont des types valeur, et que le passage de grands tableaux entraîne un coût de performance :
Exemple
// Traiter la matrice...
matrix[0][0] = 100
return matrix
}
// Une meilleure approche consiste à utiliser des pointeurs ou des slices
func processMatrixPtr(matrix *[3][3]int) {
matrix[0][0] = 100
}