Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >层次分明井然有条,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang包管理机制(package)EP10

层次分明井然有条,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang包管理机制(package)EP10

作者头像
用户9127725
发布于 2022-09-21 07:22:24
发布于 2022-09-21 07:22:24
25200
代码可运行
举报
运行总次数:0
代码可运行

    Go lang使用包(package)这种概念元素来统筹代码,所有代码功能上的可调用性都定义在包这个级别,如果我们需要调用依赖,那就“导包”就行了,无论是内部的还是外部的,使用import关键字即可。但事情往往没有那么简单,Go lang在包管理机制上走了不少弯路,虽然1.18版本的包管理已经趋于成熟,但前事不忘后事之师,我们还是需要了解一下这段历史。

    环境变量

    一般情况下,go lang在系统中会依赖两个环境变量,分别是:GOPATH 和 GOROOT,有点类似于Python解释器目录的概念,GOROOT 这个变量的作用就是为了告诉当前运行的 Go 进程当前 Go安装路径,当要运行的时候去什么位置找GoSDK相关的类。

    GOPATH 这个变量的设定是默认所有的项目和引用的第三方包都下载到GOPATH的src目录下,也就是说,你的代码只要不在GOPATH里,就没法编译。我们可以理解这个目录就是项目目录,这一点跟Python区别还是挺大的,Python的pip包管理机制至今都是经典的包依赖设计模式。

    GOPATH这种设定方式会导致很多问题,比方说我有很多go lang项目,而每个项目又都有自己的GOPATH目录,那所有依赖的包就都在项目各自目录下,导致重复包过多,反之,如果大家都用一个GOPATH目录,又会带来版本问题,每个项目依赖的包版本不一致,到底怎么进行统筹又是一个问题,这就是GOPATH设定早期被人诟病的原因。

    Go modules

    针对因为GOPATH这种反人类的设计而导致的包管理乱象,Go lang 1.11 版本的时候推出了新特性 Go modules。

    Go modules 是官方推出的依赖管理工具,Go modules 提供了3个重要的功能:

    1.go.mod 文件,它和Node的package.json文件的功能相似,都是记录当前项目的依赖关系。

    2.机器生成的传递依赖项描述文件 : go.sum。

    3.不再有 GOPATH 的反人类限制,所有代码可以位于电脑的任何路径中。

    go lang1.18早已经集成了Go modules,但就像golang1.18第一篇精炼教程里写得那样,默认还是反人类的GOPATH模式,你想用,得通过命令手动开启:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go env -w GO111MODULE=on

    为了能够向下兼容维护go1.11版本以下的项目,可以设置为兼容模式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go env -w GO111MODULE=auto

    三方包管理

    三方包指的是外部开源的一些包,而使用go modules机制管理三方包相对简单,首先新建一个项目目录,比如c:/www/test 

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd c:/www/test

    进入项目目录后,初始化项目:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go mod init test

    系统返回:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
C:\Users\liuyue\www\test>go mod init test
go: creating new go.mod: module test

C:\Users\liuyue\www\test>dir


2022/08/12  12:13    <DIR>          .
2022/08/12  12:13    <DIR>          ..
2022/08/12  12:13                21 go.mod
               1 个文件             21 字节
               2 个目录 228,767,113,216 可用字节

    这里注意项目名和目录名称要吻合,go.mod 文件是开启 modules 的必备配置文件。它记录了当前项目引用的包数据信息。go.mod 文件中定义了以下关键词:

    module:用于定义当前项目的模块路径

    go:用于设置Go 版本信息

    require:用于设置一个特定的模块版本

    exclude:用于从使用中排除一个特定的模块版本

    replace:用于将一个模块版本替换为另一个模块版本

    接着,运行go get命令安装三方包,比如说gin框架:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go get github.com/gin-gonic/gin

    随后编写main.go文件,也就是main包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
	d := gin.Default()
	d.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{"message": "hello go 1.18", "data": ""})
	})
	d.Run("127.0.0.1:5000")
}

    这里将刚刚安装的三方包导入,然后再main函数中调用。

    紧接着启动服务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go run main.go

    系统返回:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
C:\Users\liuyue\www\test>go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /                         --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on 127.0.0.1:5000
[GIN] 2022/08/12 - 12:19:20 | 200 |      3.8876ms |       127.0.0.1 | GET      "/"
[GIN] 2022/08/12 - 12:19:21 | 404 |            0s |       127.0.0.1 | GET      "/favicon.ico"

    说明三方包的服务已经启动了,访问http://localhost:5000:

    这就是一个go lang项目导入三方包的具体流程。

    接着我们打开项目中的go.mod文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module test

go 1.18

