栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Go语言 包管理

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go语言 包管理

Go语言

文章目录
    • Go语言
      • 8. 包管理
        • 8.1 工作区
          • 8.1.1 工作区结构
          • 8.1.2 GOPATH
          • 8.1.3 GOROOT
          • 8.1.4 GOBIN
        • 8.2 包的声明
        • 8.3 包的导入
          • 8.3.1 导入声明
          • 8.3.2 远程导入
          • 8.3.3 别名导入
          • 8.3.4 匿名导入
        • 8.4 main包
        • 8.5 包的初始化
        • 8.6 包的命名
        • 8.7 依赖包管理
        • 8.8 Go语言命名规范
          • 8.8.1 驼峰式命名法
          • 8.8.2 导出标识符
        • 8.10 知识拓展(标准包简介)
          • 8.10.1 unsafe
          • 8.10.2 os-os/exec-syscall
          • 8.10.3 archive/tar和/zip-compress
          • 8.10.4 fmt-io-bufio-path/filepath-flag
          • 8.10.5 strings-strconv-unicode-regexp-bytes
          • 8.10.6 math-math/cmath-math/rand-sort-math/big
          • 8.10.7 container-/list-ring-heap
          • 8.10.8 time-log
          • 8.10.9 encoding/Json-encoding/xml-text/template
          • 8.10.10 net-net/http-html
          • 8.10.11 runtime
          • 8.10.12 reflect

8. 包管理

Go语言包的主要作用是把功能相似或相关的代码组织在同一个包中,以方便查找和使用。

8.1 工作区

Go语言中没有工程文件的概念,而是通过目录结构来体现工程的结构关系。Go代码必须放在工作区中。

8.1.1 工作区结构

工作区其实就是一个对应于特定工程的目录,它应包含三个子目录:src目录、pkg目录和bin目录。

GO工作区:
 ├─bin
 │ ...
 ├─pkg
 │ └─windows_amd64
 │ ├─github.com
 │ ...
 └─src
 ├─github.com
 ...

各个目录作用

  • src目录

    用于以代码包的形式组织并保存Go源码文件(如.go、.c、.h、.s等),同时也是Go编译时查找代码的地方

  • pkg目录

    用于存放经由go get/install命令构建安装后的代码包的“.a”归档文件,也是编译生成的lib文件存储的地方。

  • bin目录

    与pkg目录类似,在通过go get/install命令完成安装后,保存由Go命令源码文件生成的可执行文件。

目录src用于包含所有的源代码,是Go命令行工具一个强制的规则,而pkg和bin则无须手动创建,必要时Go命令行工具在构建过程中会自动创建这些目录。

8.1.2 GOPATH

GOPATH可以理解为工作目录或工作区,是平时接触最多的一个环境变量。它可以是一个目录,也可以是多个目录路径,每个目录代表一个工作区。

Go的所有操作(编码、依赖管理、构建、测试、安装等)基本上都是围绕GOPATH来进行的。GOPATH必须要设置,但并不是固定不变的,GOPATH的目的是为了告知Go需要代码的时候去哪里查找。需要注意的是,这里的代码包括本项目和引用外部项目的代码。GOPATH可以随着项目的不同而重新设置。

在实际开发环境中,工作目录往往有多个。这些工作目录的目录路径都需要添加至GOPATH。

为了能够构建这个工程,需要先把所需工程的根目录加入到环境变量GOPATH中。否则,即使处于同一工作目录(工作区),代码之间也无法通过绝对代码包路径完成调用。

使用命名行添加GOPATH

查看当前的GOPATH

临时添D:NewProject目录到GOPATH可使用set命令,Windows下使用分号作为分隔符:

使用set添加GOPATH,添加的是临时变量,当cmd窗口结束时,该变量就会结束。如果想要永久添加一个GOPATH路径,可以使用setx,只需要将如上命令的“set”更换成“setx”即可。

如果GOPATH设置了多个工作区,那么查找依赖包时是以怎样的顺序进行呢?例如包a依赖包b,包b依赖包c,那么会先查找c包。那在工作区是如何查找这个依赖包c的呢?

→ 首先,在查找依赖包的时候,总是会先查找GOROOT目录,也就是Go语言的安装目录,如果没有找到依赖的包,才到工作区去找相应的包。在工作区中是按照设置的先后顺序来查找的,也就是会从第一个开始依次查找,如果找到就不再继续,如果没有找到就报错。

go get会下载代码包到src目录,但是只会下载到第一个工作区目录。

8.1.3 GOROOT

GOROOT是Go语言的程序安装目录,并非必须要设置的。GOROOT的目的就是告知Go当前的安装位置,编译的时候从GOROOT去找SDK的system library。

Windows下查看GOROOT

8.1.4 GOBIN

GOBIN目录一般为GOPATH的可执行文件放置目录,一般指bin。默认安装的Go语言是没有设置GOBIN目录的。

