1Go语言之包与gomod

Posted 行走的皮卡丘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1Go语言之包与gomod相关的知识,希望对你有一定的参考价值。

1、Go语言之包与gomod

1、包的使用

1.1 package与import

在实际的开发中,我们往往需要在不同的文件中,去调用其它文件的定义的函数,比如 main.go 中,需要使用"fmt"包中的Println()函数:

package main
import "fmt"

在Go中,Go的每一个文件都属于一个包,也就是说Go是以包的形式来管理文件和项目目录结构。

如果要导入某些第三方包,直接输入包所在地址即可。文件的包名通常和文件所在的文件夹名一致,一般为小写字母。

- package 指令在 文件第一行,然后是import指令

  • import包时,路径从$GOPATH 的 src下开始,不用带 src , 编译器会自动从 src 下开始引入
  • 为了让其它包的文件,可以访问到本包的函数,则该函数名的首字母需要大写,类似其它语言 的 public ,这样才能跨包访问
  • 在访问其它包函数,变量时,其语法是 包名.函数名

导入包有两种书写方式:

  • import "myproject/lib": mypeoject是项目文件夹名,这里类似于绝对路径的写法
  • import "./lib":相对路径方式

多个包导入可以使用:

import (
	"包名"
	"包名" 
)

1.2 GOPATH

GOPATHGROOT

GOROOT: Go的安装目录,比如c:/Go
GOPATH: Go的项目目录

GoPath目录用来存放代码文件、可运行文件、编译后的包文件。 1.1-1.7版本必须设置,而且不能和Go的安装目录一样,1.8版本后会有默认值:

Unix:$HOME/go
Windows:%USERPROFILE%/go。

GOPATH允许多个目录,多个目录的时候Windows是分号,Linux系统是冒号隔开。当有多个GOPATH时,默认会将go get的内容放在第一个目录下,$GOPATH 目录约定有三个子目录:

  • src:存放源代码,一般一个项目分配一个子目录;
  • pkg:编译后生成的文件,如.a文件
  • bin:编译后生成的可执行文件,可以加入$PATH

注意:一般建议package的名称和目录名保持一致

1.3 包中的函数调用方式

函数调用的方式

  • 同包下:直接调用即可
  • 不同包下:包名.函数名

注意:Go中,大写字母开头的变量是可导出的,也就是其它包可以读取的,是公有变量;小写字母开头的就是不可导出的,是私有变量。

1.4 init函数 与 _

init()函数在包加载时就会默认最先调用,用来对包中的一些属性进行初始化操作:

package util

import "fmt"

func init()
	fmt.Println("初始化操作...")

有些情况下,我们在加载包时,并不是要使用包内的函数,而是想调用其初始化方法,可以这样引入包:

import _ "package1"

一个go包可以拥有读个init函数,会按照包中不同文件名顺序、同文件名中init函数前后顺序依次调用。

1.5 点操作

点语法在使用包调用函数时,可以省略包名:

import . "fmt"

Println("无需包名即可调用...")

不推荐该使用方式。

1.6 包别名

import p1 "package1"		// 此时包 package1 可以在代码中使用 p1 代替	

2、包的管理

go有很多优秀的第三方包,可以使用 go get 包地址来下载,下载的包会默认安装在Gopath目录中的src文件夹中。

Gopath支持多个目录,go get默认都会将包下载到配置的第一个Gopath中。

3、go mod

go的项目依赖管理一直饱受诟病,在go1.11后正式引入了go modules功能,在go1.13版本中将会默认启用。从此可以不再依赖gopath,摆脱gopath的噩梦。

go mod 初步使用:

# 开启go mod
export GO111MODULE=on

# 在新建的项目根目录下(src)下使用该命令
go mod init 项目名                      # 此时会生成一个go.mod文件

# 使用
# 在项目中可以随时import依赖,当 go run 时候,会自动安装依赖,比如:
import (
	"github.com/gin-gonic/gin"
)

go run 后的 go.mod:

module api_server

go 1.12

