前言

无论什么Python还是Golang当你的代码量达到一定程度时,就需要使用package来分类、组织我们的代码文件。

 

一、Package概念

包在项目开发过程中组织代码的1种方式。

包是多个Go文件的集合,是一种高级的代码复用方案,Go语言为我们提供了很多内置包,如fmtosio等。

在目前我使用的go1.11.5中每1个.go文件都需要存放在Gopath路径下的1个文件中(包)。

package main

 .go文件最开始声明这是1个main包,也就是程序的入口。

 

1.初识 go-package

在go语言中1个文件夹可以称为1个包,在文件夹(包)可以创建多个.go文件。

在同1个文件夹(包)中的.go文件必须pakage关键字指定同1个包名。

在go语言中包分为2类

1.main包:使用main包可以让我们写的程序编译成1个可执行的二进制文件,所以main包就是程序的入口。

2.非main包:可以规范和分类我们在程序执行时所需要的功能

如果多个.go文件在同1个文件夹(包)中,那它们就可以直接使用相互的功能,无需导入包。 

在包同定义的功能首字母大写,才可以被外部包所调用,否则只能在同1个包中使用。

 

 

2.使用package

2.1定义package

一般来说除了1个程序入口(main包)之外,在Go项目中其他都是我们程序开发人员自由定义的(工具包),以便调用。

mai包可以生成1个可执行文件。

我们使用package关键字定义1个包

如果当前package想要被其他包调用,那么该工具包中的标识符(变量名、函数名、struct名、interface名)首字母大写表示可见性(对外可见)。

 

 在Go中1个文件夹就是1个package, 所以package中的.go文件一般会和package同名。  

 programmer.go

package devlepment

import "fmt"

//Programer 大写才能被外部其他包调用
func Programer(name string) {
	fmt.Printf(`
		I'm %s  a programmer work in devlepment department
		I interest in programing.in my free time I like seing some Science fiction films ranther than porn.
		`, name)
}

 

2.2.init函数

包中的init函数在调用该包时自动执行

package resources

import "fmt"

//init:导入包时自动执行
func init(){
	fmt.Println("导入resources包时自动执行")
	receptionist("May")
}

func receptionist(nam string){
	fmt.Println(`Good morning.may I help you? `)
}

2.3.init()函数执行顺序

Go语言包会从main包开始检查其导入的所有包,每个包中又可能导入了其他的包。Go编译器由此构建出一个树状的包引用关系,再根据引用顺序决定编译顺序,依次编译这些包的代码。

Golang中1个包可以包含1个init函数,不一样的是这个init函数需要自己定义

调用包时会最先初始化并调用包中mian函数的init()函数, 如下图示:

2.4.导入package

调用Go里面的包需要从Go project的src目录后面的文件夹开始import。

 

 hello/package_practice/devlepment

package main

import (
	//匿名调用包:只调用执行包中init函数中的代码,不使用(pymysql)
	_ "hello/package_practice/resources"
	//别名:包所在的路径
	devlepment "hello/package_practice/devlepment"
	sales "hello/package_practice/sales"
	finnace "hello/package_practice/finance"

)

func main(){
	devlepment.Programer("Sam")
	finnace.Contant("Sally")
	sales.Salesman("Todd")
	
	
	
}

 

二、第3方依赖包下载

以上是Golang管理依赖包的机制,那怎么下载第三方依赖包呢?

不同于Python和Node在Go种没有1个中心化管理第3方依赖的源,都是去github下载。

在项目中执行go get根据go.mod中指定的依赖包进行下载(相当于pip install ),并且还可以指定下载的版本。

  1. 运行go get -u将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
  2. 运行go get -u=patch将会升级到最新的修订版本
  3. 运行go get package@version将会升级到指定的版本号version

下载所有依赖可以使用go mod download命令。

 

二、第3方依赖包管理 

Golang源自于谷歌内部,由于是最初是内部开发,根本没有第三方依赖包管理机制;

所以一直再不断完善。

Golang项目依赖的第3方依赖包,默认情况下全部放存储go path/src目录下。

1.Gopath

Gopath是存储Go第3方依赖包的路径(相当于Python的sitepackage目录)

之前需要手动配置GoPath,Golang1.8及之后的版本自动设置GOPATH=$HOME/go 

2.Vender机制

Go1.5版本之后开始支持,能够控制Go语言程序编译时依赖包搜索路径的优先级。

如果项目require某个依赖包,如果你有vendor目录。

首先会在项目根目录下的vender文件夹中查找,如果没有找到再去$GOAPTH/src目录下查找

3.Go mod

Golang 1.12 有了 Go Modules 后,可以把Go 项目放在任何地方。

Go modGo1.11版本之后官方推出的版本管理工具, G01.12功能基本稳定。

Go1.13版本开始,go module将是Go语言默认的依赖管理工具。

D:\goproject\src>go env
set GO111MODULE=on
set GOPROXY=https://goproxy.cn

3.1.go mod命令