只有当环境变量GOPATH中只包含一个工作区的目录路径时,go install命令才会把命令源码安装到当前工作区的bin目录下。若环境变量GOPATH中包含多个工作区的目录路径,像这样执行go install命令就会失效,此时必须设置环境变量GOBIN。

8.2 包的声明

包是结构化代码的一种方式:每个程序都由包(通常简称为pkg)的概念组成,可以使用自身的包或者从其他包中导入内容。

  • Go语言的源代码以代码包为基本的组织单位
  • 在文件系统中,代码包是与文件目录一一对应的,文件目录的子目录也就是代码包的子包。
  • 在工作区中,一个代码包的导入路径实际上就是从src子目录到该包的实际存储位置的相对路径。

每一个Go源文件的第一行都需要声明包的名称,声明一个包使用关键字package。

每个Go文件都属于且仅属于一个包。一个包可以由许多以“.go”为扩展名的源文件组成,因此文件名和包名一般来说都是不相同的。

代码包的名称一般会与源码文件所在的目录同名,如果不同名,在构建和安装的过程中会以代码包的名称为准。

在Go语言中,代码包中的源码文件名可以是任意的。这些任意名称的源码文件都必须以包声明语句作为文件中的第一行,每个包都对应一个独立的名字空间。

包中成员以名称首字母大小写决定访问权限:

  • public:首字母大写,可被包外访问
  • private:首字母小写,仅包内成员可以访问

【注意】同一个目录下不能定义不同的package。

8.3 包的导入

在Go语言程序中,每个包都有一个全局唯一的导入路径。

8.3.1 导入声明

导入包需要使用关键字import,它会告诉编译器你想引用该位置的包中的代码,包的路径可以是相对路径,也可以是绝对路径。

// 声明方式一
import "fmt"
import "time"
// 声明方式二
import (
 "fmt"
 "time"
)

如上所示的标准包会在Go语言的安装位置下的src目录中找到,而其他包都需要在GOPATH环境变量中的目录下寻找,GOPATH指定的这些目录就是开发者的个人工作空间。

如果在GOPATH中仍然没有找到所需的包,编译器在编译或运行时就会报错。

8.3.2 远程导入

Go语言不仅支持调用本地包,还支持调用远程服务器的包,例如托管在GitHub上的一个非常热门的Web框架gin,可以通过远程导入的方式将其导入使用。

使用go get 命令下载远程包

package main

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

func main() {
   r := gin.Default()
   r.GET("/ping", func(c *gin.Context) {
      c.JSON(200, gin.H{
         "message": "pong",
      })
   })
   r.Run()
}

成功返回

说明有人请求了服务

8.3.3 别名导入

在导入包时,可以指定包成员的访问方式,例如对包进行重命名,也就是使用别名的方式,避免导入两个相同包名的不同包而发生冲突。

import print "fmt"
package main

import (
   print "fmt"
   date "time"
)

func main() {
   print.Println("当前日期为:", date.Now().Day())
}

8.3.4 匿名导入

在Go语言中,如果导入了一个包而不使用,在编译时会产生“unused import”的编译错误。有时可能需要导入一个包,但不会引用到这个包的标识符,在这种情况下可以使用包的匿名导入的方式,就是使用下划线“_”来重命名该包

import _“fmt”

性能分析案例

package main

import (
   "net/http"
   _ "net/http/pprof"
)

func ping(writer http.ResponseWriter, request *http.Request) {
   writer.Write([]byte("{"message":"pong"}"))
}

func main() {
   http.HandleFunc("/ping", ping)
   http.ListenAndServe(":8080", nil)
}

8.4 main包

在Go语言中,命名为main的包具有特殊的含义。Go语言的编译程序会试图把这种名字的包编译为二进制可执行文件。所有用Go语言编译的可执行程序都必须有一个名叫main的包,main包有且仅有一个。

当编译器发现某个包的名字为main时,它一定也会发现名为main()的函数,否则不会创建可执行文件。main()函数是程序的入口,所以,如果没有这个函数,程序就没有办法开始执行。程序编译时,会使用声明main包的代码所在的目录名称作为可执行文件的文件名。

一个应用程序可以包含不同的包,而且即使你只使用main包也不必把所有的代码都写在一个巨大的文件里,你可以用一些较小的文件,并且在每个文件非注释的第一行都使用package main来指明这些文件都属于main包。如果你打算编译包名不为main的源文件,如mypack,编译后产生的对象文件将会是mypack.a而不是可执行程序。

注意,所有的包名都应该使用小写字母。

8.5 包的初始化

在Go语言里面有两个保留的函数:init函数(能够应用于所有的package)和main函数(只能应用于package main)。这两个函数在定义时不能有任何的参数和返回值。

建议用户在一个package中,每个文件只写一个init函数。

每个package中的init函数都是可选的,但package main就必须包含一个main函数。

每个包可以包含任意多个init(),这些函数都会在程序执行开始的时候被调用。所有被编译器发现的init()都会安排在main()之前执行。init()用于设置包、初始化变量或者其他要在程序运行前优先完成的引导工作。

程序的初始化和执行都起始于main包。如果main包还导入了其他的包,那么就会在编译时将它们依次导入。