require (
	github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 // indirect
	github.com/gin-gonic/gin v1.3.0 // indirect
	github.com/golang/protobuf v1.3.1 // indirect
	github.com/mattn/go-isatty v0.0.7 // indirect
	github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 // indirect
	gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
	gopkg.in/yaml.v2 v2.2.2 // indirect
)

使用go mod后,run产生的依赖源码不会安装在当前项目中,而是安装在:$GOPATH/pkg/mod

贴士:如果我们安装的是go1.11以上版本,且想要开启go mod,那么可以给go配置环境如下:

export GOROOT=/usr/local/go                 # golang本身的安装位置
export GOPATH=~/go/                         # golang包的本地安装位置
export GOPROXY=https://goproxy.io           # golang包的下载代理
export GO111MODULE=on                       # 开启go mod模式
export PATH=$PATH:$GOROOT/bin               # go本身二进制文件的环境变量
export PATH=$PATH:$GOPATH/bin               # go第三方二进制文件的环境便令

注意:使用了go mod后,go get安装的包不再位于$GOPATHA/src 而是位于 $GOPATH/pkg/mod

4、网络下载问题解决

4.1 推荐方式 GOPROXY

从 Go 1.11 版本开始,还新增了 GOPROXY 环境变量,如果设置了该变量,下载源代码时将会通过这个环境变量设置的代理地址,而不再是以前的直接从代码库下载。goproxy.io 这个开源项目帮我们实现好了我们想要的。该项目允许开发者一键构建自己的 GOPROXY 代理服务。同时,也提供了公用的代理服务 https://goproxy.io,我们只需设置该环境变量即可正常下载被墙的源码包了:

开发时设置Goland的Prefrence-Go-proxy即可

linux开启代理

注意:必须开启go modules才能使用,也可以选择其他镜像,如阿里云

export GOPROXY=https://goproxy.io			

win开启代理

$env:GOPROXY = "https://goproxy.io"

关闭代理

export GOPROXY=

4.2 replace方式

go modules还提供了 replace,可以解决包的别名问题,也能替我们解决 golang.org/x 无法下载的的问题。

go module 被集成到原生的 go mod 命令中,但是如果你的代码库在 $GOPATH 中,module 功能是默认不会开启的,想要开启也非常简单,通过一个环境变量即可开启 export GO111MODULE=on。

module example.com/hello

require (
    golang.org/x/text v0.3.0
)

replace (
    golang.org/x/text => github.com/golang/text v0.3.0
)

4.3 手动下载 旧版go的解决

我们常见的 golang.org/x/… 包,一般在 GitHub 上都有官方的镜像仓库对应。比如 golang.org/x/text 对应 github.com/golang/text。所以,我们可以手动下载或 clone 对应的 GitHub 仓库到指定的目录下。

mkdir $GOPATH/src/golang.org/x
cd $GOPATH/src/golang.org/x
git clone git@github.com:golang/text.git
rm -rf text/.git

当如果需要指定版本的时候,该方法就无解了,因为 GitHub 上的镜像仓库多数都没有 tag。并且,手动嘛,程序员怎么能干呢,尤其是依赖的依赖,太多了。

5、go mod引起的变化

引包方式变化:

  • 不使用go mod 引包:“./test” 引入test文件夹
  • 使用go mod 引包:“projectmodlue/test” 使用go.mod中的modlue名/包名

因为在go1.11后如果开启了go mod,需要在src目录下存在go.mod文件,并书写主module名(一般为项目名),否则无法build。

开启go mod编译运行变化:

  • 使用vscode开发,必须在src目录下使用 go build命令执行,不要使用code runner插件
  • 使用IDEA开发,项目本身配置go.mod文件扔不能支持,开发工具本身也要开启go mod支持(位于配置的go设置中)

以上是关于1Go语言之包与gomod的主要内容,如果未能解决你的问题,请参考以下文章

1Go语言之包与gomod

go语言基础之包和自定义包与main包

Python基础之包与模块

面向对象之包

go之包引用、"实体类"的使用套路(struct)

1Go语言基础之变量和常量