require (
	github.com/gin-contrib/sse v0.1.0 // indirect
	github.com/gin-gonic/gin v1.8.1 // indirect
	github.com/go-playground/locales v0.14.0 // indirect
	github.com/go-playground/universal-translator v0.18.0 // indirect
	github.com/go-playground/validator/v10 v10.10.0 // indirect
	github.com/goccy/go-json v0.9.7 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/leodido/go-urn v1.2.1 // indirect
	github.com/mattn/go-isatty v0.0.14 // indirect
	github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/pelletier/go-toml/v2 v2.0.1 // indirect
	github.com/ugorji/go/codec v1.2.7 // indirect
	golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
	golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
	golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
	golang.org/x/text v0.3.6 // indirect
	google.golang.org/protobuf v1.28.0 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
)

    三方包gin以及gin所依赖的三方包都一目了然。

    内部包管理

    内部包指的是项目内部的包,一般情况下就是自己开发的可复用的包,go modules也可以对内部包进行管理,在刚刚创建的test项目中,新建目录my:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
C:\Users\liuyue\www\test>mkdir my

C:\Users\liuyue\www\test>dir
 驱动器 C 中的卷没有标签。
 卷的序列号是 0A64-32BF

 C:\Users\liuyue\www\test 的目录

2022/08/12  12:39    <DIR>          .
2022/08/12  12:13    <DIR>          ..
2022/08/12  12:18             1,046 go.mod
2022/08/12  12:18             6,962 go.sum
2022/08/12  12:16               228 main.go
2022/08/12  12:39    <DIR>          my
               3 个文件          8,236 字节
               3 个目录 228,568,178,688 可用字节

C:\Users\liuyue\www\test>

    然后再my目录新建一个my.go文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package my

import "fmt"

func New() {
  fmt.Println("我是my包")
}

    这里我们声明包与目录名一致,随后再声明一个New函数。

    接着改写main.go内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
	"fmt"
	"test/my"
)

func main() {
	fmt.Println("main run")
	// 使用my
	my.New()
}

    程序返回:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
main run
我是my包

    触类旁通,如果包不在同一个项目下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
├── moduledemo
│   ├── go.mod
│   └── main.go
└── mypackage
    ├── go.mod
    └── mypackage.go

    这个时候,mypackage也需要进行module初始化,即拥有一个属于自己的go.mod文件,内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module mypackage

go 1.18

    然后我们在moduledemo/main.go中按如下方式导入:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import (
    "fmt"
    "mypackage"
)
func main() {
    mypackage.New()
    fmt.Println("main")
}

    结语

    对于 Go lang 的项目来说,如果没有开启 go mod模式,那么项目就必须放在 GOPATH/src 目录下,项目本身也可以看作为一个本地包,可以被其它 GOPATH/src目录下的项目引用,同时也可以被go modules模式的项目引入,因为go modules的原理是先去GOPATH/src目录下寻址,如果没有才去指定目录寻址,但反过来,如果是放在go modules项目中的本地包,GOPATH/src目录下的项目就无法引用,因为GOPATH规定项目都必须得放在GOPATH/src目录下,它只会在GOPATH/src目录下寻址,这是我们需要注意的地方。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
初窥门径代码起手,Go lang1.18入门精炼教程,由白丁入鸿儒,首次运行golang程序EP01
    前文再续,书接上回,前一篇:兔起鹘落全端涵盖,Go lang1.18入门精炼教程,由白丁入鸿儒,全平台(Sublime 4)Go lang开发环境搭建EP00 ,我们搭建起了Go lang1.18的开发运行环境,接着就可以运行第一个Go lang1.18程序了,让我们整装待发,开启Go lang1.18的处女航。
