---
# System prepended metadata

title: 'GoLang 05. 開發工具:'
tags: [GoLang]

---


###### tags: `GoLang`

# GoLang 05. 開發工具:

### Go 專案資料夾佈局:
https://github.com/golang-standards/project-layout

```bash
directory
├── /api #OpenAPI/Swagger 規範，JSON 模式（schema）文件...
├── /build #專案執行檔放置處,目錄內包含機器執行所需要的檔案
├── /cmd #如果專案編寫包含多個執行檔,將各自package main放置各目錄內
│   ├── authtest
│   │   └── main.go
│   ├── backend
│   │   └── main.go
│   └── client
│       └── main.go
├── /configs #設定檔集,如預設設定.不同OS環境設定...
├── /docs #專案文檔放置處
├── /deploy #容器化專案所需檔案放置處(選用)
│   ├── add_migration.sh
│   └── docker-compose.yml
├── /migrations/ #db特定操作（非標準方式）
│   ├── 20190721131113_extensions.down.sql
│   ├── migrations.go
│   └── README.md
│#vendor/internal/pkg 三者目錄可在go專案內子資料夾中出現
├── /vendor #Go專案外部依賴包或第三方包,可由go mod vendor產生
├── /internal #main之私用package
├── /pkg #main之公用package
│   ├── api/
│   │   ├── exitus.gen.go
│   │   └── gen.go
│   ├── auth/
│   │   ├── scopes.go
│   │   └── user.go
│   ├── conf/
│   │   ├── conf.go
│   │   └── conf_test.go
│   ├── db/
│   │   ├── db.go
│   │   ├── dbtesting.go
│   │   └── sqlhooks.go
│   ├── server/
│   │   └── server.go
│   └── store/
│       ├── comments.go
│       ├── comments_test.go
│       └── store.go
├── /scripts #build相關腳本放置處（選用）
├── /website #靜態資源檔案放置處
├── /assets #其他資源檔案放置處,如logos
├── Dockerfile
├── go.mod
├── go.sum
└── README.md
```

### Go 環境設置:

#### Windwos
```ini
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.go]
@="Go.Code.Template"

[HKEY_CLASSES_ROOT\.go\ShellNew]
"FileName"="Template.go"

[HKEY_CLASSES_ROOT\Go.Code.Template]
@="Go Code Template"

```

### Go 單元測試(Unit Test)介紹:
>
> #### go test 工具說明 :
> Golang 官方工具包提供單元測試功能透過，``go test`` 進行單元測試:
> 
> > 1. 單元測試檔名必須以 ``*_test.go`` 結尾命名，和被測試檔案必須在同一個包(package)中，此檔名內容僅會在 ``go test`` 下執行。
> > 2. 單元測試函式必須是 ``Test`` 或是 ``Benchmark`` 作為函式開頭名稱後面第一字必需大寫 ex: **TestExample** 、**BenchmarkExample** 。
> > 3. 單元測試函式輸入參數型別必須 ``*testing.T`` 、 ``*testing.B``
> >
> 
> ``go test`` 工具附加命令參數設定值:
>    
> > ``-c`` : 不運行測試，將go test編譯成為可執行檔案(二進位文件)。
> > 
> > ``-i``  : 不運行測試，安裝測試包依賴的package。
> > 
> > ``-v``  : 測試過程顯示列表所有函式(通過/不通過)。
> > 
> > ``-short``  : 縮短運行時間較長的測試項目。
> > 
> > ``-args "-TT"``  : 測試時置入命令參數 **-TT** (詳細參考flag.Args)
> > 
> > ``-timeout 1h``  : 如果測試用例運行時間超過 **1小時**，則拋出panic。
> > 
> > ``-run=funcname`` : 僅測試函式包含名稱 **funcname** 。(預設值 ``.``，表示全部測試)
> > 
> > ``-bench=funcname`` : 僅效能測試函式包含名稱 **funcname** 。(預設值 ``.``，表示全測試)
> > 
> > ``-benchmem``  : 設置效能測試的時顯示記憶體使用資訊。
> > 
> > ``-benchtime 10s``  : 設置效能測試運行的時間 **10秒** (預設值**1秒**)
> > 
> > ``-parallel 4``  : 設定效能測試並行最大CPU核心數為 **4** (預設值GOMAXPROCS)
> > 
> > ``-cpu 1,2,3,4``  : 效能測試會依序由 **1~4** CPU核心數測試。(預設值為GOMAXPROCS)
> > 
> > ``-cpuprofile cpu.out``  : 將測試過程CPU使用量紀錄儲存至 **cpu.out**
> > 
> > ``-memprofile mem.out``  : 將測試過程記憶體使用量紀錄儲存至 **mem.out**
> > 
> > ``-blockprofile block.out``  : 將測試過程中goroutine阻塞分析紀錄儲存至 **block.out**
> > 
> > ``-blockprofilerate 2`` : 設置goroutine阻塞時候紀錄間隔時間為 **2納秒** (預設值**1納秒**)
> > 
> #### 單元測試關鍵點 :
> 
> 測試資料構造時要考慮這樣幾個方面：
> >**正常輸入**: 驗證函式的正常邏輯是否通過
> >**邊界輸入**: 驗證在極端情況下的輸入，函式是否在有相應的容錯處理
> >**非法輸入**: 對於一些非正常輸入，看函式是否引起函式的奔潰和資料洩露等問題
> >**白盒覆蓋**: 覆蓋到函式的所有程式碼，語句覆蓋、條件覆蓋、分支覆蓋、分支/條件覆蓋、條件組合覆蓋。
>
> 編寫原則與成本，效率權衡 :
> 
> > 1. 優先編寫核心元件和邏輯模組的測試用例。
> > 2. 邏輯類似的元件如果存在多個，優先編寫其中一種邏輯元件的測試用例。
> > 3. 發現Bug時一定先編寫測試用例進行Debug(保持更新測試用例)。
> > 4. 測試使用者應該獨立一個檔案對應一個，不同的測試用例之間不要互相依賴。
> > 
> 原始資料出處 : https://www.itread01.com/hkpqhkxx.html

