系列文章目录
【Go语言从入门到精通系列-基础篇】Go安装 + 语言特性,以及开启你人生中的第一个go程序
【Go语言从入门到精通系列-基础篇】Go语言包的管理以及基础语法与使用。
Go语言从入门到精通系列-基础篇
- 系列文章目录
- 前言
- 第二章 Go语言包的管理以及基础语法与使用
- 1.1 Go基础程序的理解
- 1.1.1 包的声明
- 1.1.2 Go语言包所具有的特性
- 1.1.3 Go语言包的导入方式
- 1.1.4 Go的多包导入与起别名
- 1.1.5 main()函数讲解
- 1.2 Go语言包管理(Go Mod)
- 1.2.1 `GOPATH`和`GOROOT`
- 1.2.2 vendor 与 govendor
- 1.2.3 Go Mod
- 1.2.3.1 go mod命令说明
- 1.2.3.2 使用方法
- 1.3 Go 语言基础语法规则使用
- 1.3.1 基础语法
- 1.3.1.1 Go语言标记
- 1.3.1.2 行分隔符
- 1.3.1.3 注释
- 1.3.1.4 标识符
- 1.3.1.5 字符串连接
- 1.3.1.6 Go语言中的关键字
- 1.3.1.7 Go语言的空格
- 总结
前言
上一篇有学习到一个程序的输出,但是没有做详细的讲解,这一篇呢带大家共同学习Go 的基础语法,以及包管理的方式。
第二章 Go语言包的管理以及基础语法与使用
1.1 Go基础程序的理解
接上一章中我们一个程序可以看到,Go程序的结构非常简单,接下来我们对之前的代码进行简单的分析。
package main
import (
"fmt"
)
func main() {
fmt.Printf("Hello World!")
}
1.1.1 包的声明
Go语言是以 “包” 作为程序项目的管理单位。如果想要正常运行源文件,则必须先声明它所属的包。也就是每一个源文件的开头必须都是一个 package
声明,格式如下:
package ****
其中package
是声明包名的关键字
, ****表示包的名称。一般来讲Go的包与源文件所在文件夹有一一对应关系。
1.1.2 Go语言包所具有的特性
- 包名可以与其目录名不同。
- 一个目录下的同级文件属于同一个包。
- main 包是Go语言的应用程序入口包。一个Go的程序只允许且必须有一个main 包(如果没有main包,则编译会报错无法生成可执行文件)。
1.1.3 Go语言包的导入方式
也就是说在我们声明包之后,如果需要调用其他的包的方法变量,则需要使用import语句。import语句用于导入程序中所依赖的包,导入时包名必须使用双引号,格式如下:
import "packageName"
而在第一章中我们使用 import "fmt"
导入了fmt
包,这段代码会告诉编译器我们需要用到fmt
包中的函数或变量等。
- fmt: 它是Go语言为我们提供用于程序中的格式化输入与输出,方便我们的调试。
1.1.4 Go的多包导入与起别名
在我们实际的编写程序过程中肯定不止一个包,那么我们如何进行多包导入呢?可以使用import
关键字同时导入多个包,当然需要配合我们的英文括号()
将包的名称写入其中,并且每个包名独占一行,格式如下:
import (
"fmt"
"os"
)
也可以给导入的包名设置自定义别名,f 可以代替fmt
使用,o 代替 os
使用。格式如下:
import (
f "fmt"
o "os"
)
当然Go导包时需要注意检查,在程序中未使用且被导入时,编译器会报报错,无法进行编译。那么我能否只导入不使用它呢?答案是可以的,我们只需要使用 _
下划线来代替别名,编译器就允许我们只初始化这个包,而不使用包中的函数以及变量等。格式如下:
import (
f "fmt"
_ "os"
)
1.1.5 main()函数讲解
刚才也说了一个程序只能存在且必须要有一个main()
函数作为程序的入口函数,否则无法编译,并且main()
函数只能声明在main 包中 package main
,main()
函数是我们的自定义函数的一种,在Go中声明一个函数必须以 func
开头,格式定义如下:
func 函数名 (参数列表) (返回值列表) {
函数体
}
- func: 所有函数都必须以它开头。
- 函数名: 由
字母
下划线``数字
组成,其中名称开头不能数字开始,且同一个包内函数名称不能重复。 - 参数列表: 一个参数由参数变量名和参数类型组成,例如:
(name string, age int)
。 - 返回值列表: 可以是参数变量名与类型组成,也可以只是参数变量名称,而函数当有返回值时必须使用
return
语句进行参数返回。 - 函数体: 函数体是使用
{}
大括号括起来的,括号内编写我们函数的功能语句,它完成了一个函数的具体功能(注意: 左边{
括号必须与函数名保持在同一行,不然会报错)。
1.2 Go语言包管理(Go Mod)
1.2.1 GOPATH
和GOROOT
- GOROOT: 目的是为了告诉Go当前安装位置,编译时从GOROOT查找SDK的 system libariry(系统程序库),在windows使用更改环境变量方式进行自定义位置,Linux中使用export GOROOT=指定位置。
- GOPATH: 必须被设置,也可以自定义,目的是为了告诉Go在需要代码时去哪里查找。当然这里的代码包含本项目代码与引用外部项目的代码。
- GOPATH下有三个目录,上一章有提到过,分别是
src
bin
pkg
。
src目录: Go编译时查找代码的地方。
bin目录:Golang编译可执行文件存放路径。
pkg目录:编译生成的lib文件存储的地方。 - GOPATH下有三个目录,上一章有提到过,分别是
使用GOPATH问题的问题:
- 代码开发必须在go path src目录下,不然,就有问题。
- 依赖手动管理,依赖 ‘列表/关系’ 无法持久化到本地,需要找出所有依赖一个个获取。
- 依赖包没有版本可言,只能依赖全局仓库, 无法局部化分隔包管理。
1.2.2 vendor 与 govendor
Go在1.5版本引入了vendor 主要就是为了解决依赖GPATH解决go import
存在的问题, 而govendor是在vendor之后开发的,不做过多的讲解,想了解的可以自行百度,今天主要将go mod。
- govendor主要解决了包依赖,一个配置文件就能管理。
- 依赖包全都下载到项目vendor下,每个项目都把有一份,缺陷也及其明显了。
1.2.3 Go Mod
Go 版本在1.12之后能支持一个包的管理,不在依赖于GOPATH的设置,可以直接使用下载的包。
在我们使用go env
时,输出的第一位置参数GO111MODULE
它有三个值:off
on
auto (默认值)
。
-
GO111MODULE=off :Go命令行将不在支持module功能,寻找依赖的方式将沿用旧版本,及通过
vendor
与GOPATH
模式来查找。 -
GO111MODULE=on :Go命令行将使用modules,不会去GOPATH 目录下查寻。
-
GO111MODULE=auto:默认值,Go命令行将根据当前目录觉得是否启用module功能。
- 当前目录在GOPATH/src之外且该目录包含go.mod文件。
- 当前文件在包含go.mod文件的目录下。
当modules功能启用时,依赖包的存放位置变更为GOPATH/pkg
,允许同一个package多个版本并存,且多个项目可以共享缓存的 module。
1.2.3.1 go mod命令说明
go mod help
命令 | 详解 |
---|---|
download | 下载依赖包 |
edit | 编译go.mod |
graph | 打印模块依赖图 |
init | 在当前目录下初始化mod |
tidy | 拉去缺少的依赖,移除不需要的模块 |
vendor | 将依赖复制到vendor下 |
verify | 验证依赖是否正确 |
why | 解释为什么需要依赖 |
1.2.3.2 使用方法
新建一个工程为 test,使用 go mod init test
就会在当前目录下产生一个go.mod文件,一旦go.mod文件被创建,它的内容就会被go toolchain
全面掌控。也就是将当存在各类命令执行时,比如 go get
,go build
,go mod
等执行时,它会去维护或修改go.mod文件,而在我们的go mod 中我们的常用命令就只有几个 init
tidy
edit
。
而go mod
提供了四个参数释义:
- module 语句指定包的名字(路径)
- require 语句指定的依赖项模块
- replace 语句可以替换依赖项模块
- exclude 语句可以忽略依赖项模块
开启modules 的前置条件是, GO111MODULE
设置等于on
, 命令如下:
go env -w GO111MODULE=on
也就是将当我们设置好后,使用go run hello_world.go
运行代码时,如果缺少依赖包go mod
会自动查找依赖下载,再次执行时会跳过检查并安装依赖的步骤。可以使用go list -m -u all
来检查可以升级的package,使用 go get -u need-upgrade-package
来升级后将新的依赖更新到go mod
,也可以使用go get -u
升级所有依赖。
1.3 Go 语言基础语法规则使用
1.3.1 基础语法
1.3.1.1 Go语言标记
Go程序由 关键字
标识符
常量
字符串
符号
等多种标记组成。例如我们第一个程序中的 fmt.Println(“Hello World!”) 是由6中标记组成:
1.3.1.2 行分隔符
在Go语言程序中,一般来讲一行就是一个语句,不用像Java,PHP等其他的语言那样需要在一行结尾使用;
分号,因为这些工作都是由Go编译器自动完成,但是如果多个语句在同一行则必须使用;
分号将它们隔开,但是在实际的开发中不建议如此写法。例如:
fmt.Println("Hello World!")
fmt.Println("Hello Go!")
这则是两个语句,写在一行确实有些牵强了。
1.3.1.3 注释
在Go语言中,注释分为单行注释
与 多行注释
。
(1)单行注释 是以双斜线//
开头的。 可以在人格地方使用,格式如下:
// 输入语句
fmt.Println("Hello World!")
(2)多行注释 通常被称为块注释
, 是以 “/*”
开头,“*/”
结尾。格式如下:
/*
这里是多行注释
这里是多行注释
*/
fmt.Println("Hello World!")
1.3.1.4 标识符
标识符通常用来对变量,类型等程序实体进行命名。一个标识符实际上就是一个或者多个字母,数字, 下划线组成的字符串序列。格式如下:
name user age user_id _tmp name01 c ...
以上呢是正确的命名方式,之前讲到过错误的方式, 例如:
1_name back-name switch
也就是不能以数字开头,不能带其他符号,不能以关键字命名。
1.3.1.5 字符串连接
Go 语言的字符可以通过 +
加号的方式实现字符串连接,格式如下:
package main
import (
"fmt"
)
func main() {
str1 := "Hello"
str2 := " World!"
fmt.Printf(str1 + str2)
}
// 结果: Hello World!
1.3.1.6 Go语言中的关键字
上面讲了不能使用关键字命名,那么Go语言中有25个关键字或保留字,见下表:
关键字 | 释义 |
---|---|
continue | 跳过 |
for | 循环 |
import | 导入依赖 |
return | 返回 |
var | 声明变量 |
const | 声明常量 |
fallthrough | 如果case带有fallthrough,程序会继续执行下一条case,不会再判断下一条case的值 |
if | 判断语句 |
ranage | 从slice、map等结构中取元素 |
type | 定义类型 |
chan | 定义一个channel |
else | 用在条件语句中,表明当条件不成立时的分支 |
goto | 跳转语句 |
package | 声明包 |
switch | 分支语句结构的引导词 |
case | 分支语句结构的引导词 |
defer | 延迟执行,函数的收尾工作。在函数结束前执行 |
go | 并发 |
map | map结构类型 |
struct | 定义结构体 |
break | 提前跳出一个块 |
default | 默认选项,用在switch和select语句种 |
func | 函数定义 |
interface | 定义接口 |
select | go语言特有的channel选择结构 |
除了以上几种,最新版的Go语言中有30几种保留字标识符,他们可以分为以下三类:
- 常量相关:true,false,iota,nil。
- 类型相关:int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,uintptr,float,float32,float64,complex128,complex64,bool,byte,rune,string,error。
- 函数相关:make,len,cap,new,append,copy,delete,complex,real,imag,panic,recover。
1.3.1.7 Go语言的空格
在Go语言中,变量声明必须使用空格隔开,如下:
var name string
在函数体中,适当的使用空格来让代码易读且更加直观 如:
name=surname+li
相比加入空格
name = surname + li
一般在开发过程中我们都会使用编辑器的格式化命令来快速进行格式化。
总结
如果没有躺赢的命那就站起来奔跑,我们兵分两路,顶峰相见。