我正在参加「掘金·启航计划」

PHP命名空间namespaceJavapackageJavaScriptmodule
package

Go语言包管理历史

Go
GOPATHGOPATHsrcvendorGo module

包的定义

什么是包(package)?

.go

我们开发的程序(项目或者类库)是由一个或多个包构成的。

程序、包、源码文件之间的关系如下图所示:

包的声明

GoGo modulego mod init
//创建项目目录
mkdir demo
//进入目录
cd demo
//初始化项目
go mod init github.com/my/demo

go.mod

go mod initdemogo.mod
module github.com/my/demo
​
go 1.18
go.modmodulego

go.sum

go get
go get github.com/go-sql-driver/mysql
go.sum
go getgo.mod
module github.com/my/demo
​
go 1.18
​
require github.com/go-sql-driver/mysql v1.7.0 // indirect

main包

mainmain
package main
​
func main(){
    //...
}

包的声明

package
package 包名
main

user/user.go

package user
​
type User struct {
    ID   int
    Name string
}

user/list.go

package user
​
func (u *User) List() []User {
    return []User{{ID: 1, Name: "test"}}
}

包的导入与使用

import

导入路径

标准库包的导入路径一般就是标准库的名称:

import "fmt"
import "time"
import "net/http"
github.com/my/demouser
import "github.com/my/demo/user"

对于有多重目录的包来说,比如controller目录下有一个order包,那么其路径需要包含完整的目录名:

import "github.com/my/demo/controller/order"

两种导入方式

Go的包有两种导入方式,一种是标准导入,一种是匿名导入。

标准导入

普通导入在关键字import后跟着导入路径即可,然后就可以通过包名调用包下的变量、函数、常量了:

package main
​
import "github.com/my/demo/user"
​
func main() {
  userList := user.List()
  fmt.Println(userList)
}
time
package time
​
import "time"
​
func Now() int64 {
    return time.Now().Unix()
}
timetime
package main
​
import t "github.com/my/demo/time"
import "time"
​
func main() {
  fmt.Println(time.Now().Unix())
  fmt.Println(t.Now())
}

如果别名是一个点号,那么此时导入的所有变量、函数、常量都不需要通过包名来访问了:

package main
​
import . "github.com/my/demo/time"
import "time"
​
func main() {
  fmt.Println(time.Now().Unix())
  fmt.Println(Now())
}
import
package main
​
import (
    "time"
​
    t "github.com/my/demo/time"
)
​
func main() {
  fmt.Println(time.Now().Unix())
  fmt.Println(Now())
}

匿名导入

import
init_
import (
    "database/sql"
    "time"
​
    _ "github.com/go-sql-driver/mysql"
)

可见性

privatepublic
package user
​
//private
func eat(){
    //....
}
​
//public
func Say(){
    //....
}

内部包

GithubGitlabinternalinternal

比如下面的目录中,internal包中所有的代码,只能在本项目中使用,其他开发者无法导入:

.
├── cmd
│   └── main.go
├── go.mod
├── go.sum
├── internal
│   └── util
│       └── util.go
├── time
│   └── time.go
└── user
    ├── list.go
    └── user.go

小结

包是Go语言代码的组织单位,通过包,我们可以管理我们的代码,尤其是当开发大型项目时,可以通过包进行模块划分,另外,我们也可以封装自己的包以供其他开发者使用,或者在自己的项目中导入其他开发者的包。

最后,总结一下在这篇文章中的要点:

  • Go包管理的历史
  • 包的声明,对go.mod和go.sum文件有清楚的认识。
  • 包的导入,包括导入路径,导入方式,可见性以及内部包。