钟
2023/02/23阅读:26主题:极客黑
GO 快速学习篇-基础语法篇(1)关键字和标识符
前言
GO有特有的关键字或叫保留字符,这种关键关键标识符是不可以用于自定义定义变量的,也就是说不能用作标识符。
Go关键字有哪些?
Go语言的关键字有如下所列:
-
var 定义变量。
-
const ' 定义标量或叫常量。
-
break 终止循环,退出循环。
-
case 用于switch条件中条件匹配。
-
chan 用于定义通道。
-
continue 退出当前循环,进行下一个循环,通常用于FOR中。
-
default 默认表达式,默认值。
-
defer 定义延迟执行功能。
-
type 自定义新的结构类型。
-
if 条件判断语句。
-
else 条件判断语句。
-
switch 条件匹配语法,选择结构。
-
fallthrough 用于 switch 语句。。当我们使用此关键字表示将输入的下一种情况。
-
for 循环。
-
func 用于函数声明。
-
go 创建goroutine协程。
-
goto 强制无条件跳转至带标签。
-
import 用于包导入。
-
interface 定义接口。
-
map map 类型对象。它用于映射是键值对的无序集合。
-
package 定义包(方法集)。
-
range 进行可迭代对象循环迭代,常用于切片,管道或者MAP。
-
return 返回值。
-
select 用于 goroutine协程中在同步通信操作期间等待。
-
struct 结构体类型数据
上述的关键字都不可用于变量名,否则会提示语法错误。如下图所示:

变量名(标识符)命名约束规范
变量名标识的是一个对象的名字,这个对象可以是变量,可以是常量,可以是函数,也可以是结构,也可以是类型等。在定义的具体的名字的时候,我们通常需要:见名思意,而且它也需要遵循一定的规则:
-
1.可以由字母或数字或下划线组成。 -
2.首字母不能为数字。 -
3.保留字或关键字不可能用于定义变量名。 -
4.不能包含有空格或其他特殊字符。 -
5.GO变量对大小写是敏感的,它区分大小写。
空白标识符
对于我们定义一些变量名,存在但是不会用到的,我们可以使用下滑杠“_”进行忽略。这个下划线也可以叫做空白标识符。它可以较少内存空间。
它主要的应用场景有:
-
函数返回值,忽略。 -
包导入时候仅仅执行包的init函数。此时不会调用其他包中变量或函数。 -
类型断言。
如下示例:
函数返回值,忽略

包导入,忽略

类型断言
如果没有实现Actions接口,则编译错误,如下所示:

变量和常量
变量或常量是对对象某种描述标识符,通常它需要被赋予值才有存在意义。
变量
常量定义的注意事项点:
-
1: 变量定义后必须被使用。 -
2: 变量的命名需遵循一定的规则,比如不能使用数字开头,还有一些关键字,保留字不能被定义为变量。 -
3: 变量的声明后没有使用的话,它是一个空值。 -
4: 用一个作用域中,不能存在重复同名的变量。 -
5: 可以隐式声明变量类型,GO会自动推到类型。 -
6: 短变量声明仅限于局部变量中定义,不可用于全局变量。 -
7:短变量可以多变量同时声明,且可以自动进行类型的推入戏导。
通常的定义格式如下:
var a string = "Go"
or
a:= "Go"
其中 var表示定义变量 a表示变量名 "Go" 是变量的值。详细示例代码如下:
package main
import "fmt"
func get_user_info() (int, string) {
return 89, "你大爷"
}
// 学习变量的定义及注意事项
func main() {
//1: 变量定义后必须被使用
//2: 变量的命名需遵循一定的规则,比如不能使用数字开头,还有一些关键字,保留字不能被定义为变量
//3: 变量的声明后没有使用的话,它是一个空值
//4: 用一个作用域中,不能存在重复同名的变量
//5: 可以隐式声明变量类型,GO会自动推到类型
//6: 短变量声明仅限于局部变量中定义,不可用于全局变量
//7:短变量可以多变量同时声明,且可以自动进行类型的推导
var a string
fmt.Println("空值", a)
// 6:在同一行中可以声明多个变量
var b, c string
fmt.Println("变量", b, c)
// 一次同时声明多个不同类型的变量
var (
name string
age string
sex int
)
// 赋值
name = "大爷"
age = "12"
sex = 29
// 需要被使用
fmt.Println("同时声明多个 不同类型的变量", name, age, sex)
//8:匿名变量,可以使用下划线进行下定义,表示忽略该变量
age11, name22 := get_user_info()
fmt.Println("匿名变量", age11, name22)
_, name33 := get_user_info()
fmt.Println("匿名变量", age11, name33)
}
常量
常量是用const关键字来定义,它又几种定义方式,具体如下代码所示:
const name1 string = "GO"
const name2 = "GO"
const (
name3 string = "GO"
name4 = "GO"
)
const name5, name6 = "GO", "GOU"
iota特殊常量
-
可以被编译器修改的常量 -
当他出现在定义的常量的 const后面时,表示对当前的常量进行0值初始。 -
如果关键之const后 定义后多个变量,后续的变量还可以进行计数累加。
示例图:

输出结果图:

结果说明:
-
关键字iota从0开始计算,每增加一个常量会让iota自动+1 -
如果常量值设为iota,且下一个常量没有赋值,则没有赋值的常量和它的上一个常量的值相同(c = 5 也 d = 5 f= 5) -
e为4 是因为它通过变量累加起来,从0 到e的时候刚好累计到4.
运算符
运算符无非就是加减乘除算术,比较,赋值,逻辑,位运算等等。
数据类型
-
整形 -
浮点型 -
布尔类型 -
字符 -
字符串类
整型
整型定义:
-
它没有小数点数。 -
它可以十进制的也可以八进制或十六进制表示。 -
可以是一个正负值。
类型划分
-
基本类型 -
短整型 -
长整型 -
无符号类型
在定义整形变量时,需根基实际需求设置变量类型。因为每个类型的每个类型都有固定的数值范围。
-
有符合类型(可以理解为可以取负值的类型,,即可以支持正数也可以支持负数的形式) -
无符号类型(可以理解为从0开始正值,无负值类型,即只支持正数形式,不支持负数的形式)
有符号类型
-
int 类型 整型,取值范围和操作系统的位数有关(在实际应用中,通常我们的使用int或uint设置整形数值范围,其中在不同的系统中各自占用的字节说也不一样,32位的占四个字节,64为的占8个字节)
-
int8 类型 整型,取值范围是 -2的(8-1)次方-到2的(8-1)次方-1,也就是 -128~127(8代表是int8还是int16) [占用1字节]
-
int16 类型 整型,取值范围是 -2的(16-1)次方-到2的(16-1)次方-1,也就是 -32768~32767(8代表是int8还是int16) [占用2字节]
-
int32 类型 整型,取值范围是 -2的(32-1)次方-到2的(32-1)次方-1(8代表是int8还是int16)[占用4字节]
-
int64 类型 整型,取值范围是 -2的(64-1)次方-到2的(64-1)次方-1(8代表是int8还是int16)[占用8字节]
无符号类型
-
uint 类型 - 无符号整型,取值范围和操作系统的位数有关(在实际应用中,通常我们的使用int或uint设置整形数值范围,其中在不同的系统中各自占用的字节说也不一样,32位的占四个字节,64为的占8个字节)
-
uint8 类型 - 无符号整型,取值范围0~255,也就是0~2到8的次方-1. [占用1字节]
-
uint16 类型 - 无符号整型,取值范围0~65535,也就是0~2到16的次方-1. [占用2字节]
-
uint32 类型 - - 取值范围0~xxxx,也就是0~2到32的次方-1. [占用4字节]
-
uint64 类型 取值范围0~Xxxx,也就是0~2到64的次方-1. [占用8字节]
浮点类型
定义
-
用于浮点类型是用于存放小数。 -
提供了float32 和 float64。 -
浮点类型不支持无符号类型。 -
它可以使用科学计数法的形式表示。
实际应用中通常。如果定义对于的浮点类型的,系统默认是使用float64。因为float64的精度比float32高。
-
float32 最大值:3.4e38 常量:math.MaxFloat32 -
float64 最大值:1.8e308 常量:math.MaxFloat64
bool类型
定义
-
布尔类型也叫 bool 类型 -
数据只允许取值 true 和 false -
bool 类型 占 1 个字节,默认值为 false。
字符串类型
-
字符串是一个不可改变的字节序列。 -
字符串可以包含任意的数据。 -
通常用于表示可读的文本。 -
在Go 语言 字符串是 UTF-8 字符的一个序列,就是一串固定长度的字符连接起来的字符序列。
Go 语言里的字符串的内部实现使用 UTF-8 编码。通过 rune 类型,可以方便地对每个 UTF-8 字符进行访问。当然,Go 语言也支持按传统的 ASCII 码方式进行逐字符访问。
ASCII编码和Unicode编码区别
ASCII编码
-
ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。标准ASCII 码也叫基础ASCII码,使用7 位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符。其中最后一位用于奇偶校验。
问题:ASCII是单字节编码,无法用来表示中文(中文编码至少需要2个字节),所以,中国制定了GB2312编码,用来把中文编进去。但世界上有许多不同的语言,所以需要一种统一的编码。
Unicode编码
-
Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。 Unicode最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
Unicode和ASCII的区别
-
ASCII编码是1个字节,而Unicode编码通常是2个字节。
-
字母A用ASCII编码是十进制的65,二进制的01000001;而在Unicode中,只需要在前面补0,即为:00000000 01000001。
新的问题:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。
UTF8
本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。
-
UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。
字符小练习
package main
import (
"fmt"
"strings"
)
func main() {
// 字符串转义
name := "你好 \n 小钟同学"
fmt.Println(name)
// 斜杠转义--输出反斜杠
path := "D:\\Go\\bin"
fmt.Println(path)
// 双引号的转义
fuhao := "你是\"睡"
fmt.Println(fuhao)
// 多行字符串的定义
str := `你是谁
我是说,
你傻啊
`
fmt.Println(str)
// 求字符串的长度
str1 := "男人"
// 为什么长度是6呢? 因为一个汉字占用3个字节,所以它的长度就是6
fmt.Println(len(str1))
str2 := "MM"
// 为什么长度是2呢? 因为一个Y英文占用1个字节"",所以它的长度就是2
fmt.Println(len(str2))
// 字符串的拼接
str3 := "我是你家的"
str4 := "哪一个大爷?"
fmt.Println(str3 + str4)
// Sprintf表示获取里面的值并返回
str5 := fmt.Sprintf("%v%v", str3, str4)
fmt.Println(str5)
// 字符串的分割,返回数组
str6 := "大家&好"
fmt.Println(strings.Split(str6, "&"))
}
字符类型
-
字符串 中的每一个元素叫做一个字符。
-
Go 语言 中的单个字符 常量 必须使用单引号引起来。
-
Golang 中没有专门的字符类型,如果要存储单个字符(字母),一般使用 byte 来保存。
-
如果使用 uint8 类型,或者 byte 型,来表示一个字符,它代表了 ASCII 码的一个字符。
-
如果使用 rune 类型,代表一个 UTF-8 字符。当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型实际是一个 int32。
示例图示: 图示结果:

