返回

Go学习笔记01-Go项目的创建与运行

从零开始学习Golang语言

写在前面

开一个新坑:从零开始学习Golang语言,使用的IDE是Goland。在本系列中,博主将持续发布自己学习golang的笔记。由于博主也是零基础学习golang语言,文中如有不对之处,还望不吝赐教。随着学习的深入,博主也会不断回顾之前的文章,不断更正自己的笔记,希望我们能够一起进步。💪

Go语言背景

Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算

Go语言相关学习网站:

搭建开发环境

安装Golang

Go官网下载安装包:

下载Go安装包

下载好了安装包,点击启动执行,接下来的步骤就是按导航提示一步步操作即可。有一点要注意的是,GO默认安装在C:\GO,如果要修改默认安装路径,在见到如下界面时重新选择。

我将其安装在了D:\Program Files\Go\,这个路径就是后面提到的GOROOT路径(重要),选好之后点Next

最后点Finish,这样,Go语言开发环境就安装完成了。

配置环境变量

在安装完golang后,还需了解三个环境变量,分别是GOROOTGOPATHPATH。下面来分别介绍一下它们的作用

  • GOROOT:GO安装的根目录。
  • PATH:各个操作系统都存在的环境变量,用于指定系统可执行命令的默认查找路径。
  • GOPATH:用来设置工作目录,即编写代码的地方。包也都是从GOPATH设置的路径中寻找。

配置系统变量GOROOT,变量名为GO_HOME,变量值为之前填入的安装路径,我的为D:\Program Files\Go\

配置系统变量Path,添加环境变量,值为之前填入的安装路径中的二进制bin文件夹,我的为D:\Program Files\Go\bin

配置用户变量GOPATH,变量名为GOPATH,变量值可以暂时设置为任意目录,我设置的为D:\Code\go,因为后面我们使用Goland这个IDE来创建项目,为了使每个项目相互隔离,使用不同的包,我们需要为每个项目设置不同的工作目录。

这个时候,打开cmd,输入 go versioin就会出来当前安装的Go语言环境版本。我安装的版本为go1.17.6

到此,Go语言环境就安装完成了🎉

Goland创建项目并运行

Goland下载地址,按照引导安装非常简单,不做赘述。

安装完成后点New Project,创建新项目

配置项目地址,我这里设置为D:\Code\GolandProjects\TestProject

配置代理,我这里设置为GOPROXY=https://goproxy.cnGOPROXY 是Go语言官方提供的一种通过中间代理商来为用户提供包下载服务的方式。

配置GOPATH,设置为之前填写的项目地址,取消索引整个GOPATH

接下来,我们配置一下项目的目录结构:新建三个文件夹binpkgsrc,创建go.mod包管理文件

  • bin文件目录:用于存放编译生成的可执行文件.exe
  • src文件目录:用于存放源代码
  • pkg文件目录:存放依赖包
  • go.mod包管理文件就放在src下面就行。

之后,我们设置本项目GOPATHModule GOPATH路径为刚才创建的文件目录。

GoLand中,选择File→Settings,打开设置

  • Project GOPATHsrc文件目录,存放源码
  • Module GOPATH为项目目录
  • 取消使用系统环境定义的GOPATH

来到GO Modules设置

  • 选中使用GO包整合
  • 配置包的代理下载地址

配置运行方式

这个时候,基本设置好了,下面开始经典的HelloWorld程序编写

src目录下新建一个main包,在main包新建一个名为HelloWorld的go程序

打印HelloWorld,我们用Go自带的打印方法打印,输入:

1
fmt.Println("HelloWorld~")

这时系统会自动识别并引入包所在的目录import "fmt",因为这个是Go自带的SDK里的方法。可以自己识别到并自动添加,后面自己引用第三方的包也一样。这里也强调一点,引入的是这个包所在的目录,在你用的时候才是包名。

最后,构建一个Run/Debug Configuration

GoLand中,运行Go有三种方式:

  • 文件方式运行(File)
  • 以包的方式运行(Package)
  • 以整个目录的方式运行(Directory)

以文件方式运行

以单个文件的方式运行,最为简单,直接可以右击要运行的文件,选择Run,则可以直接运行程序,编译生成的可执行文件位于用户目录C:\Users\username\AppData\Local\Temp\GoLand\下,并不在bin文件中

