1. Тип int: базовый тип целых чисел
Когда вы только начинаете программировать, самое частое действие — что-то посчитать: сумму, разницу, количество, остаток, размер, индекс. И вот тут появляется тип int: он хранит целые числа без дробной части. В Go это базовый и самый популярный тип для счётчиков и «обычных чисел», поэтому сегодня мы будем тренироваться именно на нём.
Важная мысль: int — это про числа, которые можно представить как «…, -2, -1, 0, 1, 2, …». Отрицательные значения тоже допустимы. Например, температура может быть -5, баланс может быть -200, а настроение после трёх часов отладки — ну, вы поняли.
Техническая ремарка без углубления: размер int зависит от платформы (обычно 32 или 64 бита). Для учебных задач вам достаточно знать, что int подходит для большинства обычных расчётов.
Мини-пример: объявили int и вывели
package main
import "fmt"
func main() {
var tasks int = 12
fmt.Println(tasks) // 12
}
Обратите внимание: мы явно написали int, но могли бы и короче — через := (мы это уже проходили раньше).
package main
import "fmt"
func main() {
tasks := 12
fmt.Println(tasks) // 12
}
2. Операторы +, -, *: сложение, вычитание, умножение
Теперь, когда у нас есть числа, хочется делать с ними то, ради чего люди вообще терпят математику в школе: считать. В Go для int доступны привычные арифметические операторы: + (сложение), - (вычитание) и * (умножение). Они выглядят ровно так, как вы ожидаете, и ведут себя тоже ожидаемо — это один из приятных моментов языка.
Важный нюанс для новичков: в Go нет «скрытой магии» вроде автоматических преобразований типов в арифметике. Если у вас числа — вы работаете с числами. Если строки — это отдельная история, и склеивание строк через + мы будем разбирать отдельно. Сегодня держим фокус на целых числах.
Пример: «мини-планировщик задач»
Представим, что у нас есть план на день и уже выполненные задачи. Посчитаем, сколько осталось.
package main
import "fmt"
func main() {
planned := 10
done := 3
remaining := planned - done
fmt.Println(remaining) // 7
}
А теперь добавим «очки продуктивности»: допустим, за каждую выполненную задачу вы получаете 5 очков. Посчитаем.
package main
import "fmt"
func main() {
done := 3
pointsPerTask := 5
points := done * pointsPerTask
fmt.Println(points) // 15
}
Да, это похоже на RPG. В каком-то смысле программирование так и работает: качаем уровень, собираем артефакты, побеждаем багов.
3. Оператор /: целочисленное деление
Деление — самая частая «подстава» для новичка, потому что мозг помнит школьную математику, а компьютер — типы данных. Если вы делите два значения типа int, результат тоже будет int. А это значит, что дробная часть просто отбрасывается. Не округляется, не «сохраняется где-то рядом», не прячется в тёмном углу программы — её просто нет.
Это поведение называется целочисленным делением. Оно не «плохое» и не «хорошее»: оно полезное, если вы делите конфеты между детьми или страницы между главами. Но оно может быть неожиданным, если вы рассчитывали на дробь.
Пример: «поровну» и «без сдачи»
package main
import "fmt"
func main() {
a := 7
b := 2
fmt.Println(a / b) // 3
}
Почему так? Потому что 7 / 2 в целых числах — это «сколько раз двойка помещается в семёрке целиком». Три раза. Остаток будет отдельно, и для него у нас есть оператор % (чуть позже).
Практический пример: «процент выполнения» без дробей
Проценты часто хочется выводить красиво, но мы пока работаем только с int, поэтому сделаем «целый процент».
package main
import "fmt"
func main() {
planned := 10
done := 3
percent := (done * 100) / planned
fmt.Println(percent) // 30
}
Здесь важно, что мы умножили done на 100 до деления, иначе done / planned дало бы 0, и дальше всё было бы грустно и неправдоподобно.
4. Оператор %: остаток от деления
Оператор % в Go — это остаток от деления. Он отвечает на вопрос: «Что осталось, когда мы разделили максимально “ровно”, без дробей?» Если / даёт нам «целую часть», то % даёт «хвостик». И этот хвостик невероятно полезен: проверка чётности, расклад минут по часам, распределение чего-то «поровну» и понимание, сколько осталось.
Важно сразу отучиться от ассоциации «проценты». Знак похож на символ процента, но смысл другой. В программировании % — это остаток.
Пример: конфеты и дети
package main
import "fmt"
func main() {
candies := 17
kids := 5
each := candies / kids
left := candies % kids
fmt.Println(each) // 3
fmt.Println(left) // 2
}
Читается по-человечески: «каждому по 3, ещё 2 останется». И да, именно так вы внезапно становитесь главным по честному дележу в компании.
Пример: минуты в часы и минуты
Классическая задачка: есть количество минут, хотим получить «сколько часов» и «сколько минут остатком».
package main
import "fmt"
func main() {
totalMinutes := 135
hours := totalMinutes / 60
minutes := totalMinutes % 60
fmt.Println(hours, minutes) // 2 15
}
Обратите внимание: мы пока не собираем строку вида 2:15, потому что это уже тема про строки. Сейчас нам важна математика: / даёт «сколько целых часов», % — «сколько минут осталось».
5. Приоритет операторов: как читаются выражения
Когда выражения становятся длиннее, появляется вопрос: «А что выполнится первым?» У операторов есть приоритет. В Go, как и в обычной математике, умножение и деление выполняются раньше сложения и вычитания. А остаток % по приоритету стоит рядом с * и /. Это значит, что выражение 2 + 3*4 вычислится как 2 + (3*4).
Новичок часто получает «не тот ответ» именно из-за приоритета, а потом подозревает Go в заговоре. На самом деле заговор простой: математика.
Таблица приоритета
| Операторы | Пример | Выполняются раньше? |
|---|---|---|
|
|
Да |
|
|
Нет |
Пример: одно выражение — два результата
package main
import "fmt"
func main() {
fmt.Println(2 + 3*4) // 14
fmt.Println((2 + 3) * 4) // 20
}
Скобки — это ваш способ сказать: «Я точно знаю, что хочу, и прошу компьютер не догадываться за меня». Даже если вы помните приоритет, скобки делают код читаемее. В промышленной разработке это часто важнее, чем экономия двух символов.
6. Мини-проект: делим пиццу и считаем прогресс
Сейчас у нас уже достаточно инструментов, чтобы написать маленькую программу, которая выглядит как «настоящее приложение», а не просто набор разрозненных вычислений. Мы пока не читаем данные из ввода, это будет отдельной темой, поэтому значения зададим прямо в коде. Зато потренируемся сразу в + - * / %, в приоритете и в целочисленном делении.
Идея такая: у нас есть пицца, разрезанная на кусочки, есть компания людей, и есть план «сколько кусочков можно съесть сегодня, чтобы совесть не звонила маме». Посчитаем порции, остаток и процент от плана.
Версия 1: делим поровну и считаем остаток
package main
import "fmt"
func main() {
slices := 14
people := 5
each := slices / people
left := slices % people
fmt.Println(each, left) // 2 4
}
Результат 2 4 означает: «каждому по 2 кусочка, 4 останется».
Версия 2: добавляем «план» и процент выполнения
Допустим, наш план — съесть не больше 10 кусочков всей компанией (пицца в опасности, но мы держимся).
package main
import "fmt"
func main() {
plan := 10
alreadyEaten := 3
remaining := plan - alreadyEaten
percent := (alreadyEaten * 100) / plan
fmt.Println(remaining) // 7
fmt.Println(percent) // 30
}
Здесь мы использовали сразу несколько вещей: вычитание для остатка по плану, умножение и деление для целого процента, а также скобки. В данном случае скобки не обязательны, но помогают читать.
Версия 3: сколько пицц нужно при размере pizzaSize
Представим, что мы заранее знаем, сколько всего кусочков нужно на всех (например, по 3 на человека), и хотим понять, сколько целых пицц покупать и сколько кусочков останется «на утро» (утро, конечно, наступит не у всех).
package main
import "fmt"
func main() {
people := 5
slicesPerPerson := 3
pizzaSize := 8
totalSlices := people * slicesPerPerson
pizzas := totalSlices / pizzaSize
left := totalSlices % pizzaSize
fmt.Println(pizzas, left) // 1 7
}
Получилось 1 7: одна целая пицца и ещё 7 кусочков сверху. То есть фактически нужно 2 пиццы, но вот здесь мы упираемся в то, что у нас пока нет условий if. Поэтому сейчас мы честно показываем результат деления и остатка. Чуть позже, когда появятся условия, мы научимся делать «округление вверх» в таких задачах корректно и автоматически.
7. Типичные ошибки при работе с int и арифметикой
Ошибка №1: ожидать дробный результат от int / int.
Очень легко по привычке думать, что 7 / 2 должно дать 3.5. Но если оба числа — int, результат тоже int, а дробная часть отбрасывается. Если вам нужны «настоящие дроби», это отдельная тема, и там будут другие типы чисел и другие привычки.
Ошибка №2: забывать про приоритет операторов и получать «странные» ответы.
Выражение a + b*c считается как a + (b*c), а не как (a+b)*c. Если порядок важен, скобки — ваш лучший друг. Даже когда скобки не обязательны, они часто делают намерение кода очевидным и спасают от ошибок при чтении.
Ошибка №3: путать % с процентами.
Символ похож на «проценты», но это остаток. 17 % 5 — это не 17 процентов от 5 и не 5 процентов от 17. Это «что осталось, когда разделили 17 на 5 поровну». Очень полезная операция, особенно в задачах на чётность, время и делёж.
Ошибка №4: случайно делить на ноль (/ 0 или % 0).
Деление на ноль для int — это не «ошибка компиляции», а ошибка выполнения (программа упадёт). Сейчас у нас ещё нет условных операторов, чтобы красиво проверять делитель, поэтому запомните простое правило: делитель должен быть ненулевым, и за этим нужно следить заранее.
Ошибка №5: делать процент как done / total * 100.
При целочисленном делении done / total часто превращается в 0, и дальше всё тоже становится 0. В целочисленной арифметике обычно делают наоборот: (done * 100) / total. Это не «хак», а нормальная техника работы с int, когда вы хотите получить целый процент без дробей.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