Go-异常和常用包讲解

异常panic

package main

// panic
func main() {

   // 什么时候会发生恐慌panic,我们不知道什么时候会报错
   // 程序运行的时候会发生panic

   // 手动抛出panic。我们在一些能够预知到危险的情况下,可以主动抛出
   // 如果有panic发生,我们尽可能接收它,并处理。
   // func panic(v any)  使用 panic() 程序就会终止,停在这里强制结束
   panic("程序 panic了")


}

go 语言是追求简洁的,他没有使用 try…catch 语句

错误error机制: error接口,接收错误,然后判断实现。

异常:Java中也有

如果有些情况,必须要处理异常,就需要使用panic,抛出了异常,recover,接收这个异常来处理。

假设:手动给一个值设定了大小区间 (0-500) i++ 499 panic, 有人给我处理这个panic

package main

import "fmt"

// panic  recover
//
// 出现了panic之后,如果有defer语句,先执行所有的defer语句。
//
// defer : 延迟函数,倒序执行,处理一些问题。
func main() {
   defer fmt.Println("main--1")
   defer fmt.Println("main--2")
   fmt.Println("main--3")
   testPanic(1) // 外部函数,也不会继续再向下执行了
   defer fmt.Println("main--4")
   fmt.Println("main--5")
}
func testPanic(num int) {
   defer fmt.Println("testPanic--1")
   defer fmt.Println("testPanic--2")
   fmt.Println("testPanic--3")
   // 如果在函数中一旦触发了 panic,会终止后面要执行的代码。
   // 如果存在defer,正常按照defer逻辑执行
   if num == 1 {
      panic("出现预定的异常----panic")
   }
   defer fmt.Println("testPanic--4")
   fmt.Println("testPanic--5")
}

recover结合defer处理 panic 恐慌

package main

import "fmt"

// panic  recover
//
// 出现了panic之后,如果有defer语句,先执行所有的defer语句。
//
// defer : 延迟函数,倒序执行,处理一些问题。
func main() {
   defer fmt.Println("main--1")
   defer fmt.Println("main--2")
   fmt.Println("main--3")
   testPanic(1) // 外部函数,如果在函数内部已经处理panic,那么程序会继续执行
   defer fmt.Println("main--4")
   fmt.Println("main--5")
}
func testPanic(num int) {
   // 出去函数的时候处理这里面可能发生的panic
   // recover func recover() any 返回panic传递的值
   // panic   func panic(v any)
   defer func() {
      if msg := recover(); msg != nil {
         fmt.Println("recover执行了... panic msg:", msg)
         // 处理逻辑
         fmt.Println("---------程序已恢复----------")
      }
   }()

   defer fmt.Println("testPanic--1")
   defer fmt.Println("testPanic--2")
   fmt.Println("testPanic--3")
   // 如果在函数中一旦触发了 panic,会终止后面要执行的代码。
   // 如果存在defer,正常按照defer逻辑执行
   if num == 1 {
      panic("出现预定的异常----panic")
   }
   defer fmt.Println("testPanic--4")
   fmt.Println("testPanic--5")
}

执行逻辑:

1、panic 触发

2、触发panic当前函数的所有defer语句,倒序执行

3、直到遇到recover处理了这个panic…函数结束

4、main,继续向下执行。

Go语言中包

Go语言中包的本质:文件夹,不同的文件夹可以存放不同的功能代码。

Go语言的源码复用就是建立在包机制上的

fmt.println()

main包

1、main函数所在的包,必须是main包。代表程序的入口

2、main包中引入其他包 ,import “fmt”

3、main是程序的入口,其他包不能使用,尽量使用网址作为包名。

package包

src:保存我们项目的源码路径,所有的代码都用包的形式放在这里。

package 声明包在哪里,不需要和文件夹名一致,但是我们尽量使用文件夹的名字。

1、一个目录下所有的go文件的package必须同名。

2、package可以和文件夹不同名,但不建议这么写

3、同一个包下的所有go文件的函数,可以直接调用

4、导入包的时候,要从src去写。

package pojo

// 导入其他包,需要从goworks 下面的src 目录开始导,最标准写法
// import "study/lesson10/service"
// 相对路径的导包,十分不建议
// import "../service"

5、对于外包中的函数,我们需要使用 包名.函数名来使用。

package service

