做期货关注网站,mvc5网站开发之六,网页设计与制作html,爱网站官网Go 语言中#xff0c;包#xff08;Package#xff09;的目的和其他语言中的库或模块是一样的#xff0c;支持模块化、封装、单独编译和重用。 ——《The Go Programming Language》 有时候需要自己写一个包方便多次使用#xff0c;但是在导入自己写的包时遇到了问题。我以… Go 语言中包Package的目的和其他语言中的库或模块是一样的支持模块化、封装、单独编译和重用。 ——《The Go Programming Language》 有时候需要自己写一个包方便多次使用但是在导入自己写的包时遇到了问题。我以前以为import部分直接就是包的路径但是实际自己写了之后发现不是这样的。这部分实际上这部分是可以解释成一个标识符是由一个go.mod文件确定一般含义确实是路径末端。
Go 中模块的概念其实还包含了一部分版本管理的功能。所以 Go 的模块和版本管理无论是学习还是开发都不是一件容易的事情Go 团队也在一直努力调整和优化。本文只能代表当前版本go1.20.2版本的情况如果未来更新了我会进行备注。
go.mod是什么
每个 Go 的模块都是由go.mod确定该文件描述了模块的属性例如模块存放的路径是否依赖其他模块、最低使用 Go 版本等信息。比如modv0.8.0的go.mod内容为
module golang.org/x/modgo 1.17require golang.org/x/tools v0.1.12 // tagx:ignore然后在编译的时候编译器会去找有没有这个标识这个模块的go.mod如果有的话找到对应的xxx.go然后导入相应的包中使用的功能进行编译。
这里有两个问题
Go 在哪找模块的如何让 Go 从特定目录下搜索包 模块module和包package的区别在于模块是一系列包的集合并且在模块文件结构的根目录下有个go.mod文件自己甚至可以直接被编译成一个程序。而包是某一个或多个.go文件用来划分包级别的作用域package level可以当做其他语言的库。范围应该是模块包源代码文件。但是在某些情况下包、模块、库这三个词是可以混用的在不同情况下叫法不同但是却指同一个东西。 需要注意package main是个例外这并不是一个库尽管开头有个package而是用来表示这是个可以单独执行的程序。 创建模块和编写包的内容
这里举个例子来进行演示演示的例子来自《The Go Programming Language》中 Section 2.7是用来数一个数的二进制有多少位为1比如输入1返回1输入0x1234567890ABCDEF返回32。
新建一个文件夹popcount然后在里面创建一个名为popcount.go的文件
$ mkdir popcount
$ cd popcount
$ touch popcount.go输入以下内容下面这个算法不是最快的也不是最容易理解的但是可以解释很多东西
package popcount// pc[i]用来计数第i位是不是
var pc [256]byte
//初始化包
func init() {for i : range pc {pc[i] pc[i/2] byte(i1)}
}// PopCount返回x有多少位为1.
func PopCount(x uint64) int {return int(pc[byte(x(0*8))] pc[byte(x(1*8))] pc[byte(x(2*8))] pc[byte(x(3*8))] pc[byte(x(4*8))] pc[byte(x(5*8))] pc[byte(x(6*8))] pc[byte(x(7*8))])
}上文中pc首字母是小写的所以只能在popcount包中使用而PopCount首字母是大写的所以可以在导入popcount包的文件中使用。
继续在popcount中通过go mod init命令创建go.mod文件如下
$ go mod init test/popcount
go: creating new go.mod: module test/popcount
go: to add module requirements and sums:go mod tidy
$ ls
go.mod popcount.go可以看到多了个go.mod文件。
导入自建包本地包
然后在其他地方新建一个目录pop_test来编写使用这个包的程序代码可以和popcount在同一个目录下或者其他地方都行这里选择和popcount在同一个目录下如下
$ cd ..
$ mkdir pop_test然后在pop_test中新建一个go.mod
$ go mod init pop_test这时候go.mod的内容应该是如下样式
module pop_testgo 1.20用你喜欢的文本编辑器打开它在末尾添加这样两句话变成如下样式
module pop_testgo 1.20require test/popcount v0.0.0
replace test/popcount ../popcount最后这两句都不能省略少一句都不行。
第一句是为了说明使用popcount的版本第二句是因为我们使用的是本地包local package而不是下载导入的库本地包的位置并不在GOROOT/src/test/popcount中Go 编译的时候找不到的关于GOROOT后面还有一些内容。第二句话其实类似于 C 编译器中的选项-I。这里解决了开头的那两个问题
然后新建一个main.go文件输入以下内容
package mainimport (fmttest/popcount
)func main() {a : popcount.PopCount(0x1234567890ABCDEF)fmt.Println(a)
}这时候运行应该看到以下结果
$ go run main.go
32这种方法是官方推荐的但是问题在于要在项目的根目录如上的pop_test下创建一个go.mod。
第二种方法
下面这种方法是根据运行机制进行设置的说实话并不是很方便管理但是某些情况下却挺方便的。
上文中提到Go 默认是在GOROOT/src下寻找包的某个包就是GOROOT/src/包名。那么就可以直接在GOROOT/src下按照包名的结构放置自建的本地包然后就可以在程序代码中直接使用了不用再在项目根目录下创建一个go.mod文件来说明使用的本地包的位置了。
通过以下命令找到你的GOROOT如下
$ go env GOROOT
/usr/local/go你的可能不是/usr/local/go。对于 Go 的这些环境变量最好使用go env查看如果你使用echo $GOROOT可能会发现这个环境变量是空的。
此外最好不要用expert在 Shell 配置文件中修改这个环境变量因为标准库都在默认的GOROOT中一旦你切换了那么这些标准库你最好都复制到新位置。特殊情况下直接用expert修改但是只在当前终端切换不要彻底替换。
这种方法的最大弊端在于修改了/usr/local/go这些默认目录大部分时期是通过脚本自动操作配置的如果你进行了修改那么未来可能会出现问题和冲突而你又忘了修改了这部分那就是个很大的问题了。
所以如果必须用这种方法最好创建一个不会重名或者概率不大的文件夹比如ZhongUncle然后在里面创建包和配置go.mod。
希望能帮到有需要的人