右击文件运行后,GoLand新建了一个默认的运行配置文件。在右上方,可以看到配置运行方式的地方,如果之前没有任何配置的话,会提示你Add Configurations,如果之前有过配置,会出现下拉框让你选择配置或者Edit Configurations

这是以文件方式运行go文件的默认运行配置

设置Output directory为当前项目的bin文件目录,我这里设置为D:\Code\GolandProjects\TestProject\bin后,执行,可以看到bin文件目录中生成可执行文件:

从下方窗口也可以看到输出路径和运行结果:

以包方式运行

Run kind选择Package

Package path输入main函数所在的包名,其他保持不变,这样就以包的方式去运行和调试了

以整个目录的方式运行

Run kind选择DirectoryDirectory输入main函数所在的目录,其他保持不变,则以包的方式去运行和调试。

不管以什么方式运行,运行的入口,即main方法的所属包名必须是package main

1
2
3
4
5
6
7
package main

import "fmt"

func main() {
	fmt.Println("HelloWorld~")
}

引入第三方包

go.mod文件中加入第三方包的名称和版本,这时,Goland就会在网上把包下载下来,保存在一开始我们设置的Module GOPATH路径下pkg文件夹下。

1
2
3
4
5
6
7
module TestProject

go 1.17

require (
	github.com/go-ole/go-ole v1.2.4
)

这个时候,我们只是下载了第三方包,还没有去引用它,所以还没有在External Libraries中有所体现。

接下来我们在程序中引用包,import后,会发现goland识别不了,这时我们把光标移动到红色位置,然后同时按下Alt+EnterGoland会智能提示需要同步包,我们点同步

同步好后,会发现左边的pkg文件目录下出现了我们导入的第三方包go-oleExternal Libraries中也识别出了这个包。这个时候我们就可以在程序中使用了,如下图:

到这里,我们就可以成功配置并运行一个GO项目了!🎉🎉🎉

导入本地包

2023.9.29补充

只用在项目src目录下建一个go.mod即可,不用在每个包下建立go.mod(弃用之前2023.8.19的方法)

使用时通过包名/函数名or变量名即可,使用Goland的话包会自动导入

注意:

  • 导入包被外部包调用的变量名或函数名首字母要大写
  • 避免包循环导入:明确业务层、工具类等包的规划

2023.8.19补充

在要被导入的本地包路径下执行:

1
go mod init 包名

在要使用该包的包路径下的go.mod文件中添加

1
2
3
4
5
require (
	...
	包名 v0.0.0
)
replace 包名 => ../包名 //dir修改为包所在的相对路径。如:“../dir”

在要使用该包的go文件中

1
2
3
4
5
6
7
import (
	...
	"包名"
)
func main(){
    包名.函数()//函数s
}

注意:避免包之间互相依赖,如果检测到import cycle会在编译时报错import cycle not allowed

例如:

Package A depends on Package B Package B depends on Package A

mutex死锁一样,陷入了死循环

万事开头难,希望我们能坚持学习💪

GOPATH和GoModule区别

Go 语言的的包依赖管理从最初的 GOPATHGO VENDOR,再到最新的 GO Modules。目前最主流的包依赖管理方式是使用官方推荐的 Go Modules ,在版本 Go 1.14 发布后,官方强烈推荐使用 Go Modules进行包依赖管理。

GOPATH

可以将GOPATH理解为工作目录,在这个工作目录下,通常有如下的目录结构

bin:存放编译后生成的二进制可执行文件

pkg:存放编译后生成的 .a 文件

src:存放项目的源代码和下载的包,将包全部放在 $GOPATH/src 目录下进行管理的方式,我们称之为GOPATH模式

在这个模式下,使用 go install 时,生成的可执行文件会放在 $GOPATH/bin 下。

如果你安装的是一个库,则会生成 .a 文件到 $GOPATH/pkg 下对应的平台目录中(由 GOOSGOARCH 组合而成)。

  • GOOS:表示目标操作系统,有 darwin(Mac)linuxwindowsandroidnetbsdopenbsdsolarisplan9
  • GOARCH,表示目标架构,常见的有 armamd64
  • 这两个都是 go env 里的变量,可以通过 go env 变量名 进行查看

使用 GOPATH 模式进行包依赖管理的缺点:

  • 无法在项目中,使用指定版本的包。因为不同版本包的导入方法都一样。
  • 其他人运行你的开发的程序时,无法保证他下载的包版本是你所期望的版本。当对方使用了其他版本,有可能导致程序无法正常运行。
  • 在本地,一个包只能保留一个版本。这意味着:在本地开发的所有项目,都得用同一个版本的包,这几乎是不可能的。