### Go 單元測試範例 - 函式輸入與期望結果對比:
> ```go=
> //Basic_Unit_Testing1\Basic_Unit_Testing_Example1.go
> package Basic_Unit_Testing_Example1
> func fc_AddInt(vi_inputA, vi_inputB int) int {
> 	return vi_inputA + vi_inputB
> }
> ```
> 
> ```go=
> //Basic_Unit_Testing1\Basic_Unit_Testing_Example1_test.go
> package Basic_Unit_Testing_Example1
> 
> import (
> 	"fmt"
> 	"testing"
> )
> 
> func Test_fc_AddInt(testT *testing.T) {
> 
> 	var vs_theTestPanic string
> 	defer func() {
> 		if err_recover := recover(); err_recover != nil {
> 			testT.Fatalf("測試過程發生panic，本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover)
> 		}
> 	}()
> 
> 	var stsl_Testers = []struct {
> 		add1 int
> 		add2 int
> 		want int
> 	}{
> 		{1, 1, 2},
> 		{2, 0, 2},
> 		{0, 2, 2},
> 		{9223372036854775807, -1, 9223372036854775806},
> 		{9223372036854775806, 1, 9223372036854775807},
> 		{9223372036854775807, 9223372036854775807, 0}, //overflows
> 		{-1, -1, -2},
> 	}
> 
> 	for vi_TestIndex, st_TestObject := range stsl_Testers {
> 		vs_theTestPanic = fmt.Sprintf("stsl_Testers[%v] %v", vi_TestIndex, st_TestObject)
> 		theTestResult := fc_AddInt(st_TestObject.add1, st_TestObject.add2)
> 		if theTestResult == st_TestObject.want {
> 			testT.Logf("項目測試正確 %v+%v=%v(%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult)
> 		} else {
> 			testT.Errorf("項目測試[錯誤] %v+%v=%v(錯誤的結果:%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult)
> 		}
> 	}
> }
> ```
> ```sass=
> d:\單元測試\Basic_Unit_Testing1>go test -v
> === RUN   Test_fc_AddInt
> --- FAIL: Test_fc_AddInt (0.00s)
>     Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 1+1=2(2)
>     Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 2+0=2(2)
>     Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 0+2=2(2)
>     Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 9223372036854775807+-1=9223372036854775806(9223372036854775806)
>     Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 9223372036854775806+1=9223372036854775807(9223372036854775807)
>     Basic_Unit_Testing_Example1_test.go:37: 項目測試[錯誤] 9223372036854775807+9223372036854775807=0(錯誤的結果:-2)
>     Basic_Unit_Testing_Example1_test.go:35: 項目測試正確 -1+-1=-2(-2)
> FAIL
> exit status 1
> FAIL    Lesson4/單元測試/Basic_Unit_Testing1    0.026s
> ```