import (
   "fmt"

   "study/lesson10/pojo/user"
)

func userInfo() {
   user.UpdateUserInfo()

   fmt.Println()
}

聊聊其他的包导入方式

1、可以批量导入包

import(
	// 系统
	""
	
	// 自己写的包 ..
	""
	
	// 网上下载的包 github...
	""
)

2、相对路径导入包 …/ 上一级

import "../xxx" // 不建议这样用

3、如果包名冲突,解决办法。

package controller

// 包
//
//import "math/rand"  // 随机数生成

import (
   //"crypto/rand"
   //R "math/rand" // 可以给包起别名
   //. "math/rand" // 简便模式:可以直接调用该包下的函数,不需要通过包名。
   _ "math/rand" // 匿名导入,只会执行这个包下的init方法
)

func test() {

}

init函数(重点)

要匿名导入 _ “math/rand” // 匿名导入,只会执行这个包下的init方法

Go语言中,除了main函数入口以外,还有一个十分特别的函数 init()函数。

init:初始化,在main方法执行之前执行

init:设置一些包… 初始化一些全局变量… 建立一些第三方的连接(数据库连接)、注册、检查、修复程序状态。

init 函数可以有多个。

init函数的执行顺序问题

package main

import (
   "fmt"

   _ "study/lesson10/aaa" // b.go  -- init()
   // 匿名导入包,会执行报下所有go文件的 init 函数, 单个init被多个地方导入,只会执行一次
   // 1、先执行导入包的init函数,单个go文件中是顺序执行的,所有go中的init函数执行完毕后,才会到main包
   // 2、如果导入了多个匿名包,按照main中导入包的顺序来进行执行。
   // 3、在同一个包下的go文件如果有多个,都有init的情况下,按照文件排放顺序来执行对应的init函数()
   _ "study/lesson10/test" // a.go  c.go  -- init()
)

func init() {
   fmt.Println("main---init")
}
func main() {
   // init 函数不需要传入参数,也没有返回值,任何地方不能调用 init()
   //init()
}

在这里插入图片描述

strings包

package stringsdemo

import (
   "fmt"
   "strings"
)

// strings 字符串常用操作包
// strings 所有方法自己点一下
// 看源码,这个函数如何使用
// 想一个案例测试
func Test() {

   // 1、字符是不能修改的
   str := "cheng,ccczzzaaa"

   // strings下的常用方法
   // 1、判断某个字符是否包含了指定的内容 Contains
   // Contains(s, substr string) bool
   fmt.Println(strings.Contains(str, "z"))

   // 2、判断某个字符串是否包含了多个字符串中的某一个
   fmt.Println(strings.ContainsAny(str, "zk"))

   // 3、统计这个字符在指定字符串中出现的数量 Count() 计数
   // func Count(s, substr string) int
   fmt.Println(strings.Count(str, "n")) // 4

   // 后期作业和IO会结合的
   fileName := "20230219.mp3"
   // 4、判断用什么开头的HasPrefix()
   if strings.HasPrefix(fileName, "2023") {
      fmt.Println("找到2023开头的文件:", fileName)
   }
   // 5、判断用什么结尾的 HasSuffix()
   if strings.HasSuffix(fileName, ".mp4") {
      fmt.Println("找到mp4结尾的文件:", fileName)
   }

   // 6、寻找这个字符串第一次出现的位置 Index()
   fmt.Println(strings.Index(str, "z"))
   // 7、寻找这个字符串最后一次出现的位置 LastIndex()
   fmt.Println(strings.LastIndex(str, "ua"))

   // 8、拼接字符串, 数组或者切片拼接 ,前端给了我们多个参数。保存为一个字符串
   // Join()
   str2 := []string{"a", "b", "c", "d", "e"}
   fmt.Println(strings.Join(str2, " "))
   // 通过某个格式,拆分字符串 Split()
   str3 := strings.Join(str2, "-")
   fmt.Println(strings.Split(str3, "-")) // 用的最多

   // 大小写ToUpper()
   fmt.Println(strings.ToUpper(str))
   fmt.Println(strings.ToLower(str))
   // 替换 -1 改所有的,  1 就是一个  2就是2两个
   fmt.Println(strings.Replace(str, "e", "程", 1))
   // 截取某个字符串
   str5 := str[0:5]
   fmt.Println(str5)

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值