GoVendor

为了解决 GOPATH 方案下不同项目下无法使用多个版本库的问题,Go v1.5 开始支持vendor

以前使用 GOPATH 的时候,所有的项目都共享一个 GOPATH,需要导入依赖的时候,都来这里找。

解决的思路就是,在每个项目下都创建一个 vendor 目录,每个项目所需的依赖都只会下载到自己vendor目录下,项目之间的依赖包互不影响。

在编译时,Go v1.5 在你设置了开启 GO15VENDOREXPERIMENT=1 (注:这个变量在 v1.6 版本默认为1,但是在 v1.7 后,已去掉该环境变量,默认开启 vendor 特性,无需你手动设置)后,会提升 vendor 目录的依赖包搜索路径的优先级(相较于 GOPATH)。

其搜索包的优先级顺序,由高到低是这样的

  • 当前包下的 vendor 目录
  • 向上级目录查找,直到找到 src 下的 vendor 目录
  • GOROOT 目录下查找
  • GOPATH 下面查找依赖包

虽然这个方案解决了一些问题,但是解决得并不完美。

如果多个项目用到了同一个包的同一个版本,这个包会存在于该机器上的不同目录下,不仅对磁盘空间是一种浪费,而且没法对第三方包进行集中式的管理(分散在各个角落)。

并且如果要分享开源你的项目,你需要将你的所有的依赖包悉数上传,别人使用的时候,除了你的项目源码外,还有所有的依赖包全部下载下来,才能保证别人使用的时候,不会因为版本问题导致项目不能如你预期那样正常运行。

GoModule

go modulesv1.11 版本正式推出,从 v1.11 开始,go env 多了一个环境变量: GO111MODULE

它有三个可选值:offonauto,默认值是auto

GO111MODULE=off禁用模块支持,编译时会从GOPATHvendor文件夹中查找包。

GO111MODULE=on启用模块支持,编译时会忽略GOPATHvendor文件夹,只根据 go.mod下载依赖。

GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,自动开启模块支持。

在使用go modules模式后,项目目录下会多生成两个文件也就是 go.modgo.sum 。这两个文件是 go modules 的核心。

go.mod

  • go mod 不再依靠GOPATH,使得它可以脱离 GOPATH 来创建项目
  • 对项目进行 go modules 的初始化
  • 第一行:模块的引用路径
  • 第二行:项目使用的 go 版本
  • 第三行:项目所需的直接依赖包及其版本

在实际应用上,你会看见更复杂的 go.mod 文件,比如下面这样

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
module TestProject
go 1.17
require (
    example.com/apple v0.1.2
    example.com/banana v1.2.3
)

exclude example.com/banana v1.2.4

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

主要是多出了两个 flag:

  • exclude: 忽略指定版本的依赖包
  • replace:由于在国内访问golang.org的各个包比较慢,所以在go.mod中使用replacegolang.org替换成github.com上对应的库。

go.sum

每一行都是由模块路径,模块版本,哈希检验值组成,其中哈希检验值是用来保证当前缓存的模块不会被篡改。hash 是以h1:开头的字符串,表示生成checksum的算法是第一版的hash算法(sha256)。

go.modgo.sumgo modules 版本管理的指导性文件,因此 go.modgo.sum 文件都应该提交到你的 Git 仓库中去,避免其他人使用你写项目时,重新生成的go.modgo.sum 与你开发的基准版本的不一致。

综上,GOPATHGoModule的区别是:

GOPATH模式 GoModule模式
GOPATH环境变量 必须设置 可设置可不设置
$GOPATH/pkg文件目录 存放.a文件 $GOPATH/pkg目录存放依赖包
$GOPATH/src文件目录 存放源码和依赖包 存放源码
对依赖包的版本控制 无法对依赖包作版本控制 可以对依赖包作版本控制

Go的根目录结构

简单介绍下go的目录结构。以windows为例,进入D:\Program Files\go将看到如下内容

介绍几个比较主要的目录:

  • api,里面包含所有API列表,IDE使用了里面的信息;
  • bin,里面是一些go的工具命令,主要是gogofmtgodoc
  • doc,go的使用文档,可以让我们在没有网络的情况下也可以阅读;
  • src,主要是一些源码,如golang的编译器、各种工具集以及标准库的源码。

参考资料

Built with Hugo
Theme Stack designed by Jimmy