### Go 單元測試範例 - 函式輸入與錯誤回報:
> ```go=
> //Basic_Unit_Testing2\Basic_Unit_Testing_Example2.go
> package Basic_Unit_Testing_Example2
> import (
> 	"errors"
> )
> 
> func fc_DivInt(vi_inputA, vi_inputB int) int {
> 	return vi_inputA / vi_inputB
> }
> 
> func fc_DivIntMod(vi_inputA, vi_inputB int) (int, error) {
> 	if vi_inputB == 0 {
> 		return 0, errors.New("除數不得為0")
> 	}
> 	return vi_inputA / vi_inputB, nil
> }
> 
> ```
> 
> ```go=
> //Basic_Unit_Testing2\Basic_Unit_Testing_Example2_test.go
> package Basic_Unit_Testing_Example2
> 
> import (
> 	"errors"
> 	"fmt"
> 	"testing"
> )
> 
> func Test_fc_DivIntMod(testT *testing.T) {
> 
> 	var vs_theTestPanic string
> 	defer func() {
> 		if err_recover := recover(); err_recover != nil {
> 			testT.Fatalf("測試過程發生panic，本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover)
> 		}
> 	}()
> 
> 	type ty_TestIndex struct {
> 		dividend int
> 		divisor  int
> 		want1    int
> 		want2    error
> 	}
> 
> 	var stsl_Testers = []ty_TestIndex{
> 		{1, 1, 1, nil},
> 		{10, 2, 5, nil},
> 		{0, 2, 0, nil},
> 		{9223372036854775807, 1, 9223372036854775807, nil},
> 		{9223372036854775806, 3, 3074457345618258602, nil},
> 		{9223372036854775807, 4611686018427387903, 2, nil},
> 		{9223372036854775807, 0, 0, errors.New("除數不得為0")}, //除零預期錯誤
> 		{-1, 1, -1, nil},
> 	}
> 
> 	for vi_TestIndex, st_TestObject := range stsl_Testers {
> 		vs_theTestPanic = fmt.Sprintf("stsl_Testers[%v] %v", vi_TestIndex, st_TestObject)
> 		theTestResult1, theTestResult2 := fc_DivIntMod(st_TestObject.dividend, st_TestObject.divisor)
> 
> 		if theTestResult2 == nil {
> 			theTestResult2 = errors.New("nil")
> 		}
> 		if st_TestObject.want2 == nil {
> 			st_TestObject.want2 = errors.New("nil")
> 		}
> 
> 		if theTestResult1 == st_TestObject.want1 && theTestResult2.Error() == st_TestObject.want2.Error() {
> 			testT.Logf("項目測試正確 %v/%v=%v,%v(%v,%v)", st_TestObject.dividend, st_TestObject.divisor, st_TestObject.want1, st_TestObject.want2, theTestResult1, theTestResult2)
> 		} else {
> 			testT.Errorf("項目測試[錯誤] %v/%v=%v,%v(錯誤的結果:%v,%v)", st_TestObject.dividend, st_TestObject.divisor, st_TestObject.want1, st_TestObject.want2, theTestResult1, theTestResult2)
> 		}
> 	}
> 
> }
> ```
> 
> ```sass=
> d:\單元測試\Basic_Unit_Testing2>go test -v
> === RUN   Test_fc_DivIntMod
> --- PASS: Test_fc_DivIntMod (0.00s)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 1/1=1,nil(1,nil)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 10/2=5,nil(5,nil)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 0/2=0,nil(0,nil)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775807/1=9223372036854775807,nil(9223372036854775807,nil)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775806/3=3074457345618258602,nil(3074457345618258602,nil)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775807/4611686018427387903=2,nil(2,nil)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 9223372036854775807/0=0,除數不得為0(0,除數不得為0)
>     Basic_Unit_Testing_Example2_test.go:48: 項目測試正確 -1/1=-1,nil(-1,nil)
> PASS
> ok      Lesson4/單元測試/Basic_Unit_Testing2    0.025s
> ```