我们使用go mod无非处于2种目的

目的1.我自己开发的项目生成go.mod让别人同步我的依赖包

目的2.别人写得项目,我跟他的依赖包版本保持一致。

go get     从github或者指定代理下载第三方依赖---->本地cache(默认为$GOPATH/pkg/mod目录)
go mod download   根据gomod文件下载指定版本的依赖包    
go mod edit        编辑go.mod文件
go mod graph       打印模块依赖图
go mod init        初始化当前文件夹, 创建go.mod文件
go mod tidy        整理go.mod中依赖(增加缺少的module,删除无用的module)校验go mod中设置的版本和D:\goproject\pkg\mod中的版本是否一致!
go mod vendor      需要在离线环境开发、编译时,将第3方依赖包复制到当前项目vendor目录下。
go mod verify      校验依赖
go mod why         解释为什么需要依赖

自己生成go.mod流程

D:\goproject\src\go相关模块\kafka>SET GO111MODULE=on

D:\goproject\src\go相关模块\kafka>SET GOPROXY=https://goproxy.cn

D:\goproject\src\go相关模块\kafka>go mod init
go: creating new go.mod: module go相关模块/kafka

D:\goproject\src\go相关模块\kafka>go mod download
go: finding github.com/Shopify/sarama v1.19.0

go.mod文件语法

go.mod文件记录了项目所有的依赖信息,其结构大致如下:

module jd.com/logagent //当前包名

go 1.13   //go版本

require ( //在这里指定第三方依赖库的版本信息
	github.com/Shopify/sarama v1.19.0  
	github.com/davecgh/go-spew v1.1.1 // indirect 
	github.com/eapache/go-resiliency v1.2.0 // indirect
	github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
	github.com/eapache/queue v1.1.0 // indirect
	github.com/golang/snappy v0.0.1 // indirect
	github.com/hpcloud/tail v1.0.0
	github.com/pierrec/lz4 v2.5.2+incompatible // indirect
	github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
	gopkg.in/fsnotify.v1 v1.4.7 // indirect
	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
)

replace语法

在国内访问golang.org/x的各个包都需要FQ,你可以在go.mod中使用replace替换成github上对应的库。

replace (
	golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac => github.com/golang/crypto v0.0.0-20180820150726-614d502a4dac
	golang.org/x/net v0.0.0-20180821023952-922f4815f713 => github.com/golang/net v0.0.0-20180826012351-8a410e7b638d
	golang.org/x/text v0.3.0 => github.com/golang/text v0.3.0
)
go.sum作用

为了确保一致性构建,Go引入了go.mod文件来标记每个依赖包的版本,在构建过程中go命令会下载go.mod中的依赖包,下载的依赖包会缓存在本地,以便下次构建。

考虑到下载的依赖包有可能是被黑客恶意篡改的,以及缓存在本地的依赖包也有被篡改的可能,单单一个go.mod文件并不能保证一致性构建。

为了解决Go module的这一安全隐患,Go开发团队在引入go.mod的同时也引入了go.sum文件,用于记录每个依赖包的哈希值。

在构建时,如果本地的依赖包hash值与go.sum中记录的hash值不一致,则会拒绝构建。

4.离线安装Go依赖包

在离线环境开发时除了使用内网Goporxy代理,还可以采用以下方式解决Go依赖包下载问题。

4.1下载go项目的依赖包

导出项目需要的go.mod文件,放到联通外网环境的机器上。

外网机器配置GOMODCACHE

go env -w GOMODCACHE="C:\your\path\pkg\mod"

在go.mod所在的文件夹下,执行

go mod download

这样go.mod里的依赖包将会下载到$GOMODCACHE下缓存起来,以便于后期Go编译器进行项目的编译构建。

打包$GOMODCACHE/cache/download文件夹,生成download.zip包。使用文件摆渡传到离线云桌面。

4.2.搭建内网环境文件服务器

download.zip文件导入服务器中,放到/export/package/go_download下。

登录服务器(例1.1.1.1),启动文件服务器

cd /export/package/go_download
python3 -m http.server 8010

4.3.离线云桌面

需要下载go依赖包的项目设置GOPROXY=http://1.1.1.1:8010

go env -w GOPROXY=http://1.1.1.1:8010

开始从内网文件服务器下载go依赖包

设置GoRoot
export GOOROOT=/usr/local/go
整理项目中包含的go.mod文件
/usr/local/go/bin/go mod tidy
根据go.mod中指定的依赖包版本,从内网文件服务器下载go依赖包
/usr/local/go/bin/go mod download

5.Goland/Pycharm离线环境下安装插件

在离线环境下使用Goland、Pycharm连接数据库,需要下载各种数据库的drivers,这些drivers保存在本机的如下目录下

C:\Users\GIENTECH\AppData\Roaming\JetBrains

 

 

 

 

 

参考

posted on 2020-04-14 08:26  Martin8866  阅读(1280)  评论(0编辑  收藏  举报