• Go学习第六章——系统函数与错误处理


    1 字符串相关系统函数

    下面给出20个常见的函数,不需要导包,直接可以用

    func main() {
        // 1.统计字符串的长度,按字节 len(str)
        // golang的编码统一为utf-8(ascii的字符(字母和数字))占一个字节,汉字占用3个字节
        str := "hello北"
        fmt.Println("str len=", len(str))
        //输出:str len= 8
    
        // 2.字符串遍历,同时处理有中问的问题 r := []rune(str)
        str2 := "hello北京"
        r := []rune(str2)
        for i := 0; i < len(r); i++ {
           fmt.Printf("字符=%c\n", r[i])
        }
        // 输出:
        // 字符=h
        // 字符=e
        // 字符=l
        // 字符=l
        // 字符=o
        // 字符=北
        // 字符=京
    
        // 3.字符串 转 整数:n, err := strconv.Atoi("12")
        n, err := strconv.Atoi("123")
        if err != nil {
           fmt.Println("转换错误", err)
        } else {
           fmt.Println("转成的结果是", n)
        }
        // 输出:转成的结果是 123
    
        // 4.整数 转 字符串 str = strconv.Itoa(12345)
        str = strconv.Itoa(12345)
        fmt.Printf("str=%v, str=%T\n", str, str)
        // 输出:str=12345, str=string
    
        // 5.字符串 转 []byte: var bytes = []byte("hello go")
        var bytes = []byte("hello go")
        fmt.Printf("bytes=%v\n", bytes)
        // 输出:bytes=[104 101 108 108 111 32 103 111]
    
        // 6.[]byte 转 字符串: str = string([]byte{97, 98, 99})
        str = string([]byte{97, 98, 99})
        fmt.Printf("str=%v\n", str)
        // 输出:str=abc
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    还有好多,我这里直接不按照代码看了,具体查看官方文档~~

    1. 10进制转 2, 8, 16进制: str = strconv.FormatInt(123, 2),返回对应的字符串
    2. 查找子串是否在指定的字符串中: strings.Contains("seafood", "foo") //true
    3. 统计一个字符串有几个指定的子串 : strings.Count("ceheese", "e") //4
    4. 不区分大小写的字符串比较(==是区分字母大小写的): **fmt.Println(strings.EqualFold(“abc”, “Abc”)) **// true
    5. 返回子串在字符串第一次出现的index值,如果没有返回-1 : strings.Index("NLT_abc", "abc") // 4
    6. 返回子串在字符串最后一次出现的index,如没有返回-1 : strings.LastIndex("go golang", "go")
    7. 将指定的子串替换成 另外一个子串: strings.Replace("go go hello", "go", "go语言", n)
      n可以指定你希望替换几个,如果n=-1表示全部替换
    8. 按照指定的某个字符,为分割标识,将一个字符串拆分成字符串数组: strings.Split(“hello,wrold,ok”, “,”)
    9. 将字符串的字母进行大小写的转换: strings.ToLower("Go") // go strings.ToUpper(“Go”) -> GO
    10. 将字符串左右两边的空格去掉: strings.TrimSpace(" tn a lone gopher ntrn ")
    11. 将字符串左右两边指定的字符去掉 :
      strings.Trim("! hello! ", " !") // ["hello"] //将左右两边 ! 和 " "去掉
    12. 将字符串左边指定的字符去掉 : strings.TrimLeft ()
    13. 将字符串右边指定的字符去掉 : strings.TrimRight ()
    14. 判断字符串是否以指定的字符串开头: strings.HasPrefix("ftp://192.168.10.1", "ftp") // true

    2 时间和日期相关的函数

    说明:在编程中,经常使用到日期相关的函数,比如:统计某段代码执行消费的时间等等。

    2.1 Now函数

    时间和日期的函数,需要到入time包,所以你获取当前时间,就要调用函数Now函数:

    func main() {
    	// Now()返回值是一个结构体,类型是:time.Time
    	nowTime := time.Now()
    	fmt.Printf("%v ~~~ 对应的类型为:%T\n", nowTime, nowTime)
    
    	//调用结构体中的方法:
    	fmt.Printf("年:%v \n", nowTime.Year())
    	fmt.Printf("月:%v \n", nowTime.Month())      
    	fmt.Printf("月:%v \n", int(nowTime.Month())) 
    	fmt.Printf("日:%v \n", nowTime.Day())
    	fmt.Printf("时:%v \n", nowTime.Hour())
    	fmt.Printf("分:%v \n", nowTime.Minute())
    	fmt.Printf("秒:%v \n", nowTime.Second())
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    输出:

    2023-10-23 22:03:36.4169858 +0800 CST m=+0.011527901 ~~~ 对应的类型为:time.Time
    年:2023    
    月:October 
    月:10      
    日:23      
    时:22      
    分:3       
    秒:36    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    2.2 日期的格式化
    • 将日期以年月日时分秒按照格式输出为字符串:
    func main() {
    	// Now()返回值是一个结构体,类型是:time.Time
    	now := time.Now()
    
    	//Printf将字符串直接输出:
    	fmt.Printf("当前年月日: %d-%d-%d 时分秒:%d:%d:%d  \n", now.Year(), now.Month(),
    		now.Day(), now.Hour(), now.Minute(), now.Second())
    	//Sprintf可以得到这个字符串,以便后续使用:
    	datestr := fmt.Sprintf("当前年月日: %d-%d-%d 时分秒:%d:%d:%d  \n", now.Year(), now.Month(),
    		now.Day(), now.Hour(), now.Minute(), now.Second())
    	fmt.Println(datestr)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出结果:

    当前年月日: 2023-10-23 时分秒:22:3:56  
    当前年月日: 2023-10-23 时分秒:22:3:56 
    
    • 1
    • 2
    • 按照指定格式:
    func main() {
        // Now()返回值是一个结构体,类型是:time.Time
        now := time.Now()
    
        //这个参数字符串的各个数字必须是固定的,必须这样写
        datestr2 := now.Format("2006/01/02 15/04/05")
        fmt.Println(datestr2)
        //选择任意的组合都是可以的,根据需求自己选择就可以(自己任意组合)。
        datestr3 := now.Format("2006 15:04")
        fmt.Println(datestr3)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出结果:

    2023/10/23 22/04/37
    2023 22:04
    
    • 1
    • 2

    3 内置函数

    1. 什么是内置函数/内建函数:
      Golang设计者为了编程方便,提供了一些函数,这些函数不用导包可以直接使用,我们称为Go的内置函数/内建函数。

    2. 内置函数存放位置:
      在builtin包下,使用内置函数也的,直接用就行

    3. 常用函数:

    (1)len函数:
    统计字符串的长度,按字节进行统计

    (2)new函数:
    分配内存,主要用来分配值类型(int系列, float系列, bool, string、数组和结构体struct)

    func main() {
    
    	num1 := 100
    	fmt.Printf("num1的类型%T , num1的值=%v , num1的地址%v\n", num1, num1, &num1)
    
    	num2 := new(int) // *int
    	//num2的类型%T => *int
    	//num2的值 = 地址 0xc04204c098 (这个地址是系统分配)
    	//num2的地址%v = 地址 0xc04206a020  (这个地址是系统分配)
    	//num2指向的值 = 100
    	*num2  = 100
    	fmt.Printf("num2的类型%T , num2的值=%v , num2的地址%v\n num2这个指针,指向的值=%v", 
    		num2, num2, &num2, *num2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    输出结果:

    num1的类型int , num1的值=100 , num1的地址0x940a0b8
    num2的类型*int , num2的值=0x940a0bc , num2的地址0x9422058
     num2这个指针,指向的值=100
    
    • 1
    • 2
    • 3

    模拟内存图的情况,如图:

    在这里插入图片描述

    (3)make函数:
    分配内存,主要用来分配引用类型(指针、slice切片、map、管道chan、interface 等)后面再将~~

    4 错误处理

    1. 先写个必定报错的代码
    import "fmt"
    
    func test() {
    	num1 := 10
    	num2 := 0
    	res := num1 / num2
    	fmt.Println("res=", res)
    }
    
    func main() {
    	test()
    	fmt.Println("下面的代码和逻辑。。。。")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    报错显示:

    panic: runtime error: integer divide by zero
    
    • 1

    这里的panic代表的意思是恐慌,也就是致命错误,会直接崩溃,断掉连接

    4.1 基本使用

    Go中引入的处理方式为:defer,panic,recover三个函数

    Go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常的处理

    func test() {
    	// 使用defer + recover 来捕获和处理异常
    	defer func() {
    		err := recover() // recover()内置函数,可以捕获到异常
    		if err != nil {
    			fmt.Println("err=", err)
    		}
    	}()
    	num1 := 10
    	num2 := 0
    	res := num1 / num2
    	fmt.Println("res=", res)
    }
    
    func main() {
    	test()
    	fmt.Println("下面的代码和逻辑。。。。")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    输出结果:

    err= runtime error: integer divide by zero
    下面的代码和逻辑。。。。
    
    • 1
    • 2

    会发现,异常被抛出,而且还能继续执行下面的代码~~

    4.2 自定义错误

    Go也支持自定义错误,使用errors.New 和 panic 内置函数实现。

    1. errors.New(“错误说明”),会返回一个error类型的值,表示一个错误

    2. panic内置函数,接受一个interface{}类型的值(也就是任何值了)作为参数。可以接受error类型的遍历,输出错误信息,并退出程序

    如果err := readConf("config.ini"),也就是正确的,就没有问题~

    // 函数去读取以配置文件init.conf的信息
    // 如果文件名传入不正确,我们就返回一个自定义的错误
    func readConf(name string) (err error) {
    	if name == "config.ini" {
    		//读取...
    		return nil
    	} else {
    		//返回一个自定义错误
    		return errors.New("读取文件错误..")
    	}
    }
    
    func test() {
    	err := readConf("config.ini")
    	if err != nil {
    		//如果读取文件发送错误,就输出这个错误,并终止程序
    		panic(err)
    	}
    	fmt.Println("test()继续执行....")
    }
    
    func main() {
    	test()
    	fmt.Println("main()下面的代码。。。。")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    输出结果:

    test()继续执行....
    main()下面的代码。。。。
    
    • 1
    • 2

    如果err := readConf("config2.ini"),也就是错误的,就会报错,并且中止程序

    输出结果如下:

    panic: 读取文件错误..
    
    goroutine 1 [running]:
    main.test()
            F:/gocode/GoStudy_Day1/Day03/model/main/test.go:24 +0xb0
    main.main()
            F:/gocode/GoStudy_Day1/Day03/model/main/test.go:30 +0x18
    
    Process finished with the exit code 2
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第六章结束啦~~按道理应该属于函数章节,但我觉得应该拉出来单独,这样好理解一些~!!

  • 相关阅读:
    【UML】UML的几种关系(依赖-关联-聚合-组合-继承-实现)
    安全加固Linux系统的方法
    面试题:熟悉设计模式吗?谈谈简单工厂模式和策略模式的区别
    多卡服务器使用
    YashanDB混合存储揭秘:行式存储如何为高效TP业务保驾护航(下)
    js中数组的方法
    hive数据倾斜(超详细)
    shell
    Ps:利用 AI 技术创建人像皮肤图层蒙版
    pentaho(keetle)使用手册
  • 原文地址:https://blog.csdn.net/Hai_Helloyou/article/details/134001028