### Go 單元測試範例 - 雙函式結果對比(隨機輸入):
> ```go=
> //Basic_Unit_Testing3\Basic_Unit_Testing_Example3.go
> package Basic_Unit_Testing_Example3
> 
> func fc_SumA(via_Input ...int) int {
> 	var vi_sum int
> 	for i := 0; i < len(via_Input); i++ {
> 		vi_sum += via_Input[i]
> 	}
> 	return vi_sum
> }
> 
> func fc_SumB(vi_sum int, via_Input ...int) int {
> 	for i := 0; i < len(via_Input); i++ {
> 		vi_sum += via_Input[i]
> 	}
> 	return vi_sum
> }
> ```
> 
> ```go=
> //Basic_Unit_Testing3\Basic_Unit_Testing_Example_test3.go
> package Basic_Unit_Testing_Example3
> 
> import (
> 	"math/rand"
> 	"testing"
> 	"time"
> )
> 
> 
> func Test_fc_SumAnB(testT *testing.T) {
> 
> 	var vs_theTestPanic string
> 	defer func() {
> 		if err_recover := recover(); err_recover != nil {
> 			testT.Fatalf("測試過程發生panic，本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover)
> 		}
> 	}()
> 
> 	theRandSeed := time.Now().UTC().UnixNano()
> 	rand.Seed(theRandSeed)
> 	var vi_RandInt int
> 	var vi_Output_fc_SumA int
> 	var vi_Output_fc_SumB int
> 
> 	for index := 0; index < 10; index++ {
> 		vi_RandInt = rand.Int()
> 		vi_Output_fc_SumA = fc_SumA(vi_RandInt)
> 		vi_Output_fc_SumB = fc_SumB(vi_RandInt)
> 		if fc_SumA(vi_RandInt) == fc_SumB(vi_RandInt) {
> 			testT.Logf("項目測試正確 %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt)
> 		} else {
> 			testT.Errorf("項目測試[錯誤] %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt)
> 		}
> 	}
> }
> 
> ```
> ```sass=
> d:\單元測試\Basic_Unit_Testing3>go test -v
> === RUN   Test_fc_SumAnB
> --- PASS: Test_fc_SumAnB (0.00s)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 128637770004810965=128637770004810965 (亂數種子:1570086382169605200,亂數int:128637770004810965)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 2710904496263871649=2710904496263871649 (亂數種子:1570086382169605200,亂數int:2710904496263871649)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7459572758933604767=7459572758933604767 (亂數種子:1570086382169605200,亂數int:7459572758933604767)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7058483080362729371=7058483080362729371 (亂數種子:1570086382169605200,亂數int:7058483080362729371)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7049057841437937710=7049057841437937710 (亂數種子:1570086382169605200,亂數int:7049057841437937710)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 8952472848806917481=8952472848806917481 (亂數種子:1570086382169605200,亂數int:8952472848806917481)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 7580769296778865075=7580769296778865075 (亂數種子:1570086382169605200,亂數int:7580769296778865075)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 5973232751947046394=5973232751947046394 (亂數種子:1570086382169605200,亂數int:5973232751947046394)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 2797291425107336826=2797291425107336826 (亂數種子:1570086382169605200,亂數int:2797291425107336826)
>     Basic_Unit_Testing_Example3_test.go:30: 項目測試正確 1338551253019334488=1338551253019334488 (亂數種子:1570086382169605200,亂數int:1338551253019334488)
> PASS
> ok      Lesson4/單元測試/Basic_Unit_Testing3    0.028s
> ```


