【GoLang入门】幼儿园入门学习
变量定义
Go中有很多种定义变量的方式,集百家之长,最标准的应该是先定义,后赋值。
注意:在Go中,局部变量定义了就必须使用,否则编译不成功
标准定义方式,关键字 变量名称 类型
1 | package main |
定义并赋值, 关键字 变量名 类型 = 值
1 | package main |
省略类型,Go会自动根据值来推断类型 关键字 变量名 = 值
这种定义方式是最常用,项目中使用最多的
1 | package main |
最简单的定义方式(只能在方法里面使用)
1 | package main |
全局变量,在函数外部的就是全局变量,全局变量必须使用var
或const
关键字,不能使用:=
1 | package main |
一次定义多个变量
1 | package main |
定义常量,使用const
关键字定义
1 | package main |
命名规范
核心思想:首字母大写的变量、函数、方法、属性可在包外(跨包)进行访问
类似java的公开和私密,首字母大写就是公开,首字母小写就私密
package概念
Go中是以package(包)为单位的,在同一个包内可以直接使用其他文件定义的变量和方法
在package user
的user/user.go
中定义了Name
和age
变量,在user/info.go
中可以直接使用,不需要导包
前提是user.go和info.go都在同一目录下,并且都写了package user
总结:Go 是以包为单位控制可见性的:同包共享所有内容,跨包只能访问导出的(首字母大写)成员。
输入输出
输出
在go中,常用的输出就fmt.Println
和fmt.Printf
Println是换行输出,可以一次性输出多个值,使用空格分隔,和python的print一样
fmt.Printf
是格式化输出,用的最多,但是不会自动换行, 可以在末尾加上\n
常用格式有: %s %d %f %.2f %T %v %#v 分别对应:字符串 整数 浮点数 保留2位小数点 类型 任意类型 空文本输出双引号
Sprintf和Printf一样,但是返回格式化后的文本, 可以使用变量接收
输入
Go中使用fmt.Scan
来接收标准输入,和python的input一样,但是没有输入提示,要自己输出
如果输入的值不能转化为对应类型,那么就会报错,但是会输出变量的默认值,比如age输入a会输出0
1 | package main |
基础数据类型
基础数据类型有:整数类型 浮点数类型 复数类型 字符串类型 布尔类型
整数类型
int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64
int后面的数字就是能存储的最大数据长度,int8是8个字节(8个二进制)
int取决于平台,32位操作系统就是int32 64位操作系统就是int64
uint和int同理,但它是无符号整数,只能用来存正整数,不能存负数
什么时候用int8或者int32? 在内存很匮乏并且长度短的项目中使用
浮点数类型
就一个float32和float64, 没什么好说的,用的也少
数组和切片
Go的数组需要定义长度,并且长度不能改变, 所以在Go中不常用,常用的是切片,和python中的列表类似
1 | func main() { |
切片可以动态增加和删除元素, 不用定义长度,也是由数组演变而来
1 | func main() { |
为了更像python中的列表,能存储任意类型,可以使用any类型定义
1 | func main() { |
创建全0切片, 默认长度为10,元素值都为0, 这样在可预估的长度条件下就更高效,不用一直扩充
它还有一个容量参数,不写为长度,容量是底层数组容量, 只要不超过容量都不会进行底层数组扩充
假设有一个场景: 一个班级最多有100个学员,就可以像下面这样定义, 不要太大也不要太小
1 | indexList := make([]int, 100) |
map
map在每种语言都存在,只是叫法不一样,js叫对象,python叫字典,就是有一个键和一个值(key-value)组成的集合
1 | func main() { |
还有其他定义方式,喜欢那种用那种, 但make用的多一点
1 | func main() { |
判断语句
使用if写一个成绩等级判断,大于90为优, 80-90为良,60-70为中,小于60为差
在go中且运算符为&&,或运算符为||,还有一个取反运算符,!(表达式);对应python的and、or、一样
1 | func main() { |
go中有switch语句,python中没有,所以它不常用,基本上if…else if…else就够用了
go和java有一点不同,go的switch有一个条件满足就跳出,不会进入自动下一层判断
如果要进入下层判断,可以使用fallthrough关键字, 和java恰恰相反
1 | package main |
switch还有一种写法,表达式写在switch后面,case是表达式的运算结果
1 | func main() { |
for循环
Go只有for循环,没有while循环和do…while循环
for循环很简单,和其他语言一样,也有i–
1 | func main() { |
老样子,99乘法表练练嵌套for循环, 在学校上学就是这么写的
1 | func main() { |
死循环
1 | func main() { |
模拟while循环, 没人会这么写
1 | func main() { |
遍历切片
基础写法和js一样,但go中也有range的写法
1 | func main() { |
range写法, 可以迭代全部可以迭代数组、切片、字符串、map、channel
对于map来说,range返回的是key和value, 如果不需要其中一个,可以使用_占位符来忽略
1 | func main() { |
跳过循环
break是跳出整个for循环体
continue是跳过本次循环中没有执行的部分
和python一模一样的
函数参数
函数是一段封装了特定功能的可重用代码块,用于执行重复的任务或者计算,函数接收一个或多个参数并返回一个或多个结果
Go使用func关键字定义函数,下面是一个最简单的函数;main函数是入口函数,由Go调用
1 | func main() { |
go中定义函数参数由很多中方式,基础是参数名称 参数类型
, 如果类型相同可以省略前面的参数类型
1 | func login(username, password string) { |
接收不确定参数个数的参数,可以使用...类型
的方式,就像Println函数一样
1 | func Println(a ...any) (n int, err error) { |
函数返回值
函数的返回值类型在参数后面定义,可以返回一个或多个返回值
1 | func add(a, b int) int { |
多个返回值使用小括号包裹,指定类型
1 | func div(a, b int) (int, bool) { |
定义返回名称,可以使用直接使用return关键字,Go会自动返回返回名称的当前值
1 | func div(a, b int) (r int, ok bool) { |
匿名函数
Go不支持函数内再定义函数,但是可以使用匿名函数来实现相同的作用
1 | func userInfo() (name string, age int) { |
匿名函数只能在定义的函数体内使用,不能在其他函数内使用;同一个文件不行,首字母大写也不行
并且匿名函数只能在函数体内定义,不能在外部定义, 匿名函数的上级必须是有个func, 匿名函数内可以定义匿名函数
高阶函数
在Go中,可以把一个函数当成参数传递到另一个函数中,函数也可以返回另外一个函数
下面是一个计数器,实现调用一次id就加1的效果
1 | func makeGetId() func() { |
值传递和引用传递
值传递就是把变量拷贝一份传递给变量,函数内修改不会影响外部变量的值
引用传递就是传递变量的内存地址(指针)给函数,函数内修改会影响外部变量的值
在go中使用&变量名
可以获取到变量的内存地址,使用*指针
获取内存地址的值
1 | func value(a int) { |
四个特殊函数
init函数是一个特殊的函数,存在以下特征:
- 在main函数之前执行,自动调用, 并且不能被其他函数调用
- 不能作为其他函数的参数传入
- 不能有传入参数和返回值
- 一个go文件可以有多个init函数,谁在前面谁先执行
总结: init函数主要是用于非main包的初始化
1 | func init() { |
defer函数也是一个特殊的函数,存在以下特性:
- 使用defer定义,用于注册延迟调用
defer
函数会在 函数“结束”之前调用- 多个defer函数,遵循先进后出,先定义的后调用
- defer函数中的变量,在defer声明时就赋值了
总结:defer函数用于资源释放和异常处理,保证资源在return前被释放
1 | func main() { |
recover函数也是一个特殊的函数,存在以下特征:
- recover函数只能在defer函数中使用
recover()
返回panic
的传入值(异常信息),没有异常时返回nil
。
总结:用来捕获(恢复)panic引发的异常, 如果程序中发生了 panic
,而且用 recover()
捕获了它,程序就不会崩溃,可以继续执行
1 | func safeDivide(a, b int) { |
panic函数也是一个特殊的函数,存在以下特征:
- 抛出运行时错误,导致程序崩溃(除非被
recover
捕获) - 程序立即停止当前函数,逐层向上展开调用栈
总结:panic抛出一个致命错误,让程序停止执行;类似python中的raise,但是go不鼓励使用panic来做常规错误处理,而是使用 error
类型返回错误;Go 标准库里,函数通常返回一个 error
类型作为最后一个返回值,调用方通过判断这个错误值是否为 nil
来判断是否有错。
1 | func testRecover() { |