目录
异常处理
在之前我们其实也有接触到错误处理,比如我们String转换类型的时候使用到的strconv函数就有返回值是error类型的,那么异常处理机制中我们使用defer + recover来处理异常。
panic是我们Go中的一个终止过程的一个函数,如果这个函数被触发了,那么程序就会异常终止,所以其中说“recover会取回传至 panic 的错误值“其实就是会把程序中报错的错误信息取到。
简单来说就是recover能取到我们程序中的异常信息,那么我们看一下简单的demo实现
package main
import "fmt"
func main(){
defer func(){//通过defer将检错匿名函数压如栈帧中
err := recover()//recover获取错误信息
if err!= nil{//一切正常时err==nil
fmt.Println("程序异常:",err)
}
}()
num1:=10
num2:=0
num3:=num1/num2
fmt.Println(num3)
}
在这个案例中我们有一个分母为0的异常,recover会获取到这个异常,而defer关键字就是会在我们程序最后才会执行defer修饰的部分。即先进行除法赋值,然后异常判断。
自定义异常类型
package main
import (
"fmt"
"errors"
)
func test(num1,num2 int)(err error){
if num2==0 {
//自定义错误类型,通过New抛出异常
return errors.New("分母不能为0")
}else{
num3:=num1/num2
fmt.Println(num3)
return nil//正常,返回nil
}
}
func main(){
err := test(10,0)
if err!=nil {
fmt.Println("程序异常:",err)
}
fmt.Println("11111")
fmt.Println("222222")
}
这段代码中我们自己定义程序可能出现的异常问题,然后通过New创建并返回异常信息,在函数的返回值中接收这个error类型的数据,然后在主函数中接收并判断。
这种处理方式可以直接将错误类型返回出来,但是缺点是依然会执行程序错误后的代码
很多情况下我们的代码在程序异常后,后面的代码其实都不需要执行了,这时我们需要新的处理方法
Panic()
通过painc()函数可以终止异常程序的执行
数组
数组初始化
四种方式
其实在数组这里没什么太多的文章,我们就是需要知道一下Go语言中数组怎么进行初始化的。
二维数组创建的方式如下:
- 声明并初始化一个二维数组,指定数组的维度和初始值:
// 声明一个包含3行4列的二维数组 var arr = [3][4]int{ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, }
- 通过多次赋值来创建一个二维数组:
// 声明一个包含2行3列的二维数组 var arr [2][3]int arr[0] = [3]int{1, 2, 3} arr[1] = [3]int{4, 5, 6}
切片
切片这个概念其实在Python中也有,他俩其实差不多,就是把我们数组中的部分元素按照一定的规律取出。话不多说,我们先看看切片怎么初始化。
切片定义的三种方法
[1]方式1:定义一个切片,然后让切片去引用一个已经创建好的数组。
func main(){
var arr = [...]int{4,5,6,7}
for _,val := range arr{
fmt.Println(val)
}
slice := arr[1:3]
fmt.Println(slice)
}
上述我们可以了解到,切片的区间范围其实是左闭右开的 即[1:3),
那么既然我们能直接输出slice中的数据,那么slice中的数据和数组中的数据是同一个么?
由上面这个例子我们可以知道,slice中的数据其实就相当于数组元素的一个引用,他们俩其实是同一个数据
[2]方式2:通过make内置函数来创建切片。基本语法: var切片名[type = make(llen,[cap])
ps: make底层创建一个数组,对外不可见,所以不可以直接操作这个数组,要通过slice去间接的访问各个元素
[3]方式3:定一个切片,直接就指定具体数组,使用原理类似make的方式。
切片追加元素
上面包括了切片中追加单独元素以及切片的底层原理,其实就是创建一个新的数组然后再追加,如果这时想要再原来数组中追加的话,只需要追加和新生成的数组是同一个就可以了。其次,切片追加切片的时候需要注意“…”不能省略 。
映射map
func main(){
var a map[int]string
a = make(map[int]string,10)
a[1] = "张三"
a[2] = "李四"
a[3] = "王五"
fmt.Println(a)
}
map的其他初始化方法:①make不加数量参数,②直接赋值初始化
map的特点:
(1) map集合在使用前一定要make
(2) map的key-value是无序的
(3) key是不可以重复的,如果遇到重复,后一个value会替换前一个value
(4) value可以重复的
(5) map并不提供类似C++中的first或者key直接输出的方式
map操作
(1)增加和更新操作作:
map["key"]= value---------> 如果key还没有,就是增加,如果key存在就是修改
(2) 删除操作:
delete(map,"key"),delete是一个内置函数,如果key存在,就删除该key-value,如果key不存在,不操作,但是也不会报错(像C++中的set的insert一样)
(3) 清空操作:如果我们要删除map的所有key ,没有一个专门的方法一次删除,可以遍历一下key,逐个删除;
或者map = make(...),make一个新的,让原来的成为垃圾,被gc回收
(4)查找操作:
value ,bool = map[key]
value为返回的value,bool为是否返回,要么true 要么false
(5)map的遍历
map只能用for-range遍历
func main(){
//创建一个key为string,value为map映射的类型,其中value的map,key为string,val为string
mp := make(map[string]map[string]string)
mp["动物"] = make(map[string]string)
mp["动物"]["猫科"] = "老虎"
mp["动物"]["犬科"] = "猎狗"
mp["动物"]["猫科"] = "hello kitty"//会覆盖掉老虎,因为key相同
for idx,val := range mp{
fmt.Printf("%v\n",idx)
for mtype,val1 := range val{
fmt.Printf("科属:%v 名字:%v\n",mtype,val1)
}
}
}