1. 程式人生 > >Go語言-第一個程式和Go tools (fmt, run, build, install)

Go語言-第一個程式和Go tools (fmt, run, build, install)

1. 初步使用

1.1 Go工具

常用的Go工具只有不多的幾個命令:

  • go fmt
  • go run
  • go build
  • go install

Go語言有自己的嚴格的格式,一個好習慣是在提交程式碼前先用內建的格式調整程式調整一下格式:

go fmt
go fmt xxx.go
go fmt xxx

最簡單的情況,就在.go檔案所在目錄下執行上述命令,那麼當前目錄下所有的.go檔案就都處理了。
可以帶引數指定目標檔案或者目標包,只要GOPATH設定的沒問題,能夠找到包,這個命令就可以成功執行,統一格式我還是贊同的,起碼閱讀程式碼會有比較統一的體驗。

本地試執行、除錯,用:

go run xxx.go
go run *.go

注意:以上.go原始檔必須包含帶有main函式的那個.go原始檔,只有其他的.go原始檔是不能執行的。

編譯成本地可執行檔案:

go build xxx.go
go build xxx
go build

然後可執行檔案可以直接執行。如果不指定檔案,那麼當前資料夾內含有main函式的.go原始檔編譯,然後生成一個跟目錄名稱一樣的可執行檔案。注意如果指定xxx.go,那麼也是含有main函式的那個.go檔案。

編譯成成可釋出的可執行檔案:

go install xxx
go install

1.2 例項

1.2.1 工程結構

go專案結構一般如下,注意包名就是src下的目錄名,包名需要全部小寫字母組成

,檔名與包名無要求,同一個包可以有多個go檔案:

.
└── src
    ├── test
    │   ├── 1.go
    │   └── 2.go
    └── tmplib
        ├── lib1.go
        └── lib2.go

以上專案的應用程式名稱是test,本地自定義包tmplib
test包含2個原始檔,1.go和2.go;tmplib包含2個原始檔lib1.go和lib2.go。

包名等於目錄名,所以tmplib裡的原始檔應該屬於tmplib包;但是test目錄下的原始檔不屬於test包,而是main包,因為每個go程式必須有一個main包,程式的入口在其中的main函式。
詳見每個原始檔的第一行 package xxx

原始檔清單:

//1.go
package main

import (
	"fmt"
	"tmplib"
)

func main() {
	fmt.Println("hello1")
	tmplib.Lib1()
	funcIn2()
}

//2.go
package main

import (
	"fmt"
	"tmplib"
)

func funcIn2() {
	fmt.Println("hello2")
	tmplib.Lib2("funcIn2")
}

//lib1.go
package tmplib

import (
    "fmt"
)

func Lib1() {
    fmt.Println("lib1")
}

//lib2.go
package tmplib

import (
    "fmt"
)

func Lib2(caller string) {
    fmt.Println("lib2:", caller)
}

想要構建執行應用程式test,首先要設定好環境變數,切換到src上一級目錄,然後

export GOPATH=${PWD}

1.2.2 go fmt

見2.1節,go fmt可以指定單個.go檔案,也可以指定一批.go檔案,可以不指定,預設當前目錄下的所有.go檔案。
比如在/src/test目錄下:

$go fmt
1.go
2.go

這樣原始檔的格式就已經用工具調整好了。

1.2.3 go run

本地除錯執行go程式,最常用的是go run,見2.1節,通常需要包含main包裡的所有檔案,在/src/test目錄下:

$go run *.go
hello1
lib1
hello2
lib2: funcIn2

如果指定的go檔案不足,會發生找不到symbol的錯誤:

$go run 1.go
# command-line-arguments
./1.go:11:2: undefined: funcIn2

如果指定的go檔案不包含入口main函式,也會報錯:

$go run 2.go
# command-line-arguments
runtime.main_main·f: relocation target main.main not defined
runtime.main_main·f: undefined: "main.main"

如果不是在main包裡,會報錯並提示,需要在main包裡,比如在tmplib目中執行:

$go run *.go
go run: cannot run non-main package

1.2.4 go build

go build會編譯並在當前目錄生成可執行檔案,但是一般我不這麼用,因為如果go run沒啥問題了,那麼go install也不應該有什麼問題。
如果還有問題,通過go build 也不會發現。
而且這樣生成的可執行檔案,目錄位置取決於當前的目錄位置${PWD},也並不方便。不如按照固定的目錄比如 /bin/xxx 規範。
在main包(./src/test)所在目錄下build:

$go build *.go
$ls -l
-rwxrwxr-x 1 docker docker 1864476 Dec 11 14:51 1
-rw-rw-r-- 1 docker docker     108 Dec 11 14:29 1.go
-rw-rw-r-- 1 docker docker     109 Dec 11 14:29 2.go

生成了一個可執行檔案1

在任意目錄build(比如切換到./src同級目錄):

$go build test
$ls -l
drwxrwxr-x 4 docker docker    4096 Dec 11 14:53 src
-rwxrwxr-x 1 docker docker 1864476 Dec 11 14:53 test

生成可執行檔案test

1.2.5 go install

程式編寫和除錯之後,用go install釋出。
go install對於main包和其他包的處理是不同的,main包會在src同級目錄建立./bin目錄,放入可執行檔案;非main包會在src同級建立pkg目錄,放入編譯好的.a檔案。
在任意目錄中執行命令:

go install test

生成可執行檔案及其依賴的包:

.
├── bin
│   └── test
├── pkg
│   └── linux_amd64
│       └── tmplib.a
└── src

把bin目錄部署到生產環境即可,不會再依賴其他的部分了,這真是極好的。