一文带你了解Go的工程管理 2023-03-13 15:24 174阅读 0赞 前言: 大家好,我是asong,这是我的第三篇原创文章。这一篇将对Go的工程管理进行详细的介绍,学习了这些,对我们的日常项目开发有很大帮助。最后对go module的使用进行详细介绍(一定要看到最后呦!)。 ## 一、golang中包的概念 ## Go语言中使用包来组织源代码的,并且通过命名空间进行管理。所以所有源代码都必须属于某个包。每个go文件中第一行都必须是以package name声明自己所在包。 在介绍包之前,我们需要了解一下Go作用域问题。Go语言的作用域有一点区别于其他语言,所以一定好好掌握这一点,要不就会出现令人头皮发麻的bug,浪费我们开发的时间。 Go语言有三种类型的作用域: * 全局作用域:所谓全局作用域,就是在任何地方都可以访问的标识符。可以分为两类,一类是Go语言内置的预声明标识,比如类型、关键字等,我们在任何文件中都可以直接使用;另外一类,Go语言包内以大写字母开头的标识符,比如变量、常量、函数等,只要它的第一个字母是大写的,它们就具有全局作用域,我们在任意文件中就可以看到;这是Go语言设计者特别设计的,在其他语言中是没有这个,较新颖,需要注意。 * 包内作用域:既然以大写字母开头的标识符是全局作用域,那么以小写字母开头的标识符,就是仅在本包可见,其他包是不可见的,也就是具有包内作用域。 * 局部作用域:局部作用域也就是每个代码块内定义变量统称为局部变量,这些局部变量仅在当前代码块内可见。 Go语言中包是可以定义在很深的目录中,包的定义是不包括目录路径的,但是包的引用一般都是全局路径引用。标准包源码是位于GROOT/src下面,可以直接引用,但是自定义包必须放到GOPATH/src目录下才可以被引用。包引用这里就不做特别说明了,没有什么特别的,正常引用即可。这里主要介绍一下包引用格式,这里有一些特殊。包引用主要有四种引用方式。这里以fmt包为例子,进行代码示范。 * 普通引用:也就是标准引用,代码示范如下: import "fmt" * 别名引用:也就是我们在引用包的时候可以给这个包起一个别名,这样当包名比较长或者难记的时候,可以使用这个别名进行函数调用。代码示范如下: import M "fmt" * 省略包名方式:我们在对包中方法进行调用时,需要加上包名.进行调用,如果我们在包引用时使用一个点代替,那么在对包中的方法进行调用时,不需要再写包名.,直接调用即可。代码示范: import . "fmt"func main(){ //不再需要fmt. Println("test")} * 只想执行初始化init函数:有时候我们导入包只是为了执行初始化init函数,不需要使用包中的其他函数方法,那么我们在包引用的时候,使用如下方式,即可实现 import _ "fmt" 这里提到了init函数,init函数是在什么时候加载运行的呢?下面介绍一下包的加载过程。 Go语言的程序在执行main/main之前,Go会对整个程序的包进行初始化,执行流程如下: * 包初始化程序从main函数引用的包开始,逐级查找包的引用,直到找到没有引用其他包的包,最终生成一个包引用的有向无环图。 * Go编译器会将有向无环图转换为一棵树,然后从树的叶子节点开始逐层向上对包进行初始化。 * 单个包的初始化过程,先初始化常量、然后是全局变量,最后执行init函数。 ## 二、Go语言包管理 ## 包管理这里一直是Go诟病的一个功能。在Go1.11版本之前,Go使用go get获取第三方工具包,这种方式缺乏对依赖包版本的管理和可复制构建的支持。所以Go社区中已有一些解决方案,比如dep、glide等。但是依然会出现一些问题,比如依赖包版本的变化、依赖包的本地缓存问题、GOPATH的问题。所以Go在1.11版本引出了go module来解决这些问题,这一节我将对go module前后的一些变化进行介绍。 go get默认情况下是不支持包版本控制。在Go1.11之前的版本中,添加依赖意味着将该依赖项的源代码仓库克隆到GoPath下面。所以没有版本的概念。所以当不同的项目需要依赖包的不同版本时,Go包管理工具无法实现。 所以在Go1.5引入了vendor机制。使用vendor需要手动设置环境变量GO15VENDOREXPERIMENT=1,在Go1.6以后,默认是开启vendor目录查找的。vendor机制其实就是在包中引入vendor目录,将依赖部分的外部包复制到vendor目录下,这样编译器在查找外部依赖包时,就会优先在vendor目录下进行查找,所以使用vendor机制后,查找第三包流程如下: * 如果当前包下有vendor目录,则从其下查找第三方的包,如果没有找到,则继续执行下一步操作。 * 如果当前包目录下没有vendor目录,则沿当前包目录向上逐级目录查找vendor目录,直到找到GOPATH/src下的vendor目录,只要找到vendor目录就去其下查找第三方的包,如果没有则继续执行下一步操作。 * 在GOPATH下面查找依赖包 * 在GOROOT目录下查找依赖包。 vendor它为工程独立的管理自己所以依赖第三包提供了保证,多个工程独立管理自己的第三方依赖包。 但是vendor有一个重要的问题没有解决,那就是没有对外部依赖的第三方包的版本管理。我们通常是使用go get -u更新第三方包。默认的是将工程的默认分支的最新版本拉取到本地,并不能指定第三方包的版本。在实际的升级过程中,如果发现新版本有问题,则不能很快回退,这是个问题。所以Go官方的包依赖管理工具dep、go module都是为了解决这个问题。dep笔者也没有使用过,暂时不做介绍了,本文主要讲解go module。 go module带来了三个重要的内置功能: * go.mod文件,他与package.json文件功能类似 * 机器生成的传递依赖项描述文件 go.sum * 不要需要GOPATH限制,模块可处于任何路径下。 go mod在Go1.11和1.12版本中是需要手动开启,在1.12以后默认开启go mod。为了更好的讲解go module的使用,我们创建一个例子来完成说明。开发工具是Goland。Go版本:1.14。 由于GOPATH不再必要的了,我们可以在GOPATH外创建项目。为了方面我在桌面创建一个文件,具体文件格式如下: ![format_png][] 之后我们使用Goland打开该目录,进行一些配置。我们进入settings界面,在Go模块下,配置Go moudules,配置如下即可: ![format_png 1][] 这就配置好了,注意这里不需要配置GOPATH,如果配置了会导致错误出现。配置好后,我们打开终端,使用go mod init (项目目录) 进行初始化,这样该项目目录下会生成go.mod文件,执行go build会生成go.sum文件。好了这就使用上了go module了。那么我就来搞点事情,看一看go.mod是怎么工作的吧。我们在main.go文件中,添加beego依赖,代码如下: package main import ( "github.com/astaxie/beego" ) func main() { beego.Run() } 如果是以前,需要先执行go get去获取包,才能使用,现在有了包管理,就不需要了。我们直接go build main.go就可以了。这是我们就会看到控制台输出如下: ![format_png 2][] 再看go.mod文件如下: module src go 1.14 require ( github.com/astaxie/beego v1.12.1 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect ) 我们可以看出来新增了require模块,这里是关键引用,最后的v1.12.1就是版本号。在使用模块时,go命令将完全忽略vendor目录。为了向后兼容旧版本Go,获确保用于构建的所有文件以起存储在单个文件树中,我们可以运行go mod vendor。这样在主模块的根目录下生成一个vendor目录,并将依赖模块中的所有软件包存储在该目录中。运行执行可以看到vendor目录如下: ![format_png 3][] 这就是一个简单go模块样例,已将样例代码打包上发github上,有需要的可以下载观看。下载地址如下: Go模块代码样例,点击此处:https://github.com/sunsong2020/Golang\_Dream/tree/master/code\_demo/module\_demo。 好了,今日的分享结束了。结尾在此推广一下我的公众号:Golang梦工厂,我会不断发表关于Golang方面的知识,面试,个人理解等多个方面,一定对你受益匪浅。公众号搜索:Golang梦工厂,或直接扫描下方二维码即可。 ![format_png 4][] [format_png]: /images/20230312/5402fae746304eee92114143fb172161.png [format_png 1]: /images/20230312/769f737aaf4d4f39bf0ca1dce51e42b9.png [format_png 2]: /images/20230312/bf107d7226e243288e6272ac85a429ba.png [format_png 3]: /images/20230312/0962cbbc1cf74495a5ea1bba953927b5.png [format_png 4]: /images/20230312/ff6aa5daa3a44650b49b1569a16cf8c6.png
相关 一文带你了解Go的工程管理 前言: 大家好,我是asong,这是我的第三篇原创文章。这一篇将对Go的工程管理进行详细的介绍,学习了这些,对我们的日常项目开发有很大帮助。最后对go module的使用进 朱雀/ 2023年03月13日 15:24/ 0 赞/ 175 阅读
相关 「React」一文带你了解 Redux 目录 1. React 组件状态 (1)什么数据放在 state 中 (2)修改 state 冷不防/ 2023年01月10日 13:28/ 0 赞/ 148 阅读
相关 一文带你了解TypeScript函数类型 目录 本文概览: 1. 函数类型 (1)为函数定义类型 (2)完整的函数 ╰+哭是因爲堅強的太久メ/ 2022年12月27日 01:25/ 0 赞/ 130 阅读
相关 一文带你了解云原生 > 文章转载于百度百家号:AI课工场 自进入云计算时代后,大量的新概念、新技术如雨后春笋般的涌现出来,从早期的openstack、IAAS平台,到中期的容器技术、微服务架构, 川长思鸟来/ 2022年12月07日 04:28/ 0 赞/ 177 阅读
相关 一文带你了解React生命周期 目录 1. React生命周期概览 2. 组件挂载阶段 (1)constructor 淡淡的烟草味﹌/ 2022年10月29日 09:26/ 0 赞/ 146 阅读
相关 一文带你了解equals()和hashCode() 一 前言 我们都知道,要比较两个对象是否相等时需要调用对象的equals()方法,即判断对象引用所指向的对象地址是否相等,对象地址相等时,那么与对象相关的对象句柄、对象头 你的名字/ 2022年08月31日 15:17/ 0 赞/ 109 阅读
相关 【HTTPS】一文带你全面了解SSL 【引言】 HTTPS是众所周知的,但要是问到"S"的含义是什么?也许能回答上来的人并不多。HTTPS其实是HTTP + SSL,S的含义也就是Secure Socket La 浅浅的花香味﹌/ 2021年10月19日 05:48/ 0 赞/ 389 阅读
还没有评论,来说两句吧...