一、go错误处理
1.1 错误处理
func test(){
defer func() {
err := recover() //recover内置函数,可以捕获到异常
if err != nil{
//说明捕获到异常
fmt.Println("err=", err)
}
}()
num1 := 10
num2 := 0
result := num1/ num2
fmt.Println(result)
fmt.Println("执行到这里了")
}
func main() {
test()
fmt.Println("执行到这里了")
}
1.2 自定义错误
- errors.New()和panic
func readFileNameError(fileName string)(er error){
if fileName != "readme.txt" {
return errors.New("读取文件名出错")
}else{
return nil
}
}
func main() {
err := readFileNameError("readme.txt")
if err != nil{
//panic中传入的是error类型的
//如果执行到这里,下面的程序不会执行且会报错
panic(err)
}
fmt.Println("继续执行下面的任务")
}
二、go语言接口
2.1 接口的概念
go语言将一些公共的处理逻辑模板集中在接口中
2.2 接口的案例
type Student struct{
ownName string
ownAge int
ownAddress string
}
type People interface {
age()
}
func (stu Student) age() {
fmt.Println("stu.ownName")
}
func main() {
//var stu1 Student
//stu1 = Student{}
//stu1.ownName = "jack"
//stu1.ownAge = 23
//stu1.ownAddress = "西安"
//stu1.age()
var peo People
peo = new(Student)
peo.age()
}
运行结果:
stu.ownName
2.3 利用接口修改结构体中的属性
- 类似于java中的set,get方法
type Student struct {
name string
}
type people interface {
getName()
setName(name string)
}
func (stu Student) getName() {
fmt.Println(stu.name)
}
func (stu *Student) setName(name string) {
stu.name = name
}
func main() {
var stu Student = Student{
"jack"}
stu.getName()
stu.setName("rise")
stu.getName()
}
结果:
jack
rise
三、切片
3.1 切片的本质
- 切片是数组的引用
- 切片是动态数组
- 改变切片中的元素,对应数组中的元素也会改变
func main() {
var list [5]int =[...] int{
1,2,3,4,5}
slice1 := list[1:3]
//slice
slice1[0] = 7
slice1[1] = 9
fmt.Println(list[1])
fmt.Println(list[2])
}
结果:
7
9
3.2 切片的使用
- method1
var list [5]int =[...] int{
1,2,3,4,5}
slice1 := list[1:3]
- method2
make方式创建的数组对外不可见
var slice2 []int = make([]int, 3, 5)
fmt.Println(len(slice2))
- method3
var slice2 []int = [] int{
1,2,3,4}
3.3 切片的遍历
func main() {
var slice2 []int = [] int{
1,2,3,4}
for i,v := range slice2{
fmt.Println(i,v)
}
}
3.4 append方法
func main() {
var slice2 []int = [] int{
1,2,3,4}
slice3 := slice2[1:3]
//append相当于新建了数组
slice4 := append(slice3, 200,200,400)
slice4[0] = 999
fmt.Println(slice3)
fmt.Println(slice3[0], slice4[0])
fmt.Println(slice4)
}
3.5 copy方法
- copy中的2个参数都必须是切片类型
func main() {
var slice2 []int = [] int{
1,2,3,4}
var slice3 = make([]int, 10)
copy(slice3, slice2)
fmt.Println(slice3)
slice3[0] = 4
fmt.Println(slice2[0])
}
3.6 string与切片
- string底层是一个byte数组,因此也可以进行切片操作
- string是不能通过切片修改的
var str string = "welcome"
slice1 := str[1:4]
for i, value := range slice1{
fmt.Print(i)
fmt.Printf("\t\t%c", value)
fmt.Println()
}
- 修改字符串
var str string = "welcome"
list := []byte(str)
list[1] = 'p'
str = string(list)
fmt.Println(str)
四、二维数组
4.1 二维数组的定义
func main() {
var str = [][3] int {
{
1,2,3}, {
2,3,4}}
}
4.2 for-range遍历二维数组
func main() {
var str = [][3] int {
{
1,2,3}, {
2,3,4}}
for _ , v := range str{
for _ , value := range v{
fmt.Println(value)
}
}
}
五、map
5.1 map的使用
var map_test map[string]string
//make的作用是给map分配数据空间
map_test = make(map[string]string)
map_test["name"] = "jack"
map_test["age"] = "20"
for key , value := range map_test{
fmt.Println(key, value)
}
5.2 map的crud
func main(){
var mymap map[string]string
mymap = make(map[string]string,4)
mymap["name"] = "jack"
fmt.Println(mymap["name"])
//删除元素
delete(mymap, "name")
fmt.Println(mymap["name"],"没有")
}
5.3 map的遍历
func main(){
var mymap map[string]string = map[string]string{
"name":"jack",
"age":"20",
"address":"西安",
}
for k,v := range mymap{
fmt.Println(k, " ", v)
}
}
5.4 map根据key排序
- 思路
将map的key放在切片中,排好序,然后根据排好序的切片中的key,去遍历map
func main(){
//map中没有专门针对key进行排序的方法
var str []string = make([]string, 1)
var mymap map[string]int = map[string]int{
"zack":12,
"lucy":23,
"jerry":43,
"rose":55,
"ted": 99,
}
for k,_ := range mymap{
str = append(str, k)
}
sort.Strings(str)
for index, v := range str{
fmt.Println(index,v)
}
for k, v := range mymap{
fmt.Println(k ," ", v)
}
}
5.5 map的使用细节
- map是引用类型
- map容量不够时,会自动增长
六、结构体
6.1 结构体类型
结构体是值类型,默认是值传递
6.1 创建结构体对象
- var stu1 *Student= new(Student)
type Student struct{
name string
age int
address string
}
func main(){
var stu1 *Student= new(Student)
(*stu1).age = 23
fmt.Println((*stu1).age)
}
- var stu1 *Student= &Student{}
func main(){
var stu1 *Student= &Student{
}
(*stu1).age = 23
fmt.Println((*stu1).age)
}
- var stu1 Student = Student{}
func main(){
var stu1 Student = Student{
}
stu1.age = 23
fmt.Println(stu1.age)
}
6.2 结构体指针的使用
func main(){
var stu1 Student = Student{
}
stu1.age = 23
fmt.Println(stu1.age)
var stu2 *Student = &stu1
(*stu2).age = 99
fmt.Println(stu1.age)
}
6.3 结构体细节
- 两个不同结构体类型的对象可以互转的前提是两个结论构体的结构完全一致
- 结构体重新定义会被认为是新的类型,但是可以强转
type Student struct{
name string
age int
address string
}
type Stu Student
func main(){
var stu1 Student = Student{
name: "jack",
age: 34,
address: "西安",
}
var stu2 Stu
//这里必须要强制类型转化才可以
stu2 = Stu(stu1)
fmt.Println(stu2.address)
}
6.4 结构体序列化
- json.Marshal()
type Student struct{
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
//Name string
//Age int
//Address string
}
type Stu Student
func main(){
var stu1 Student = Student{
}
stu1.Name = "jack"
stu1.Age = 34
stu1.Address = "西安"
//如果结构体中的字段是小写的话,序列化后是空的
//解决方法:a.字段名首字母大写 b.使用tag
res , err := json.Marshal(stu1)
if err != nil{
fmt.Println(err)
}
fmt.Println(string(res))
}
{
"Name":"jack","Age":34,"Address":"西安"}
//使用tag后的结果
{
"name":"jack","age":34,"address":"西安"}
6.5 结构体的方法
- getName方法举例
type Student struct{
Name string
Age int
Address string
}
func (stu Student) getName() string{
fmt.Println(stu.Name)
return stu.Name
}
type Stu Student
func main(){
var stu1 Student = Student{
}
stu1.Name = "jack"
stu1.Age = 34
stu1.Address = "西安"
stu1.getName()
}
- type integer int
type integer int
func (i *integer) change() *integer{
*i = *i + 1
fmt.Println(*i)
return i
}
func main(){
var num integer = 3
num.change()
}
七、方法
7.1方法的使用细节
- 方法名小写,只能在本包使用,方法名大写,可以在本包和其他包使用
7.2 函数和方法的区别
方法一般指的是与结构体绑定的方法,函数指的就是普通的函数。