示例图示: 图示结果:

指针类型
-
用于存放地址的类型。
-
它是一个指针变量,它存放的是一个地址,而这个地址指向的空间存放的才是值。
-
它不支持指针的移动。
-
Go语言中,使用 & 符号可以获取一个变量的地址。
-
Go语言中,使用 * 符号可以获取 Go 语言指针类型的地址所对应的值。
使用 * 定义指针变量
示例如下:

使用 *获取指针类型地址所指向的值
示例如下:
修改 *获取指针类型地址所指向的值,影响验证

函数篇
定义
-
编写函数的主要目的复杂问题分解为单一任务来解决细化的任务函数,有助于代码重用。 -
分为:自定义函数和系统函数。 -
完成某一功能的程序指令(语句)的集合,称为函数。 -
函数可以支持 返回任意多个值(类似Python返回元组)。 -
支持普通函数、匿名函数 和 闭包 三种形式。 -
函数可以无返回值 也可以有返回值,返回值可以一个或多个。
特性
Go语言函数是:“一等公民”,所以:
-
函数可以作为值进行传递。 -
支持匿名函数和闭包(closure)。 -
函数可以满足接口。
函数参数
-
Go 语言函数的参数,为形参。即如果我们【通过传值】的方式,传递的参数是【实际参数的一份拷贝】,而不是真正的实际参数。 -
形参意思是对传入的参数值的一份拷贝,每部对拷贝的参数对象修改不会影响到外部。

-
如果是实参,则必须要使用指针类型。

可变参函数
-
指定任意的个数与数据类型的参数。 -
函数最后一个参数,使用的形式 ...语法糖,效果类似于 Golang 的 切片。 -
它类似python中的*args参数,需要通过遍历提取参数。 -
可以传入任意个数与任意类型(任意数据类型时候是定义为接口类型 ,即 interface。)。
匿名函数
-
匿名函数,就是只有函数体没有函数名的函数。 -
匿名函数可以作为一种类型 被赋值给函数类型的 变量,匿名函数也往往以变量方式传递。 -
匿名函数可以直接赋值给变量,也可以作为函数的参数,传递给函数。
闭包函数
-
闭包就是一个函数 和与其相关的引用环境组合的一个整体。

defer(延时机制)篇
-
用于在函数执行完毕后调用。可以用于释放资源等场景。 -
多个 defer 定义,则只需顺序为逆序进行。也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。

-
如果同一个 函数 中,既有 defer 语句,同时也有 return 语句,那么 defer 语句会在 return 语句的后面执行。
函数错误处理
在Go中对于函数的错误,通常是通过抛出异常错误来处理的,而如何抛出错误,则是通过返回错误值对象,来抛出,如下示例所示:

panic错误处理
-
如果程序处理过程出现严重的问题,且不能正常继续运行,通常我们需要充值程序运行,程序输出了错误信息之后,直接退出不在继续往下运行。如下示例所示: 图示是会继续往下执行的:

图示不会继续往下执行的:

使用recover处理panic错误处理终止问题
当遇到panic错误程序会终止运行,但是某种情况比如以下web应用,我们不吭出现此类错误就终止程序,需要继续保持运行,则需要基于recover来处理。
-
recover 处理panic错误处理终止问题 -
recover 一般需要和de

主要的代码如下:
defer func() {
if r := recover(); r != nil {
fmt.Println("发生了错误 =我拦截修复一下!!!!!")
}
}()
作者介绍