這次聊Package, 主要是因為接著都會需要對業務面向作模組的拆分.
或者對功能作拆分, 甚至是第三方套件的引入.
一個專案只要不是只有一個main.go, 就一定會有其他的package.
程式碼的目錄, 可以重複利用程式的方案, 方便維護。
Go默認提供很多package, 像是fmt、is等。
開發者也可以創建自己的package。
package要求所有檔案的第一行添加package名稱,標示該文件所歸屬的package。
package 包名稱
// main.go
package main
import (
"fmt"
. "hello/math"
)
func main() {
fmt.Println("hello")
fmt.Println(Average([]float64{1, 2}))
}
// math/math.go
package math
func Average(xs []float64) float64 {
total := float64(0)
for _, x := range xs {
total += x
}
return total / float64(len(xs))
}
# 編譯hello package
cd $GOPATH/src/hello;
go install;
# 因為有main package, 所以會安裝到$GOPATH/bin 作為可執行包
# 編譯hello package
cd $GOPATH/src/hello/math;
go install;
# 因為沒有main package, 所以會安裝到$GOPATH/pkg下 作為工具包
使用import package,Go會先在 $GOROOT/src下尋找指定的package。
若找不到就往$GOPATH/src目錄下尋找。
找不到就會報出編譯錯誤。
package main
import (
// fmt位於$GOROOT/src下,找到!
"fmt"
// gin並不在$GOROOT/src, 接著找$GOPATH/src找github.com這目錄,找到往內找gin-gonic目錄,再找gin package
"github.com/gin-gonic/gin"
//
. "github.com/go-sql-driver/mysql"
)
在一個package內嵌套令一個package; 使用上只要指名路徑關係.
// math/math/extend/min.go
package extend
func init() {
fmt.Println("extend ==> init()")
}
func Min(a float64, b float64) float64 {
if a >= b {
return a
}
return b
}
// math/math.go
package math
import (
"fmt"
"hello/math/extend"
)
func init() {
fmt.Println("math ==> init()")
}
func Average(xs []float64) float64 {
total := float64(0)
for _, x := range xs {
total += x
}
return total / float64(len(xs))
}
func Min(a float64, b float64) float64 {
return extend.Min(a, b)
}
// main.go
package main
import (
"fmt"
. "hello/math"
)
func init() {
fmt.Println("main ==> init()")
}
func main() {
fmt.Println("hello")
fmt.Println(Average([]float64{1, 2}))
fmt.Println(Min(1, 2))
}
// base/factory.go
package base
// define interface for Class
type Class interface {
Do()
}
var (
// 存放註冊好的 類別工廠資訊
factoryByName = make(map[string]func() Class)
)
// 註冊一個類別工廠
func Register(name string, factory func() Class) {
factoryByName[name] = factory
}
// 根據name創建對應的類別
func Create(name string) Class {
if f, ok := factoryByName[name]; ok {
return f()
}
panic("name not found")
}
// ex1/reg.go
package ex1
import (
"fmt"
"github.com/tedmax100/factory/base"
)
type Class1 struct {
}
func (c *Class1) Do() {
fmt.Println("class1")
}
func init() {
base.Register("Class1", func() base.Class {
return new(Class1)
})
}
// ex2/reg.go
package ex1
import (
"fmt"
"github.com/tedmax100/factory/base"
)
type Class2 struct {
}
func (c *Class2) Do() {
fmt.Println("class2")
}
func init() {
base.Register("Class2", func() base.Class {
return new(Class2)
})
}
// main.go
package main
import (
"github.com/tedmax100/factory/base"
_ "github.com/tedmax100/factory/ex1"
_ "github.com/tedmax100/factory/ex2"
)
//因為上面使用匿名導入了ex1 & ex2 package.
//main()執行前, 這兩個package的init()會被調用, 而註冊了class1 & class2
func main() {
c1 := base.Create("Class1")
c1.Do()
---
[淺談Go專案布局與internal package](https://ithelp.ithome.com.tw/articles/10337030)