用户9127725
2022/08/08
3760
[系列] - 使用 go modules 包管理工具(一)
我想实现一个开箱即用的 API 框架的轮子,这个轮子是基于 Gin 基础上开发的。
新亮
2019/08/28
7560
[系列] - 使用 go modules 包管理工具(一)
用go-module作为包管理器搭建go的web服务器
本篇博客主要介绍了如何从零开始,使用Go Module作为依赖管理,基于Gin来一步一步搭建Go的Web服务器。并使用Endless来使服务器平滑重启,使用Swagger来自动生成Api文档。
SH的全栈笔记
2019/10/20
1.7K0
GO问答之为什么项目要在 GOPATH/src 目录下
每次升级bee工具都要先改其源码使之可以在任意目录内生成项目。实在不喜欢把第三方库和自己的所有项目放在一个目录下,太乱了。顺便问一下go为什么建议把所有项目源码都放在gopath/src目录内?
波罗学
2019/07/31
3.4K0
Golang中的包管理工具 - Go Modules
在Go1.5之前使用GOROOT和GOPATH这2个系统环境变量来决定包的位置,对于开发者主要使用GOPATH。GOPATH 解决了第三方源码依赖的问题,看一下我本机 $GOPATH/src 下的目录:
猿哥
2019/08/01
1.6K0
速学 GoMod 包管理(2021版本)
在开发中一个很现实的问题,如果你开发一个项目里面会用到 Redis,于是你写了一套与 Redis 的驱动和数据交互模块。
小锟哥哥
2022/05/10
5550
速学 GoMod 包管理(2021版本)
Go 编程 | 连载 21 - Go Modules 和 Package
GOPATH 是 Go 语言中使用的一个环境变量,它使用绝对路径提供项目的共工作目录,GOPATH 适合处理大量 Go 语言源码、多个包组合而成的复杂工程。
RiemannHypothesis
2022/09/28
5200
官方golang包管理神器,值得一试!
我们上次说过如何让一个项目在 Goland 编译器跑起来,但是要自己去下包,要花不少时间找包下包,是不是很麻烦?
机智的程序员小熊
2020/05/20
2.6K0
Go | 浅谈包管理模式
go的编译器会在 $GOPATH/src 下面寻找对应的模块,src 下的每一个目录都可以对应一个模块,目录中的目录也可以是一个模块
甜点cc
2022/11/16
5320
Go | 浅谈包管理模式
浅谈GoPath和Go Modules包管理
从v1.5开始开始引入vendor模式,如果项目目录下有vendor目录,那么go工具链会优先使用vendor内的包进行编译、测试等
仙人技术
2021/08/31
1.2K0
浅谈GoPath和Go Modules包管理
Go语言中的包管理和模块化
创建一个新的Go模块可以使用go mod init命令。该命令会生成一个go.mod文件,记录模块的元数据和依赖信息。
数字扫地僧
2024/06/21
1960
GoLang 新版包管理 -- go module 的使用
上一篇文章中,我们介绍了 GoLang 中包的使用与包管理机制。 GoLang 包的使用与管理
用户3147702
2022/06/27
2.4K0
GoLang 新版包管理 -- go module 的使用
Go两周入门系列-包管理
实际项目总要依赖各种第三发开发包,各类开发语言都有自己的第三方包依赖管理工具,例如:java的maven、js的npm、php的composer等,golang在1.11版本以前官方是没有提供包依赖管理工具的,只有一些社区提供的工具,从1.11版本以后官方就提供mod模块管理工具。
用户10002156
2023/10/04
3250
Go两周入门系列-包管理
go包管理速通,一篇文章就够了
最近在看一些go语言相关的书,发现了一个有意思的事情:其中一本书最新印刷的版本是2017年3月,而golang包管理的后起之秀 gomodule伴随go1.11于2018年8月诞生——因此,书里没有。
白泽z
2022/08/18
5050
go包管理速通,一篇文章就够了
Go的包管理学习笔记
大部分语言都有版本管理工具,比如nodejs的npm,python中的pip,java里的maven,但是go语言的版本管理经历了漫长的演进历程:
Johns
2021/08/11
1.2K0
大道如青天,协程来通信,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang通道channel的使用EP14
    众所周知,Go lang的作用域相对严格,数据之间的通信往往要依靠参数的传递,但如果想在多个协程任务中间做数据通信,就需要通道(channel)的参与,我们可以把数据封装成一个对象,然后把这个对象的指针传入某个通道变量中,另外一个协程从这个通道中读出变量的指针,并处理其指向的内存对象。
用户9127725
2022/09/23
2150
大道如青天,协程来通信,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang通道channel的使用EP14
Go Module详细使用教程,包管理不在难
go modules是 golang 1.11引入的新特性。模块是相关Go包的集合。modules是源代码交换和版本控制的单元。go命令直接支持使用modules,包括记录和解析对其他模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。
公号:咻咻ing
2020/03/04
20.6K0
Go的包管理工具(三):Go Modules
在前面的文章,我们先是介绍了Go 的几种包管理方式,然后具体介绍了一种包管理的工具:glide。随着 Go 1.11 的发布,官方的包管理工具 Go Modules 变得流行起来。在发布不久的 Go 1.12 版本中,增强了对 Go Modules 的支持。本文将会介绍如何在项目中安装和使用 Go Modules 。
aoho求索
2019/05/07
1.5K0
急如闪电快如风,彩虹女神跃长空,Go语言高性能Web框架Iris项目实战-初始化项目ep00
    在Golang Web编程的世界里,君不言高性能则已,言高性能必称Iris。彩虹女神的名号响彻寰宇、名动江湖,单论一个快字,无人能出其右,就连以简洁轻量著称于世的Gin也难以望其项背,只见彩虹女神Iris回眸一笑撩人心扉:“虽然你们也不是那么慢,但我还是快那么一点点......”,本次就让我们来一睹彩虹女神Iris的芳颜,感受宇宙最快Web框架的神乎其神。
用户9127725
2022/09/21
3300
go的包管理
go没有命名空间的概念,只有包的概念,每个目录下的package名需要一致,但是不需要跟所在目录名相同:
仙士可
2022/01/18
7270
go的包管理
相关推荐
初窥门径代码起手,Go lang1.18入门精炼教程,由白丁入鸿儒,首次运行golang程序EP01
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验