鍍金池/ 教程/ GO/ 9.8 自定義包的目錄結構、go install 和 go test
4.7 strings 和 strconv 包
13.6 啟動外部命令和程序
?# 11.4 類型判斷:type-switch
12.1 讀取用戶的輸入
10.6 方法
12.2 文件讀寫
13 錯誤處理與測試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個例子:使用 Sorter 接口排序
?# 11.5 測試一個值是否實現(xiàn)了某個接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運行時異常和 panic
10.2 使用工廠方法創(chuàng)建結構體實例
12.8 使用接口的實際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說明
7.2 切片
8.0 Map
3.1 Go 開發(fā)環(huán)境的基本要求
5.6 標簽與 goto
6.10 使用閉包調試
9.5 自定義包和可見性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測試和基準測試
6.8 閉包
4.9 指針
13.1 錯誤處理
10.1 結構體定義
5.1 if-else 結構
6.6 遞歸函數(shù)
9.9 通過 Git 打包和安裝
2.7 Go 運行時(runtime)
10.7 類型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動態(tài)類型
13.3 從 panic 中恢復(Recover)
10.3 使用自定義包中的結構體
11.14 結構體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關鍵字與標識符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結構和要素
8.6 將 map 的鍵值對調
6.11 計算函數(shù)執(zhí)行時間
5.0 控制結構
10.5 匿名字段和內嵌結構體
4.6 字符串
3.0 編輯器、集成開發(fā)環(huán)境與其它工具
13.8 測試的具體例子
7.6 字符串、數(shù)組和切片的應用
8.4 map 類型的切片
3.9 與其它語言進行交互
7.3 For-range 結構
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結構、go install 和 go test
6.3 傳遞變長參數(shù)
13.9 用(測試數(shù)據(jù))表驅動測試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫
3.3 調試器
4.5 基本類型和運算符
?# 11.8 第二個例子:讀和寫
12.5 用 buffer 讀取文件
總結:Go 中的面向對象
11.10 反射包
12.7 用 defer 關閉文件
9.4 精密計算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標簽的結構體
7.5 切片的復制與追加
?# 11.3 類型斷言:如何檢測和轉換接口變量的類型
5.4 for 結構
4.8 時間和日期
2.3 在 Linux 上安裝 Go
12 讀寫數(shù)據(jù)
6.12 通過內存緩存來提升性能
9.1 標準庫概述
12.6 用切片讀寫文件
10 結構(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯誤的模式
3.2 編輯器和集成開發(fā)環(huán)境
12.12 Go 中的密碼學
5.2 測試多返回值函數(shù)的錯誤
6.7 將函數(shù)作為參數(shù)
8.2 測試鍵值對是否存在及刪除元素
3.4 構建并運行 Go 程序
2.1 平臺與架構
5.3 switch 結構

9.8 自定義包的目錄結構、go install 和 go test

為了示范,我們創(chuàng)建了一個名為 uc 的簡單包,它含有一個 UpperCase 函數(shù)將字符串的所有字母轉換為大寫。當然這并不值得創(chuàng)建一個自己包,同樣的功能已被包含在 strings 包里,但是同樣的技術也可以應用在更復雜的包中。

9.8.1 自定義包的目錄結構

下面的結構給了你一個好的示范(uc 代表通用包名, 名字為粗體的代表目錄,斜體代表可執(zhí)行文件):

/home/user/goprograms
    ucmain.go   (uc包主程序)
    Makefile (ucmain的makefile)
    ucmain
    src/uc   (包含uc包的go源碼)
        uc.go
        uc_test.go
        Makefile (包的makefile)
        uc.a
        _obj
            uc.a
        _test
            uc.a
    bin      (包含最終的執(zhí)行文件)
            ucmain
    pkg/linux_amd64
            uc.a    (包的目標文件)

將你的項目放在 goprograms 目錄下(你可以創(chuàng)建一個環(huán)境變量 GOPATH,詳見第 2.2/3 章節(jié):在 .profile 和 .bashrc 文件中添加 export GOPATH=/home/user/goprograms),而你的項目將作為 src 的子目錄。uc 包中的功能在 uc.go 中實現(xiàn)。

示例 9.6 uc.go

package uc
import "strings"

func UpperCase(str string) string {
    return strings.ToUpper(str)
}

包通常附帶一個或多個測試文件,在這我們創(chuàng)建了一個 uc_test.go 文件,如第 9.8 節(jié)所述。

示例 9.7 test.go

package uc
import "testing"

type ucTest struct {
    in, out string
}

var ucTests = []ucTest {
    ucTest{"abc", "ABC"},
    ucTest{"cvo-az", "CVO-AZ"},
    ucTest{"Antwerp", "ANTWERP"},
}

func TestUC(t *testing.T) {
    for _, ut := range ucTests {
        uc := UpperCase(ut.in)
        if uc != ut.out {
            t.Errorf("UpperCase(%s) = %s, must be %s", ut.in, uc,
            ut.out)
        }
    }
}

通過指令編譯并安裝包到本地:go install uc, 這會將 uc.a 復制到 pkg/linux_amd64 下面。

另外,使用 make ,通過以下內容創(chuàng)建一個包的 Makefile 在 src/uc 目錄下:

include $(GOROOT)/src/Make.inc

TARG=uc
GOFILES=\
        uc.go\

include $(GOROOT)/src/Make.pkg

在該目錄下的命令行調用: gomake

這將創(chuàng)建一個 _obj 目錄并將包編譯生成的存檔 uc.a 放在該目錄下。

這個包可以通過 go test 測試。

創(chuàng)建一個 uc.a 的測試文件在目錄下,輸出為 PASS 時測試通過。

在第 13.8 節(jié)我們將給出另外一個測試例子并進行深入研究。

備注:有可能你當前的用戶不具有足夠的資格使用 go install(沒有權限)。這種情況下,選擇 root 用戶 su。確保 Go 環(huán)境變量和 Go 源碼路徑也設置給 su,同樣也適用你的普通用戶(詳見第 2.3 節(jié))。

接下來我們創(chuàng)建主程序 ucmain.go:

示例 9.8 ucmain.go

package main
import (
    "./uc/uc"
    "fmt"
)

func main() {
    str1 := "USING package uc!"
    fmt.Println(uc.UpperCase(str1))
}

然后在這個目錄下輸入 go install。

另外復制 uc.a 到 /home/user/goprograms 目錄并創(chuàng)建一個 Makefile 并寫入文本:

include $(GOROOT)/src/Make.inc
TARG=ucmain
GOFILES=\
    ucmain.go\

include $(GOROOT)/src/Make.cmd

執(zhí)行 gomake 編譯 ucmain.go 生成可執(zhí)行文件ucmain

運行 ./ucmain 顯示: USING PACKAGE UC!。

9.8.2 本地安裝包

本地包在用戶目錄下,使用給出的目錄結構,以下命令用來從源碼安裝本地包:

go install /home/user/goprograms/src/uc # 編譯安裝uc
cd /home/user/goprograms/uc
go install ./uc     # 編譯安裝uc(和之前的指令一樣)
cd ..
go install .    # 編譯安裝ucmain

安裝到 $GOPATH 下:

如果我們想安裝的包在系統(tǒng)上的其他 Go 程序中被使用,它一定要安裝到 $GOPATH 下。 這樣做,在 .profile 和 .bashrc 中設置 export GOPATH=/home/user/goprograms。

然后執(zhí)行 go install uc 將會復制包存檔到 $GOPATH/pkg/LINUX_AMD64/uc。

現(xiàn)在,uc 包可以通過 import "uc" 在任何 Go 程序中被引用。

9.8.3 依賴系統(tǒng)的代碼

在不同的操作系統(tǒng)上運行的程序以不同的代碼實現(xiàn)是非常少見的:絕大多數(shù)情況下語言和標準庫解決了大部分的可移植性問題。

你有一個很好的理由去寫平臺特定的代碼,例如匯編語言。這種情況下,按照下面的約定是合理的:

prog1.go
prog1_linux.go
prog1_darwin.go
prog1_windows.go

prog1.go 定義了不同操作系統(tǒng)通用的接口,并將系統(tǒng)特定的代碼寫到 prog1os.go 中。 對于 Go 工具你可以指定 `prog1$GOOS.goprog1$GOARCH.go 或在平臺 Makefile 中:prog1$(GOOS).go` 或 prog1_$(GOARCH).go\。

鏈接