iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
Software Development

Go Clean Architecture API 開發全攻略系列 第 16

Makefile 完全指南:自動化你的 Go 專案開發流程

  • 分享至 

  • xImage
  •  

隨著專案逐漸成形,我們需要執行的指令也越來越多:編譯、執行、測試、程式碼檢查...。
如果每位開發者都手動輸入這些指令,不僅繁瑣,而且容易因參數不同而導致結果不一致。

為了解決這個問題,我們引入一個古老而強大的工具:makeMakefile

Makefile 就如同專案的「命令中心」,它為所有常見任務提供了一個統一、簡潔的入口。開發者不再需要記住複雜的指令,只需執行 make buildmake test 即可。

Makefile 基礎

Makefile 的核心語法非常簡單,由一系列的「規則」組成:

<target>: <prerequisites>
<TAB><command>
  • target:規則的名稱,一個目標,例如 build
  • prerequisites:前置條件,即在執行此規則前,必須先完成的其他目標。
  • command:要執行的 shell 指令。

⚠️ 極其重要command 行的開頭必須是一個 Tab 字元,而不是四個或八個空格。這是 Makefile 最容易出錯的地方。

確認 make 是否安裝

在大多數 Unix-like 系統(如 Linux 和 macOS)中,make 通常已預裝。你可以在終端機中輸入以下指令來確認:

make --version

如果顯示版本資訊,表示 make 已安裝。如果沒有,請根據你的作業系統安裝 make

第一步:建立 Makefile

在你的專案根目錄下,建立一個名為 Makefile 的檔案。我們將逐步填充內容。

第二步:定義變數

為了讓 Makefile 更易於維護,我們會先定義一些變數。

這裡我們會讀取 .env 檔案中的變數,並在 Makefile 中使用。
這樣就不用重複定義相同的變數,確保一致性。

# 讀取 .env 檔案
include .env

# 定義變數
# ===================================================================================
# Variables
# ===================================================================================

pes_parent_dir:=$(shell pwd)/$(lastword $(MAKEFILE_LIST))
pes_parent_dir:=$(shell dirname $(pes_parent_dir))

DockerImageNameMigrate='migrate/migrate:v4.19.0'
MigrationFilePath=$(pes_parent_dir)/deployments/migrations
LocalDatabase='mysql://$(MYSQL_USER):$(MYSQL_PASSWORD)@tcp($(MYSQL_HOST):$(MYSQL_PORT))/$(MYSQL_DATABASE)'

第三步:撰寫核心指令

接下來,我們會撰寫一些常用的指令,例如 run 等等。

# ==============================================================================
# Development
# ==============================================================================

.PHONY: run
run: ## Run the application
  @go run ./cmd/api/main.go

整合 Day 10 的 JWT (JSON Web Token) 的生成與解析 內容,我們會建立以下的 Makefile

# ==============================================================================
# JWT Secret
# ==============================================================================

.PHONY: genJWTSecretToEnv
genJWTSecretToEnv: ## Generate a new JWT secret key and append it to the .env file
	@openssl ecparam -genkey -name secp521r1 -noout | tee -a | awk '{printf "%s""\\n",$$0}' | rev | cut -c3- | rev | awk '{printf "\nTOKEN_SECRET=\"%s\"\n",$$0}' >> .env

整合 Day 12 的 資料庫遷移 (Migration) 內容,我們會建立以下的 Makefile

# ==============================================================================
# Database
# ==============================================================================

.PHONY: databaseMigrateCreate databaseMigrateUp databaseMigrateRollback
databaseMigrateCreate: ## Create a new database migration file. Usage: make databaseMigrateCreate name="migration_name"
ifndef name
	$(error name is undefined. Usage: make databaseMigrateCreate name="migration_name")
endif
	@mkdir -p $(MigrationFilePath)
	@docker run --rm -v $(MigrationFilePath):/migrations --network host $(DockerImageNameMigrate) create -seq -ext sql -dir /migrations $(name)

databaseMigrateUp: ## Migrate database to the latest version
	@docker run --rm -v $(MigrationFilePath):/migrations --network host $(DockerImageNameMigrate) -path=/migrations/ -database $(LocalDatabase) up

databaseMigrateRollback: ## Rollback database by one version
	@docker run --rm -v $(MigrationFilePath):/migrations --network host $(DockerImageNameMigrate) -path=/migrations/ -database $(LocalDatabase) down 1
  • @ 符號:加在指令前,表示在執行時不要將該行指令本身印出來,讓輸出更乾淨。
  • .PHONY:宣告這些目標不是實際的檔案名稱,避免與檔案名稱衝突。

第四步:一個自解釋的 help 指令

一個優秀的 Makefile 應該是自解釋的。我們可以寫一個 help target,它會自動掃描 Makefile 中所有包含 ## 註解的行,並將它們格式化輸出。

# ==============================================================================
# Help
# ==============================================================================

.PHONY:  help

help: ## Show this help message
	@echo "Usage: make <target>"
	@echo ""
	@echo "Targets:"
	@awk 'BEGIN {FS = ":.*?## " } /^[a-zA-Z_-]+:.*?## / {printf "	\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

現在,只要在終端機執行 make help,你就能看到一份格式精美、包含所有指令說明的列表。

$ make help
Usage: make <target>

Targets:
        help                 Show this help message
        run                  Run the application
        databaseMigrateCreate Create a new database migration file. Usage: make databaseMigrateCreate name="migration_name"
        databaseMigrateUp    Migrate database to the latest version
        databaseMigrateRollback Rollback database by one version
        genJWTSecretToEnv    Generate a new JWT secret key and append it to the .env file

第五步:指定 Makefile 的預設目標

Makefile 中,我們可以指定一個預設目標,當使用者執行 make 而不帶任何參數時,將會執行這個目標。通常,我們會將 help 目標設為預設目標,這樣使用者可以快速查看所有可用的指令。

# ==============================================================================
# Default
# ==============================================================================

.DEFAULT_GOAL := help

總結

我們已經成功建立了一個功能完備的 Makefile。它不僅簡化了我們的日常工作,更重要的是,它為團隊提供了一套標準化的工作流程,大大提升了開發體驗和效率。

從現在開始,無論是新加入的成員還是資深的開發者,都可以透過 make 這一個簡單的入口,來執行專案的所有關鍵任務。

本文添加的完整內容可以到 Github 觀看


上一篇
六角架構的魅力之美:開發的便利
下一篇
Dockerize 你的 Go 應用:使用 Docker Compose 打造一致的開發環境
系列文
Go Clean Architecture API 開發全攻略19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言