目录

go mod如何导入本地包?

我们在使用go开发的时候,经常会用到很多第三方的包,他们大多以开源的形式提供下载 ,如托管到github上,我们只需要使用 go get github.com/xxx/xxxx 就可以下载到,这很方便。 但是我们也经常会遇到那种不开源的包,比如公司内别的部门开发的包,并没有开源,只是内部使用,这时如果我们要使用该包就不能再使用go get 了,本文就详细说明一下如何导入本地的包,以及过程中可能会遇到的坑。

这种需要导入的包根据其是否使用go mod 管理分为两种情况

不是 go mod 项目

首先创建我们自己的项目,使用go mod 方式,并且创建一个main.go文件 ,项目名为 modtest

1
2
3
4
➜  modtest tree
.
├── go.mod
├── main.go

go.mod 中此时为

1
2
3
module modtest

go 1.17

这时我们把第三方的包直接放到项目中,当然,也可以再创建一层目录, 这里我将project 包直接放到我主项目的根目录下,以下是目录结构

1
2
3
4
5
6
7
➜  modtest tree
.
├── go.mod
├── main.go
└── project
    └── pkg
        └── p.go

p.go 文件中定义一个简单的Show函数

1
2
3
4
5
6
7
package pkg

import "fmt"

func Show(name string) {
    fmt.Println("in project: ", name)
}

此时,如何在主项目的main.go 中调用这里的Show函数呢? 这里很简单,只需要按照目录结构导入pkg包即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import (
    "fmt"
    "modtest/project/pkg"
)

func main() {
    fmt.Println("hi~")
    pkg.Show("杨彦星")
}

其实这种情况下还是比较简单的,这里导入的第三方包就是主项目里的文件一样,试想一下,这个如果没有,你需也是要一层层的创建目录与对应的文件,然后写函数进行调用。

导入go mod 包

与上面的相比,如果使用go mod 创建和包会相对复杂一些,但是这种情况会更普遍,我们可以认为,这种第三方的包和自己要开发的主项目不是同一个项目,还是上面的代码,只是这次 project 也使用go mod init project 来变成和主项目不同的项目。 此时的目录结构如下

1
2
3
4
5
6
7
8
➜  modtest tree
.
├── go.mod
├── main.go
└── project
    ├── go.mod
    └── pkg
        └── p.go

最外层的go.mod 不变,还是

1
2
3
module modtest

go 1.17

project 目录下的go.mod为

1
2
3
module project

go 1.17

此时如果我们想要使用project 项目中的Show函数,需要修改主项目的 go.mod 文件,手工引入

1
2
3
4
5
6
module modtest

go 1.17

require project v0.0.1
replace project => ./project

第一个require project v0.0.1 定义了引入的包名,这里的包名可以随便起,并不一定要和内部的包名一样,但是一般情况下还是保持一致,后面写上一个版本号。 之后要写上replace project => ./project , 定义第三方的包目录所在的位置,这个位置是相对go.mod文件的,当然也可以是绝对路径,但是不推荐,因为如果在家加班时,你家里的电脑路径未必和你工作中的电脑是一样的,不要给自己找麻烦。 接下来就是如何调用了,修改主项目的main.go 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import (
    "fmt"
    "project/pkg"
)

func main() {
    fmt.Println("hi~")
    pkg.Show("yangyanxing")

}

注意我们引入包的时候是 "project/pkg"project 就是在go.mod 中定义的名字,pkg 就是project项目中的包路径了。

注意的问题

  1. 定义包的版本号问题

上面我使用的是 require project v0.0.1,版本号为 v0.0.1, 这里一定要有至少两个点., 如果只有一个点,或者没有点,则会报malformed module path "project": missing dot in first path element

  1. 调用时不要再写主包名了

在第一种情况下,我们在引入包的时候,引入的路径是 "modtest/project/pkg" , 最前面是需要加上主项目的module 名的,而对于第二种情况,引入的情况是不再需要主module名了,"project/pkg"

参考文章

3分钟带你掌握 go mod 导入本地包