### Go 效能測試範例 - (go test -bench=):
> 
> ```go=
> //d:\效能測試\Basic_Benchmark.go
> package Basic_Benchmark
> import "fmt"
> func fc_SprintInt(vi_input int) string {
> 	return fmt.Sprintf("%d", vi_input)
> }
> 
> ```
> 
> ```go=
> //d:\效能測試\Basic_Benchmark_test.go
> package Basic_Benchmark
> import "testing"
> func Benchmark_fc_SprintInt(benchB *testing.B) {
> 	benchB.ResetTimer()
> 	for i := 0; i < benchB.N; i++ {
> 		fc_SprintInt(99999)
> 	}
> }
> 
> ```
> go test -bench=. -cpu 1,2,3,4 -cpuprofile cpu.out -memprofile mem.out -blockprofile block.out
>
> ```sass=
> d:\效能測試>go test -bench=. -cpu 1,2,3,4 -cpuprofile cpu.out -memprofile mem.out -blockprofile block.out
> go test: missing argument for flag blockprofile
> run "go help test" or "go help testflag" for more information
> 
> d:\效能測試>go test -bench=. -cpu 1,2,3,4 -cpuprofile cpu.out -memprofile mem.out -blockprofile block.out
> goos: windows
> goarch: amd64
> pkg: Lesson4/效能測試
> Benchmark_fc_SprintInt          10000000               194 ns/op
> Benchmark_fc_SprintInt-2        10000000               163 ns/op
> Benchmark_fc_SprintInt-3        10000000               159 ns/op
> Benchmark_fc_SprintInt-4        10000000               139 ns/op
> PASS
> ok      Lesson4/效能測試        7.583s
> 
> d:\效能測試>go tool pprof -text -nodecount=10 cpu.out
> Type: cpu
> Time: Sep 3, 2019 at 5:35pm (CST)
> Duration: 7.45s, Total samples = 7300ms (97.99%)
> Showing nodes accounting for 4490ms, 61.51% of 7300ms total
> Dropped 46 nodes (cum <= 36.50ms)
> Showing top 10 nodes out of 52
>       flat  flat%   sum%        cum   cum%
>      830ms 11.37% 11.37%     1650ms 22.60%  runtime.mallocgc
>      800ms 10.96% 22.33%     1470ms 20.14%  fmt.(*fmt).fmtInteger
>      580ms  7.95% 30.27%     2600ms 35.62%  fmt.(*pp).doPrintf
>      380ms  5.21% 35.48%     2020ms 27.67%  fmt.(*pp).printArg
>      350ms  4.79% 40.27%      640ms  8.77%  sync.(*Pool).Get
>      350ms  4.79% 45.07%      630ms  8.63%  sync.(*Pool).Put
>      330ms  4.52% 49.59%     1430ms 19.59%  runtime.slicebytetostring
>      290ms  3.97% 53.56%      670ms  9.18%  fmt.(*fmt).pad
>      290ms  3.97% 57.53%     6140ms 84.11%  fmt.Sprintf
>      290ms  3.97% 61.51%      290ms  3.97%  runtime.memmove
> 
> d:\效能測試>go tool pprof -text -nodecount=10 mem.out
> Type: alloc_space
> Time: Sep 3, 2019 at 5:35pm (CST)
> Showing nodes accounting for 637.51MB, 99.50% of 640.68MB total
> Dropped 17 nodes (cum <= 3.20MB)
>       flat  flat%   sum%        cum   cum%
>   371.51MB 57.99% 57.99%   372.01MB 58.06%  fmt.Sprintf
>      266MB 41.52% 99.50%   638.01MB 99.58%  Lesson4/%e6%95%88%e8%83%bd%e6%b8%ac%e8%a9%a6.fc_SprintInt
>          0     0% 99.50%   638.01MB 99.58%  Lesson4/%e6%95%88%e8%83%bd%e6%b8%ac%e8%a9%a6.Benchmark_fc_SprintInt
>          0     0% 99.50%   638.01MB 99.58%  testing.(*B).launch
>          0     0% 99.50%   638.01MB 99.58%  testing.(*B).runN
> 
> d:\效能測試>go tool pprof -text -nodecount=10 block.out
> Type: delay
> Time: Sep 3, 2019 at 5:35pm (CST)
> Showing nodes accounting for 7466.18ms, 100% of 7466.19ms total
> Dropped 5 nodes (cum <= 37.33ms)
> Showing top 10 nodes out of 17
>       flat  flat%   sum%        cum   cum%
>  7466.18ms   100%   100%  7466.18ms   100%  runtime.chanrecv1
>          0     0%   100%  7466.19ms   100%  main.main
>          0     0%   100%  7466.19ms   100%  runtime.main
>          0     0%   100%   153.33ms  2.05%  runtime/pprof.StopCPUProfile
>          0     0%   100%   153.33ms  2.05%  sync.(*Once).Do
>          0     0%   100%  7312.85ms 97.95%  testing.(*B).Run
>          0     0%   100%  7311.72ms 97.93%  testing.(*B).doBench
>          0     0%   100%  7312.62ms 97.94%  testing.(*B).run
>          0     0%   100%  7312.85ms 97.95%  testing.(*B).runN
>          0     0%   100%  7466.19ms   100%  testing.(*M).Run
> 
> ```
### Go 涵蓋率測試範例 - (go tool cover):
> ```go=
> // 涵蓋率測試/Cover_Testing_Example.go
> package Cover_Testing_Example
> func fc_AddInt(vi_inputA, vi_inputB int) int {
> 	return vi_inputA + vi_inputB
> }
> 
> func fc_SubInt(vi_inputA, vi_inputB int) int {
> 	return vi_inputA - vi_inputB
> }
> 
> func fc_SumA(via_Input ...int) int {
> 	var vi_sum int
> 	for i := 0; i < len(via_Input); i++ {
> 		vi_sum += via_Input[i]
> 	}
> 	return vi_sum
> }
> 
> func fc_SumB(vi_sum int, via_Input ...int) int {
> 	for i := 0; i < len(via_Input); i++ {
> 		vi_sum += via_Input[i]
> 	}
> 	return vi_sum
> }
> ```
> 
> ```go=
> // 涵蓋率測試/Cover_Testing_Example_test.go
> package Cover_Testing_Example
> import (
> 	"fmt"
> 	"math/rand"
> 	"testing"
> 	"time"
> )
> 
> func Test_fc_AddInt(testT *testing.T) {
> 
> 	var vs_theTestPanic string
> 	defer func() {
> 		if err_recover := recover(); err_recover != nil {
> 			testT.Fatalf("測試過程發生panic，本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover)
> 		}
> 	}()
> 
> 	var stsl_Testers = []struct {
> 		add1 int
> 		add2 int
> 		want int
> 	}{
> 		{1, 1, 2},
> 		{2, 0, 2},
> 		{0, 2, 2},
> 		{9223372036854775807, -1, 9223372036854775806},
> 		{9223372036854775806, 1, 9223372036854775807},
> 		{9223372036854775807, 9223372036854775807, 0}, //overflows
> 		{-1, -1, -2},
> 	}
> 
> 	for vi_TestIndex, st_TestObject := range stsl_Testers {
> 		vs_theTestPanic = fmt.Sprintf("stsl_Testers[%v] %v", vi_TestIndex, st_TestObject)
> 		theTestResult := fc_AddInt(st_TestObject.add1, st_TestObject.add2)
> 		if theTestResult == st_TestObject.want {
> 			testT.Logf("項目測試正確 %v+%v=%v(%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult)
> 		} else {
> 			testT.Errorf("項目測試[錯誤] %v+%v=%v(錯誤的結果:%v)", st_TestObject.add1, st_TestObject.add2, st_TestObject.want, theTestResult)
> 		}
> 	}
> }
> 
> func Test_fc_SumAnB(testT *testing.T) {
> 
> 	var vs_theTestPanic string
> 	defer func() {
> 		if err_recover := recover(); err_recover != nil {
> 			testT.Fatalf("測試過程發生panic，本測項中止 -「%v」(%v)", vs_theTestPanic, err_recover)
> 		}
> 	}()
> 
> 	theRandSeed := time.Now().UTC().UnixNano()
> 	rand.Seed(theRandSeed)
> 	var vi_RandInt int
> 	var vi_Output_fc_SumA int
> 	var vi_Output_fc_SumB int
> 
> 	for index := 0; index < 10; index++ {
> 		vi_RandInt = rand.Int()
> 		vi_Output_fc_SumA = fc_SumA(vi_RandInt)
> 		vi_Output_fc_SumB = fc_SumB(vi_RandInt)
> 		if fc_SumA(vi_RandInt) == fc_SumB(vi_RandInt) {
> 			testT.Logf("項目測試正確 %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt)
> 		} else {
> 			testT.Errorf("項目測試[錯誤] %v=%v (亂數種子:%d,亂數int:%v)", vi_Output_fc_SumA, vi_Output_fc_SumB, theRandSeed, vi_RandInt)
> 		}
> 	}
> }
> 
> ```
> 
> ```sass=
> PS D:\涵蓋率測試> go test -v -cover -coverprofile cover.out
> === RUN   Test_fc_AddInt
> --- FAIL: Test_fc_AddInt (0.00s)
>     Cover_Testing_Example_test.go:37: 項目測試正確 1+1=2(2)
>     Cover_Testing_Example_test.go:37: 項目測試正確 2+0=2(2)
>     Cover_Testing_Example_test.go:37: 項目測試正確 0+2=2(2)
>     Cover_Testing_Example_test.go:37: 項目測試正確 9223372036854775807+-1=9223372036854775806(9223372036854775806)
>     Cover_Testing_Example_test.go:37: 項目測試正確 9223372036854775806+1=9223372036854775807(9223372036854775807)
>     Cover_Testing_Example_test.go:39: 項目測試[錯誤] 9223372036854775807+9223372036854775807=0(錯誤的結果:-2)
>     Cover_Testing_Example_test.go:37: 項目測試正確 -1+-1=-2(-2)
> === RUN   Test_fc_SumAnB
> --- PASS: Test_fc_SumAnB (0.00s)
>     Cover_Testing_Example_test.go:64: 項目測試正確 1054791156209780183=1054791156209780183 (亂數種子:1570164062516555300,亂數int:1054791156209780183)
>     Cover_Testing_Example_test.go:64: 項目測試正確 1572036677946546427=1572036677946546427 (亂數種子:1570164062516555300,亂數int:1572036677946546427)
>     Cover_Testing_Example_test.go:64: 項目測試正確 4043804078525964286=4043804078525964286 (亂數種子:1570164062516555300,亂數int:4043804078525964286)
>     Cover_Testing_Example_test.go:64: 項目測試正確 4490900911252265608=4490900911252265608 (亂數種子:1570164062516555300,亂數int:4490900911252265608)
>     Cover_Testing_Example_test.go:64: 項目測試正確 9189757511242968573=9189757511242968573 (亂數種子:1570164062516555300,亂數int:9189757511242968573)
>     Cover_Testing_Example_test.go:64: 項目測試正確 8466299651324370872=8466299651324370872 (亂數種子:1570164062516555300,亂數int:8466299651324370872)
>     Cover_Testing_Example_test.go:64: 項目測試正確 600841189896519269=600841189896519269 (亂數種子:1570164062516555300,亂數int:600841189896519269)
>     Cover_Testing_Example_test.go:64: 項目測試正確 8783876916636026197=8783876916636026197 (亂數種子:1570164062516555300,亂數int:8783876916636026197)
>     Cover_Testing_Example_test.go:64: 項目測試正確 4035231185535482081=4035231185535482081 (亂數種子:1570164062516555300,亂數int:4035231185535482081)
>     Cover_Testing_Example_test.go:64: 項目測試正確 4089254982128445097=4089254982128445097 (亂數種子:1570164062516555300,亂數int:4089254982128445097)
> FAIL
> coverage: 77.8% of statements
> exit status 1
> FAIL    Lesson4/涵蓋率測試      0.029s
> ```
> **go tool cover** 工具指令獲得到測試涵蓋率 **77.8%** ，可藉由下方指令分析測試過程中涵蓋的程式碼 **Cover_Testing_Example.go** :
> 
> ```sass=
> PS D:\涵蓋率測試> go tool cover -html cover.out
> ```
> ![image alt](https://lh3.googleusercontent.com/xWF5qZCGn-4-CEi_I2WoXnr4pWKHtUa8hIImcQ2ccXH-2xdGnGJviL3N_7srGRAFKpyZ2uTN3dnJeDdgQMgBx3scTIC4hnw-_HdhRSX3q0AeJKvB3BCbBiQfhNSzsbL_1yl6ML_Hu-yyvC46HlKf1EiHw4LHxQlIU7EGchH2f8bajHo0oiHMMmQYcdjt1zxBb5lP2_gneppxjpGqsgtKoZzHDpaS91r-A8-4c6zMipGYWeUxOy77ssO9QkVX_v-8zUCsm_Y0_WuvKex3_G66Uwr7K1WGydBW_PY0BU0jFmzmE3lMpeOZxs29NeJgKbk98BMEQ1OW323Wpl2SNnpSiISOSYhtgeeksUaD8xD2BWIHCW3WzfekzSO2fran24nbLiJZEmhDNUA1pDX4iA48G0L-iCLXuHJVykt-SoVqhHyG6L3WPWxyk5y4Tt7uC-SXohsrWfl9bhaZNkva2zJc8BgNZLjMoz15yfvn1r12RbCWkClr_P1HEmcRne-FO2TQUuthvQIHf_AjgoFOzA3c5NSYkUjDArZJHNeH-ozg6Fj8KCZEuKaxYgcxlc-k1GMc34VVr5OO8a1OaErCrLJ4FMnhygjpA3m3ZlJWS25yO7VC_6BK0kGRutju5DiPwFO0KPjLGUwd4VPkoTdc7oRyEjZJSoB275XlnpCsue7-Vp-lWM1hGxLCcAHL=w676-h583-no "title")
> * 紅色部分表示測試未涵蓋到的程式碼


---
