Двумерные массивы в Go 1.21: подробное руководство
Двумерные массивы в Go
Что такое двумерный массив?
Представь себе шахматную доску. У неё есть строки (ряды) и столбцы (места в ряду). Каждая клетка на доске — это ячейка, у которой есть свой номер строки и номер столбца. В программировании такая «таблица» называется двумерным массивом.
Двумерный массив — это массив, каждый элемент которого сам является массивом. Проще говоря, это таблица, где данные хранятся в строках и столбцах.
Зачем это нужно? Например, чтобы хранить:
- Схему кинозала: строки — ряды, столбцы — места.
- Карту острова: строки — координаты по вертикали, столбцы — по горизонтали.
- Таблицу товаров на складе: строки — полки, столбцы — типы товаров.
Как объявить двумерный массив в Go?
Синтаксис очень похож на обычный массив, только мы указываем два размера: сначала количество строк, потом количество столбцов.
// Объявление массива 3x3 (3 строки, 3 столбца)
var cinema [3][3]int
// Объявление и сразу заполнение
matrix := [2][3]int{
{1, 2, 3},
{4, 5, 6},
}
Обращаться к элементу нужно по двум индексам: имя_массива[номер_строки][номер_столбца]. Важно: нумерация начинается с 0!
package main
import "fmt"
func main() {
// Создаём массив 2x2
var data [2][2]int
// Заполняем его вручную
data[0][0] = 10
data[0][1] = 20
data[1][0] = 30
data[1][1] = 40
// Выводим элемент из первой строки, второго столбца
fmt.Println("Элемент [0][1]:", data[0][1]) // Выведет: 20
}
Как работать с двумерным массивом?
Чаще всего нужно пройтись по всем элементам. Для этого используют вложенные циклы — один цикл перебирает строки, другой внутри перебирает столбцы.
package main
import "fmt"
func main() {
// Создаём массив 3x4 и заполняем нулями
var grid [3][4]int
// Заполняем значениями: номер строки + номер столбца
for row := 0; row < 3; row++ {
for col := 0; col < 4; col++ {
grid[row][col] = row + col
}
}
// Выводим таблицу на экран
for row := 0; row < 3; row++ {
for col := 0; col < 4; col++ {
fmt.Print(grid[row][col], " ")
}
fmt.Println() // Переход на новую строку
}
}
Вывод программы:
0 1 2 3
1 2 3 4
2 3 4 5
Как заполнить массив с клавиатуры?
Часто в задачах нужно вводить данные от пользователя. Используем fmt.Scan внутри вложенных циклов.
package main
import "fmt"
func main() {
var rows, cols int
fmt.Print("Введите количество строк и столбцов: ")
fmt.Scan(&rows, &cols)
// Создаём массив нужного размера
arr := make([][]int, rows)
for i := 0; i < rows; i++ {
arr[i] = make([]int, cols)
}
// Заполняем с клавиатуры
fmt.Println("Введите элементы построчно:")
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
fmt.Scan(&arr[i][j])
}
}
// Выводим таблицу
fmt.Println("Ваша таблица:")
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
fmt.Print(arr[i][j], "\t")
}
fmt.Println()
}
}
Разбор типичных задач
Задача «Кинозал»
Нужно создать схему зала. Пусть свободные места — 0, занятые — 1. Мы получаем размеры зала и заполняем его.
package main
import "fmt"
func main() {
var rows, cols int
fmt.Scan(&rows, &cols)
// Создаём схему зала
hall := make([][]int, rows)
for i := 0; i < rows; i++ {
hall[i] = make([]int, cols)
// Заполняем ряд: если i % 2 == 0, то все места свободны, иначе заняты
for j := 0; j < cols; j++ {
if i%2 == 0 {
hall[i][j] = 0 // Свободно
} else {
hall[i][j] = 1 // Занято
}
}
}
// Выводим схему
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
fmt.Print(hall[i][j], " ")
}
fmt.Println()
}
}
Задача «Популярность постов»
У нас есть блогеры и их посты. Нужно найти, у какого блогера больше всего лайков.
package main
import "fmt"
func main() {
var bloggers, posts int
fmt.Print("Количество блогеров и постов: ")
fmt.Scan(&bloggers, &posts)
// Создаём таблицу лайков
likes := make([][]int, bloggers)
for i := 0; i < bloggers; i++ {
likes[i] = make([]int, posts)
fmt.Printf("Введите лайки для блогера %d: ", i+1)
for j := 0; j < posts; j++ {
fmt.Scan(&likes[i][j])
}
}
// Ищем блогера с максимальной суммой лайков
maxSum := 0
maxBlogger := 0
for i := 0; i < bloggers; i++ {
sum := 0
for j := 0; j < posts; j++ {
sum += likes[i][j]
}
if sum > maxSum {
maxSum = sum
maxBlogger = i + 1
}
}
fmt.Printf("Самый популярный блогер: %d (всего лайков: %d)\n", maxBlogger, maxSum)
}
Частые ошибки новичков
- Путают индексы: помните, что первый индекс — это строка, второй — столбец.
arr[строка][столбец]. - Выход за границы массива: если массив размером 3x3, то индексы могут быть только 0, 1, 2. Обращение к индексу 3 вызовет ошибку.
- Забывают про вложенные циклы: чтобы пройтись по всем элементам, нужно два цикла. Один цикл не сможет перебрать все ячейки.
- Неправильное создание через make: сначала нужно создать массив для строк (
make([][]int, rows)), а потом для каждой строки создать свой массив (make([]int, cols)).
Итоговый пример: «Карта сокровищ»
Представь, что у нас есть карта острова 4x4. На карте цифрами обозначены высоты. Нужно найти самую высокую точку и вывести её координаты.
package main
import "fmt"
func main() {
// Карта острова (задаём сразу)
island := [4][4]int{
{1, 3, 2, 4},
{5, 7, 6, 8},
{9, 2, 3, 1},
{4, 5, 6, 0},
}
// Ищем максимальную высоту
maxHeight := island[0][0]
maxRow := 0
maxCol := 0
for row := 0; row < 4; row++ {
for col := 0; col < 4; col++ {
if island[row][col] > maxHeight {
maxHeight = island[row][col]
maxRow = row
maxCol = col
}
}
}
fmt.Printf("Самая высокая точка находится в строке %d, столбце %d\n", maxRow, maxCol)
fmt.Printf("Высота: %d метров\n", maxHeight)
}
Вывод программы:
Самая высокая точка находится в строке 2, столбце 0
Высота: 9 метров
Важно: строки и столбцы считаются с 0! Если хочешь показывать пользователю привычные номера (начиная с 1), просто добавь 1 при выводе: maxRow+1 и maxCol+1.
Двумерные массивы — это мощный инструмент для работы с табличными данными. Потренируйся создавать свои таблицы, заполнять их и обрабатывать, и ты быстро освоишь эту тему!