<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          記一次對 Go 項目 Makefile 的重構(gòu)

          共 3924字,需瀏覽 8分鐘

           ·

          2022-04-11 15:59

          如果你不了解 Makefile 的話,那么推薦看看阮一峰的文章「Make 命令教程[1]」。本文通過一個重構(gòu)的例子帶你寫出味道更好的 Makefile,讓我們開始吧!

          假設(shè)有一個名為 foo 的項目,用 golang 開發(fā),在 docker 上部署,其 Makefile 如下:

          APP?=?$(shell?basename?${CURDIR})
          TAG?=?$(shell?git?log?--pretty=format:"%cd.%h"?--date=short?-1)

          .PHONY:?build
          build:
          ?go?build?-ldflags?"-X?'main.version=${TAG}'"?-o?./tmp/${APP}?.

          .PHONY:?docker-config
          docker-config:?env
          ?TAG=${TAG}?docker-compose?config

          .PHONY:?docker-build
          docker-build:?env
          ?TAG=${TAG}?docker-compose?build

          .PHONY:?docker-push
          docker-push:?env
          ?TAG=${TAG}?docker-compose?push

          .PHONY:?docker-up
          docker-up:?env
          ?TAG=${TAG}?docker-compose?up

          .PHONY:?docker-down
          docker-down:
          ?TAG=${TAG}?docker-compose?down

          看上去很簡潔,唯一需要說明的是在操作 docker-compose 的時候,傳遞了一個名為 TAG 的環(huán)境變量,表示項目當前所屬的標簽,看一下對應(yīng)的 docker-compose.yml 文件:

          version:?"3.0"
          services:
          ??server:
          ????image:?docker.domain.com/foo:${TAG}
          ????build:
          ??????context:?.
          ??????dockerfile:?build/docker/Dockerfile
          ????ports:
          ??????-?"9090:9090"
          ??????-?"6060:6060"

          此時出現(xiàn)了一個有待改進的地方:ports 信息重復,看一下對應(yīng)的 config.toml 文件:

          [rpc]
          port = 9090

          [debug]
          port = 6060

          其中,rpc 端口 9090,debug 端口 6060 最初是在 config.toml 文件里配置的,但是在 docker-compose.yml 文件又重復了一次,假設(shè)要修改的話,就需要修改多個地方。

          此時我們很容易想到的解決方案是把端口信息也通過環(huán)境變量傳遞,就像 TAG 變量那樣,為了獲取端口信息,我還專門寫了一個子命令 config:

          package?cmd

          import?(
          ?"fmt"
          ?"os"

          ?"github.com/spf13/cobra"
          ?"github.com/spf13/viper"
          )

          func?NewConfigCmd()?*cobra.Command?{
          ?configCmd?:=?&cobra.Command{
          ??Use:?"config?",
          ??Run:?config,
          ?}
          ?return?configCmd
          }

          func?config(cmd?*cobra.Command,?args?[]string)?{
          ?if?len(args)?!=?1?{
          ??_?=?cmd.Usage()
          ??os.Exit(1)
          ?}
          ?key?:=?args[0]
          ?value?:=?viper.Get(key)
          ?fmt.Println(value)
          }

          確定了解決方案,讓我們在看一下對應(yīng)的 docker-compose.yml 文件:

          version:?"3.0"
          services:
          ??server:
          ????image:?docker.domain.com/${APP}:${TAG}
          ????build:
          ??????context:?.
          ??????dockerfile:?build/docker/Dockerfile
          ????ports:
          ??????-?"${RPC_PORT}:${RPC_PORT}"
          ??????-?"${DEBUG_PORT}:${DEBUG_PORT}"

          此時沒有硬編碼的配置信息了,讓我們再看看對應(yīng)的 Makefile 文件:

          APP?=?$(shell?basename?${CURDIR})
          TAG?=?$(shell?git?log?--pretty=format:"%cd.%h"?--date=short?-1)
          RPC_PORT???=?$(shell?./tmp/${APP}?config?rpc.port)
          DEBUG_PORT?=?$(shell?./tmp/${APP}?config?debug.port)

          .PHONY:?build
          build:
          ?go?build?-ldflags?"-X?'main.version=${TAG}'"?-o?./tmp/${APP}?.

          .PHONY:?docker-config
          docker-config:?env
          ?APP=${APP}?TAG=${TAG}?RPC_PORT={RPC_PORT}?DEBUG_PORT={DEBUG_PORT}?docker-compose?config

          .PHONY:?docker-build
          docker-build:?env
          ?APP=${APP}?TAG=${TAG}?RPC_PORT={RPC_PORT}?DEBUG_PORT={DEBUG_PORT}?docker-compose?build

          .PHONY:?docker-push
          docker-push:?env
          ?APP=${APP}?TAG=${TAG}?RPC_PORT={RPC_PORT}?DEBUG_PORT={DEBUG_PORT}?docker-compose?push

          .PHONY:?docker-up
          docker-up:?env
          ?APP=${APP}?TAG=${TAG}?RPC_PORT={RPC_PORT}?DEBUG_PORT={DEBUG_PORT}?docker-compose?up

          .PHONY:?docker-down
          docker-down:
          ?APP=${APP}?TAG=${TAG}?RPC_PORT={RPC_PORT}?DEBUG_PORT={DEBUG_PORT}?docker-compose?down

          不得不說,長長的環(huán)境變量實在是太丑了,好在 docker-compose 支持 .env 文件[2],于是我們可以把環(huán)境變量寫入 .env 文件,然后讓 docker-compose 命令從其中取數(shù)據(jù):

          APP?=?$(shell?basename?${CURDIR})
          TAG?=?$(shell?git?log?--pretty=format:"%cd.%h"?--date=short?-1)
          RPC_PORT???=?$(shell?./tmp/${APP}?config?rpc.port)
          DEBUG_PORT?=?$(shell?./tmp/${APP}?config?debug.port)

          .PHONY:?env
          env:
          ?echo?"APP=${APP}"?>?.env;?\
          ??echo?"TAG=${TAG}"?>>?.env;?\
          ??echo?"RPC_PORT=${RPC_PORT}"?>>?.env;?\
          ??echo?"DEBUG_PORT=${DEBUG_PORT}"?>>?.env

          .PHONY:?build
          build:
          ?go?build?-ldflags?"-X?'main.version=${TAG}'"?-o?./tmp/${APP}?.

          .PHONY:?docker-config
          docker-config:?env
          ?docker-compose?config

          .PHONY:?docker-build
          docker-build:?env
          ?docker-compose?build

          .PHONY:?docker-push
          docker-push:?env
          ?docker-compose?push

          .PHONY:?docker-up
          docker-up:?env
          ?docker-compose?up

          .PHONY:?docker-down
          docker-down:
          ?docker-compose?down

          在 Makefile 里,我們定義了一個 env 操作,并把它作為所有 docker-compose 操作的前置執(zhí)行操作,終于不用再寫長長的環(huán)境變量了,不過記得把 .env 寫到 .gitignore 里!

          參考資料

          [1]

          Make 命令教程: https://www.ruanyifeng.com/blog/2015/02/make.html

          [2]

          docker-compose 支持 .env 文件: https://docs.docker.com/compose/environment-variables/



          推薦閱讀


          福利

          我為大家整理了一份從入門到進階的Go學習資料禮包,包含學習建議:入門看什么,進階看什么。關(guān)注公眾號 「polarisxu」,回復?ebook?獲取;還可以回復「進群」,和數(shù)萬 Gopher 交流學習。

          瀏覽 23
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  夜夜躁狠狠躁日日躁麻豆护士 | 亚洲qingse中文 | 亚洲色图欧美色图成人电影 | 国产骚逼精品视频 | 国产鸡吧三级视频黄色 |