最近在实现一个简单的网页程序时,需要同时导入本地包和需要从github.com下载软件包:github.com/golang/freetype。用go get 方式下载的时候报错,报错的原因大家都知道,墙外的资源受限。不使用Go Module模式的情况下,本地包正常使用,一旦开启Go Module模式,并设置代理时,外部第三方包可以下载并使用,本地包却不能正常导入了。为了确保两种类型的包都能正常使用,调整了本地包的使用方式。
二、解决办法于是开启go Module模式和代理。具体如下:
这里使用了GOLAND作为开发工具,也可以使用命令行模式设置:
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
或者直接新建一个go Module模式的项目:
1、新建Module项目
此时,系统会在项目文件夹下面新建一个go.mod文件。当然,你也可以用命令行来新建go.mod文件,如: go mod init 你的项目文件夹名称(或者其他自定义名称)
注意go.mod文件中的第一行: 其中 show_pic_mod是我的文件夹名称,这里请大家自行替换自己的项目文件夹。show_pic_mod是本地包引入路径,后面再详细说明。
2、下载软件包
go get -v -u github.com/golang/freetype
go: finding github.com/golang/freetype latest
go: finding golang.org/x/image latest
此时,go.mod文件中会添加下载包版本的信息。
module show_pic_mod
go 1.13
require (
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
)
3、导入第三方软件包
当包被下载完成后可以导入开发文件中了,在GOLAND的开发环境中可以正常使用,代码提示正常。
4、导入本地软件包
在项目主文件夹/show_pic_mod/下新建一个子文件夹,如:/mysession,在这个文件夹中创建本地软件包
在这个目录下,新建一个包,并实现一个外部可以调用的方法,这里用一个生成随机数的方法来测试。
package mysession
import (
"encoding/base64"
"math/rand"
"sync"
)
type Mananger struct {
cookiename string // cookie名称
maxLifeTime int64 // 有效时间
}
// 生成seesionId
func (manager *Mananger)SessionId()string {
// 创建32长度的byte类型的切片
bs := make([]byte, 32)
// 产生一个长度为len(p)的随机数写入p中。
if _, err := rand.Read(bs); err != nil {
return ""
}
// URLEncoding :4648定义的另一base64编码字符集,用于URL和文件名。
return base64.URLEncoding.EncodeToString(bs)
}
然后在主程序中导入这个本地包。
注意导入路径,记得我们建立的go.mod文件吗?show_pic_mod是go.mod文件中的第一个行所定义的。mysession是本地包的路径名。组合起来即可以实现本地包的导入。
提醒: go.mod文件中的第一个行所定义的“show_pic_mod”是可以手工更改的。比如:改为“test_mod”,当然在main程序中的导入路径也必须更改。
这样就可以在Go Module模式下调用本地包了。
var globalSession *mysession.Mananger
func main() {
fmt.Println(globalSession.SessionId())
}
三、相对路径的问题
Golang 有多种运行方式,如:go run main.go,或者go build main.go 再执行程序。go run命令定位到临时目录下运行,通过go build编译后执行的命令则定义于编译后该文件的存放目录。由于Golang的相对路径是相对于执行命令时的目录。当程序中需要调用文件时,相对路径成为一个必须考虑的问题。
相对路径的解决方法
1、获取当前运行文件的路径,让后将当前路径与相对路径结合的办法。
2、通过参数传递指定路径。
3、程序中增加os.Getwd()进行多层判断。
4、配置全局系统变量,可以更加固定的存放配置文件,通过os.Getenv()函数来获取系统全局变量,然后与相对路径进行拼接的方式确定路径。
下面的程序实现了第4种方式,其他方法我没有去具体实现。
具体如下:
1、设置系统全局变量,首先定义一个“GOHOME”系统变量。
2、具体的目录组织形式
HOME: 存放运行程序
font: 存放字库文件
html: 存放网页文件
pic: 存放网页所需的图片文件
// 通过系统全局变量, 更加固定的存放配置文件
// ToSlash()将路径中的目录分割符号"\"改为"/"
filepath:=filepath2.ToSlash(os.Getenv("GOHOME"))
fmt.Println("全局环境变量:",filepath)
fileAndpath := filepath2.Join(filepath, "./html/name_index.html")
fmt.Println("文件名和路径:",fileAndpath)
templ, err := template.ParseFiles(fileAndpath)
// 错误检查
checkErr2(err)
...
这样可以相对固定的存放一些配置文件、图片、CSS、js等文档,不会因为不同的运行方式导致找不到路径错误发生,当然系统全局变量根据实际需要进行调整。
参考资料:
https://www.cnblogs.com/dexte/p/12337220.html
https://www.cnblogs.com/just-save/p/12172947.html
https://studygolang.com/articles/12563
https://blog.csdn.net/Charliewolf/article/details/84109134
https://blog.csdn.net/gnufre/article/details/104183578