Ответ
Да, применял. Этот вопрос можно трактовать двояко, поэтому я отвечу на обе возможные интерпретации: встроенная функция make в Go и утилита make с Makefile для автоматизации задач.
1. Встроенная функция make()
В языке Go функция make используется для инициализации и выделения памяти под слайсы, мапы и каналы.
В отличие от new, которая только выделяет память и возвращает указатель, make инициализирует внутреннюю структуру этих типов данных.
Примеры использования:
// Слайс: создаем с длиной 0, но с ёмкостью 10.
// Это позволяет добавить 10 элементов без новых аллокаций памяти.
s := make([]int, 0, 10)
// Мапа: создаем мапу с начальной ёмкостью 100.
// Это снижает вероятность рехеширования при добавлении элементов.
m := make(map[string]int, 100)
// Канал: создаем буферизованный канал на 5 элементов.
// Отправка в него не заблокируется, пока буфер не заполнится.
ch := make(chan string, 5)
Почему это важно: Предварительное выделение памяти с помощью make — это ключевая оптимизация производительности в Go, позволяющая избежать лишних аллокаций и копирований данных при росте коллекций.
2. Утилита make и Makefile
В Go-проектах, как и во многих других, Makefile — это стандарт де-факто для автоматизации рутинных задач разработчика. Он позволяет стандартизировать команды для всей команды и для CI/CD систем.
Типичные задачи в Makefile для Go-проекта:
make build: Сборка бинарного файла.make test: Запуск тестов.make lint: Проверка кода линтером (например,golangci-lint).make run: Сборка и запуск приложения.make tidy: Выполнениеgo mod tidy.make docker-build: Сборка Docker-образа.
Пример простого Makefile:
# Имя бинарного файла
BINARY_NAME=my-app
.PHONY: build run test lint
build:
@echo "Building..."
@go build -o $(BINARY_NAME) ./cmd/app
run:
@go run ./cmd/app
test:
@echo "Running tests..."
@go test -v ./...
lint:
@echo "Running linter..."
@golangci-lint run
Использование Makefile значительно упрощает жизненный цикл разработки, делая его предсказуемым и унифицированным.
Ответ 18+ 🔞
А, про make? Ну, применял, конечно, применял. Вопрос-то, как выясняется, с подвохом, как говно в проруби — с виду одно, а копнёшь, их там два. Ладно, разберём оба случая, а то потом скажешь, что я тебя, как последнего мудака, обманул.
1. Встроенная функция make() — она же «память, я тебя создал»
В Гоше эта make — не утилита, а прям волшебная палочка для трёх вещей: слайсов, мапов и каналов. В отличие от её сестрицы new, которая просто выделяет память и тыкает в неё пальцем (возвращает указатель), make — она хозяйственная. Она не только место находит, но и полочки расставляет, всё по полочкам, блядь, раскладывает, внутреннюю кухню настраивает.
Смотри, как это выглядит вживую:
// Слайс: делаем с длиной ноль, но ёмкостью на 10 элементов.
// Это чтобы потом, когда будем пихать данные, не орать каждый раз «ой, мама, места нет!» и не копировать всё заново.
s := make([]int, 0, 10)
// Мапа: создаём с запасом на 100 ключей.
// Это чтобы она не начала истерить и не перестраивала свои внутренности при каждом чихе.
m := make(map[string]int, 100)
// Канал: буферизованный, на 5 сообщений.
// Можно накидать в него пять раз, и он не будет тебе мозг выносить блокировкой, пока ты оттуда не заберёшь. Удобно, ёпта.
ch := make(chan string, 5)
А зачем это всё? Да чтобы не тормозить, вот зачем! Это как приехать на склад не на «Оке», а сразу на фуре — сразу всё забрал и поехал, а не двадцать пять рейсов туда-сюда. Оптимизация, блядь, производительности. Меньше аллокаций — меньше работы для сборщика мусора — все счастливы.
2. Утилита make и файл Makefile — она же «автомат для ленивых»
А это уже классика, которая в любом нормальном проекте живёт. Makefile — это такая священная скрижаль, где записано, какую кнопку нажать, чтобы всё само собралось, проверилось и запустилось. Чтобы каждый раз не вспоминать, как там эта длинная команда с кучей флагов выглядит. Особенно когда в команде есть тот один чувак, который всегда всё забывает.
Что обычно в этом Makefile прописано, а?
make build— собрать бинарь. Вжух — и готово.make test— прогнать тесты. Пусть поработают.make lint— прогнать линтер (типаgolangci-lint). Пусть покритикует наш код, сука.make run— собрать и сразу запустить. Для быстрой проверки.make tidy— выполнитьgo mod tidy. Прибраться в зависимостях, а то там иногда как у свиней.make docker-build— собрать докер-образ. Для деплоя.
Вот тебе пример такого файла, простенький:
# Как бинарник назовём
BINARY_NAME=my-app
.PHONY: build run test lint
build:
@echo "Собираю, погоди..."
@go build -o $(BINARY_NAME) ./cmd/app
run:
@go run ./cmd/app
test:
@echo "Гоняю тесты, ща дым пойдёт..."
@go test -v ./...
lint:
@echo "Линтер пошёл всё проверять, ща найдёт косяки..."
@golangci-lint run
Короче, использование Makefile — это признак того, что проект не на коленке сделан. Всё чётко, стандартно, и любой новый человек, пришедший в команду, не будет тратить полдня на то, чтобы понять, как эту хуйню запустить. Просто пишешь make и нужную команду — и жизнь налаживается.