当一个包被导入时,如果该包还导入了其他的包,那么会先将其他的包导入进来,然后再对该包的包级常量和变量进行初始化,最后执行init函数(如果存在)。

8.6 包的命名

每个包都有一个包名,包名一般是短小的名字,在包的声明处指定。通常来说,默认的包名就是包导入路径名的最后一段,因此即使两个包的导入路径不同,它们依然可能有一个相同的包名。

包的命名规则:

  • 同目录下的源码文件的代码包声明语句要一致。
  • 源码文件声明的代码包的名称可以与其所在的目录的名称不同。
8.7 依赖包管理

Go在1.5版本引入了vendor属性(默认关闭,需要设置Go环境变量GO15VENDOREXPERIMENT=1),并在1.6版本中默认开启了vendor属性。

vendor属性就是让Go在编译时,优先从项目源码树根目录下的vendor目录查找代码(可以理解为GOPATH),如果vendor中有,则不再去GOPATH中查找。

有时候依赖包多了,逐个拷贝是非常费时费力的,因此在Go 1.11之后,官方发布了支持的版本管理工具mod。使用go mod命令即可运行mod工具。

mod命令:

download下载依赖的module到本地cache
edit编辑go.mod文件
graph打印模块依赖图
init在当前文件夹下初始化一个新的module,创建go.mod文件
tidy增加丢失的module,去掉未用的module
vendor将依赖复制到vendor下
verify校验依赖
why解释为什么需要依赖

当需要将所有外部依赖拷贝到vendor目录下时,只需要运行一条命令:

go mod vendor
8.8 Go语言命名规范 8.8.1 驼峰式命名法

Go语言中,我们推荐使用驼峰式命名法来对各类标识符(变量、常量和结构体等)和文件进行命名。

  • 小驼峰命名法

    第一个单词以小写字母开始,其他单词的首字母则需要大写

    var sumNum int
    var firstName string
    var isValid bool
    var printValue func()
    
  • 大驼峰命名法

    每一个单词的首字母都采用大写

    var SumNum int
    var FirstName string
    var IsValid bool
    var PrintValue func()
    

在进行测试用例的编写时,文件的命名不遵循驼峰式命名法,而是以xx_test.go的格式进行命名。

测试文件scan_test.go中的TestScan函数。

8.8.2 导出标识符

Go语言中标识符根据首字母的大小写来确定可以访问的权限。

如果首字母大写,则表示可以被其他包中的代码访问(可被导出);如果首字母小写,则表示该标识符只能在本包中使用(不可导出)。

通俗认识:首字母大写的标识符是公有的,首字母小写的标识符是私有的。

8.10 知识拓展(标准包简介) 8.10.1 unsafe

unsafe包含了一些打破Go语言“类型安全”的命令,一般的程序不会使用它,可用于C/C++ 程序的调用中。

8.10.2 os-os/exec-syscall

os:提供一个平台无关性的操作系统功能接口,采用类Unix设计,隐藏了不同操作系统间的差异,让不同的文件系统和操作系统对象表现一致。
os/exec:提供给我们运行外部操作系统命令和程序的方式。
syscall:底层的外部包,提供了操作系统底层调用的基本接口。

8.10.3 archive/tar和/zip-compress

压缩(解压缩)文件功能。

8.10.4 fmt-io-bufio-path/filepath-flag

fmt:提供了格式化输入输出功能。
io:提供了基本输入输出功能,大多数是围绕系统功能的封装。
bufio:缓冲输入输出功能的封装。
path/filepath:用来操作在当前系统中的目标文件名路径。
flag:对命令行参数的操作。

8.10.5 strings-strconv-unicode-regexp-bytes

strings:提供对字符串的操作。
strconv:提供将字符串转换为基础类型的功能。

unicode:为unicode型的字符串提供特殊的功能。
regexp:正则表达式功能。
bytes:提供对字符型分片的操作。

8.10.6 math-math/cmath-math/rand-sort-math/big

math:基本的数学函数。
math/cmath:对复数的操作。
math/rand:伪随机数生成。
sort:为数组排序和自定义集合。
math/big:大数的实现和计算。

8.10.7 container-/list-ring-heap

实现对集合的操作。
list:双链表。
ring:环形链表。

8.10.8 time-log

time:日期和时间的基本操作。
log:记录程序运行时产生的日志。

8.10.9 encoding/Json-encoding/xml-text/template

encoding/Json:读取并解码和写入并编码JSON数据。
encoding/xml:简单的XML 1.0解析器。
text/template:生成像HTML一样的数据与文本混合的数据驱动模板。

8.10.10 net-net/http-html

net:网络数据的基本操作。
http:提供了一个可扩展的HTTP服务器和客户端,解析HTTP请求和回复。
html:HTML5解析器。

8.10.11 runtime

Go程序运行时的交互操作,例如垃圾回收和协程创建。

8.10.12 reflect

实现通过程序运行时反射,让程序操作任意类型的变量。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1022372.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号