##前言

image

為了要寫一個Web Service但是有可能會發生以下的需求:

  • 不同Server,有不同的設定參數
  • 不同的OS有不同的command set
  • 想要快速的開啟或是關閉debug log

在有以上的需求的時候,一開始都是使用OS偵測或是configuration file來區隔.但是到後其實是希望能透過不同的build config能夠產生不同的binary.

決定研究了一下: go build 有以下兩種方式可以達到部分的效果.

##Go build -ldflags

這可以在go build的時候,先設定一些變數的名稱.通常我自己比較習慣透過OS環境變數來設定,然後程式裡面再去讀取.

在你的主程式裡面,可以先定義一個變數flagString:

package main

import (
	"fmt"
)

var flagString string

func main() {
	fmt.Println("This build with ldflag:", flagString)
}

透過外在go build來設定這個變數 go build -ldflags '-X main.flagString "test"' 這樣你的結果會是

>> This build with ldflag: test

這個方式可以直接設定參數,讓initialize value透過外部設定來跑.

##Go build -tags

透過go build -tags 可以達到加入不同的檔案在compiling time.由於這樣,你能夠放在這個檔案裡面的東西就有很多.可以是:

  • 不同系列的define (達到ifdef的效果)
  • 不同的function implement (達到同一個function 在不同設定下有不同實現)

以下增加一個簡單的範例,來達到不同的build config可以載入不同的define value.

file: debug_config.go

//+build debug

package main

var TestString string = "test debug"
var TestString2 string = " and it will run every module with debug tag."

func GetConfigString() string {
	return "it is debug....."
}

請注意: //+build debug 前後需要一個空行(除非你在第一行)

另外,我們也有一般的設定檔 release_config.go

//+build !debug

package main

var TestString string = "test release"
var TestString2 string = " and it will run every module as no debug tag."

func GetConfigString() string {
	return "it is release....."
}

最後在主要的main裡面,可以直接去參考這兩個define value file: main.go

package main

import (
	"fmt"
)

func main() {
	fmt.Println("This build is ", TestString, TestString2, GetConfigString())
}

在這裡如果你是跑 go build -tags debug 那麼執行結果會是:

>> This build is  test debug  and it will run every module with debug tag. it is debug.....

如果跑的是 go build會預設去讀取!debug,那麼結果會是:

>> This build is  test release  and it will run every module as no debug tag. it is release.....

可以看到他不只可以加入define參數,也可以把不同function 有著不同的implement.

##使用時機討論與心得

使用上差異:

  • ldflags 可以加入一些參數,就跟gcc的ldflags 一樣-
  • tags 很像是 gcc -D 不過由於在檔案裡面要定義 //+build XXXX,感覺有點繁瑣. 不過由於可以以檔案來區隔,你可以加入多個定義值跟function

ldflags 使用時機:

個人認為可能可以拿來改變初始值得設定,或是去改變一些程式內的設定. **比如說: **

  • buffer value: 透過build 來改變buffer size,來做不同的測試與應用.
  • log flag: 決定要不要印log

tags 使用時機:

tags的使用時機相當的多,列出幾個我看到的:

  • debug log/encrypt : 定義debug func 然後再release/debug有不同的implement (印或是不印log),也可以在某些狀況下開啟或是關閉encrypt來測試.
  • 跨平台部分: 不同OS平台需要不同的設定與implement

其他更多的部分,可以看到在逐漸加上去.

##參考鏈結


Evan

Attitude is everything