Go语言中的异常处理及文本文件处理 - Go语言学习笔记


异常处理

error

非致命错误,输出错误信息

error接口使用

import "fmt"
import "errors"

func main() {
    err1 := fmt.Errorf("%s", "this is normal err1")
    fmt.Println("err1 = ", err1)
    
    err2 := errors.New("this is normal err2")
    fmt.Println("err2 = ", err2)
}

error接口应用

import "fmt"
import "errors"

func MyDiv(a, b int) (result int, err error) {
    err = nil
    if b == 0 {
        err = error.New("分母不能为0")
    } else {
        result = a/b
    }
}

func main() {
    result, err := MyDiv(10,2)
    if err !=nil {
        fmt.Println("err = ",err)
    }else{
        fmt.Println("result = ",result)
    }
}

panic

致命错误,中断程序

显式调用panic

panic("this is a painc test")

数组越界导致panic

程序错误也会导致自动调用panic

recover

// 设置recover
defer func() {
    // recover() // 可以打印错误信息
    if err := recover() ; err != nil { // 产生了panic异常
        fmt.Println(err)
    }
}() // 自动调用此匿名函数

文本文件处理

字符串处理

字符串操作

  1. Contains:判断是否包含指定字符串;func Contains(s, substr string) bool ;判断s中是否包含substr
  2. Join:字符串链接;func Join(a []string, sep string) ;把slice a通过sep链接起来;
  3. Index:查找字符串位置;func Index(s, sep string) int ;在字符串s中查找sep所在的位置,返回位置值,找不到返回-1
  4. Repeat:生成重复字符串;func Repeat(s string, count int) string ;重复s字符串counter次,最后返回重复的字符串
  5. Replace:替换字符;func Replace(s , old, new string, n int) string ;在s字符串中,吧old字符串替换为new字符串,n表示替换次数,小于0全部替换
  6. Split:切割字符串;func Split(s, sep string) []string;把s字符串按照sep分割,返回slice
  7. Trim:首尾去除指定字符串;func Trim(s string, cutset string) string ;在s字符串的头部和尾部去除cutset指定的字符串
  8. Fields:去除空格符;func Fields(s string) []string ;去除s字符串的空格符,并且按照空格分隔返回slice

字符串转换

Append

Append系列函数将整数等转换为字符串后,添加到现有的字节数组中。
示例:

str := make([]byte, 0, 100)
str = strconv.AppendInt(str, 4567, 10) // 以10进制方式追加
str = strconv.AppendBool(str, false)
str = strconv.AppendQoute(str, "abcdefg")
str = strconv.AppendQouteRune(str, '单')

fmt.Println(string(str)) // 4567false"abcdefg"'单'

Format

Format系列函数把其他类型元素转化为字符串。

Parse

Parse系列函数把字符串转化为其他类型。

正则表达式

正则表达式是一种进行模式匹配和文本操作的复杂而又强大的工具。go语言中内置regexp包进行正则表达式操作。

正则表达式使用

buf := "abc azc a7c aac 888 a9c tac"
// 1.解释规则,MustCompile会解析正则表达式,如果成功返回解释器
reg1 := regexp.MustCompile(`a.c`) // 反引号
if reg1 == nil { // 解析失败,返回nil
    fmt.Println("regexp error")
    return
}
// 2. 根据规则提取关键信息
result1 := reg1.FindAllStringSubmatch(buf, -1) // -1:匹配所有的
fmt.Println("result1 = ", result1)

提取字符串中所有小数

buf := "3.14 567 agsdg 1.23 7. 8.99 1sdljgl 6.66 "
reg1 := regexp.MustCompile(`\d+\.\d+`) // +匹配前一个字符的1次或多次

if reg1 == nil { // 解析失败,返回nil
    fmt.Println("regexp error")
    return
}

result1 := reg1.FindAllString(buf, -1) // -1:匹配所有的
fmt.Println("result1 = ", result1)

匹配网页有效字段

// 反引号=原生字符串
buf := `
<html lang="zh-CN">
<head>
    <title>Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国</title>
</head>
<div>哈哈<div/>
<div>嘻嘻<div/>
<div>呵呵<div/>
<div>呼呼<div/>
</html>
`
reg1 := regexp.MustCompile(`<div>(?s:(.*?))<div/>`) // (.*)只要符合条件的中间内容

if reg1 == nil { // 解析失败,返回nil
    fmt.Println("regexp error")
    return
}

result1 := reg1.FindAllString(buf, -1) // -1:匹配所有的
fmt.Println("result1 = ", result1)

// 过滤<></>
for _, text := range result1 {
    fmt.Println("text[0] = ", text[0]) // 带<></>
    fmt.Println("text[1] = ", text[1]) // 不带<></>
}

JSON处理

JSON(JavaScript Object Notation)是一种比XML更轻量级的数据交换格式。go语言内置encoding/json标准库。

通过结构体生成json

// 成员变量名 首字母必须大写
type IT struct{
    Company string
    Subject []string
    IsOk bool
    Price float64
}

func main() {
    // 定义一个结构体变量,同时初始化
    s := IT{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666, 666}
    
    // 编码,根据内容生成Json文本
    buf, err := json.Marshal(s) // 普通编码
    buf, err := json.MarshalIndent(s, "", " ") // 格式化编码
    if err != nil {
        fmt.Println("err = ", err)
        return
    }
    ftm.Println("buf = ", string(buf))
}

通过map生成json

func main() {
    // 创建一个map
    m := make(map[string]interface{}, 4)
    m["company"] = "itcast"
    m["subjects"] = []string{"Go", "C++", "Python", "Test"}
    m["isok"] = true
    m["price"] = 666.666
    
    // 编码成json
    result, err := json.Marshal(m) // 普通编码
    if err != nil {
        fmt.Println("err = ", err)
        return
    }
    ftm.Println("result = ", string(result))
}

struct_tag使用

type IT struct{
    Company string `json:"company"` // 二次编码
    Subject []string  `json:"-"` // 此字段不会输出到屏幕
    IsOk bool   `json:",string"` //转化为字符串输出
    Price float64
}

解析json到结构体

需要先设定类型格式,再按格式解析取值。

type IT struct{
    Company string `json:"company"` // 二次编码
}

func main() {
    jsonBut := `
    {
    "company": "itcast"
    }`
    
    var tmp IT // 定义一个结构体变量
    err := json.Unmarshal([]byte(jsonBuf), &tmp)
    if err != nil {
        fmt.Println("err = ", err)
        return
    }
    fmt.Printf("tmp = %+v\n", tmp)
    
    // 可以只取部分内容  新定义一个结构体即可
    type IT2 struct {
        Company string `json:"company"` // 二次编码
    }
    var tmp2 IT2 // 定义一个结构体变量
    err2 := json.Unmarshal([]byte(jsonBuf), &tmp2)
    if err2 != nil {
        fmt.Println("err2 = ", err2)
        return
    }
    fmt.Printf("tmp2 = %+v\n", tmp2)
}

解析json到map

解析操作简单,但是反推类型麻烦。

func main() {
    jsonBut := `
    {
    "company": "itcast"
    }`
    
    // 创建一个map
    m := make(map[string]interface{}, 4)
    
    err := json.Unmarshal([]byte(jsonBuf), &m)
    if err != nil {
        fmt.Println("err = ", err)
        return
    }
    fmt.Printf("m = %+v\n", m)
    
    var str string
    // 类型断言,值,是value类型
    for key, value := range m {
        // fmt.Printf("%v =====> %v\n", key, value)
        switch data := value.(type) {
            case string:
                str = data // 取对的类型的值
                fmt.Printf("map[%s]的值类型为 string,内容为 value = %s\n ", key, data)
            case bool:
                fmt.Printf("map[%s]的值类型为 bool,内容为 value = %v\n ", key, data)
            case float64:
                fmt.Printf("map[%s]的值类型为 float64,内容为 value = %f\n ", key, data)
            case []interface{}: // 接口切片类型
                fmt.Printf("map[%s]的值类型为 []interface,内容为 value = %f\n ", key, data)
        }
    }
}

文件操作

文件分类

  • 设备文件:
    屏幕(标准输出设备) fmt.Println() 往标准输出设备写内容
    键盘(标准输入设备) fmt.Scan() 从标准输入设备读取内容
  • 磁盘文件:放在存储设备上的文件

    1. 文本文件
    2. 二进制文件

为什么需要文件

内存断电后,内存中内容会清空,磁盘文件永久保存。

文件操作常用接口

  1. Create:根据文件名创建新文件,返回文件对象,默认权限0666;内部调用了OpenFile
  2. NewFile:根据文件描述符创建相应文件,返回文件对象
  3. Open:打开一个名称为name的文件,但是只读;内部调用了OpenFile
  4. OpenFile:【王者】可选择读写等
  5. Write:写入byte类型信息到文件
  6. WriteAt:在指定位置写入byte类型信息
  7. WriteString:写入string信息到文件
  8. Read:读取数据到b中
  9. ReadAt:从off开始读取数据到b中
  10. Remove:删除文件名为name的文件

标准设备文件的使用

package main
import {
    "fmt"
    "os"
}

func main() {
    // os.Stdout.Close() // 关闭后,无法输出
    fmt.Println("are u ok?") // 往标准输出设备(屏幕)写内容
    
    // 标准设备文件(os.Stdout),默认已经打开,用户可以直接使用
    os.Stdout.WriteString("are u ok?\n")
    
    // os.Stdint.Close() // 关闭后,无法输入
    var a int
    fmt.Println("请输入a:")
    fmt.Scan(&a) // 从标准输入设备中读取内容,放在变量a中
    fmt.Println("a = ",a)
}

文件的读写

package main
import {
    "fmt"
    "os"
    "io"
    "bufio"
}

// 写文件
func WriteString (path String) {
    // 新建文件
    f, err := os.Create(path)
    if err != nil {
        fmt.Println("err = ", err)
        return
    }
    
    // 使用完毕,需要关闭文件
    defer f.Close()
    
    var buf string
    for i:= 0; i < 10; i++ {
        // "i = 1\n",这个字符串存储在buf中
        buf = fmt.Sprintf("i = %d\n", i)
        f.WriteString(buf)
    }
}

// 读取文件
func ReadFile(path String) {
    // 打开文件
    f, err := os.Open(path)
    if err != nil {
        fmt.Println("err = ", err)
        return
    }
    // 关闭文件
    defer f.Close()
    
    buf := make([]byte, 1024*2) // 2k大小的切片
    
    // n代表从文件读取内容的长度
    n, err1 :=    f.read(buf)
    
    if err1 != nil && err1 != io.EOF { //文件出错,同时未到结尾
        fmt.Println("err1 = ", err1)
        return
    }
    
    fmt.Println("buf = ", string(buf[:n]))
}

// 每次读取一行 借助bufio
func ReadFileLine(path String) {
    // 打开文件
    f, err := os.Open(path)
    if err != nil {
        fmt.Println("err = ", err)
        return
    }
    // 关闭文件
    defer f.Close()
    
    // 新建一个缓冲区,把内容先放在缓冲区
    r := bufio.NewReader(f)
    
    for {
        buf, err := r.ReadBytes('\n') // 遇到'\n'结束读取,但是\n也读取进来了
        if err != nil{
            if err == is.EOF{ // 文件已结束
                break
            }
            fmt.Printf("err = ", err)
        }
        
        fmt.Printf("buf = #%s%\n", string(buf)) // buf字节切片转化为字符串
    }
    
}

func main() {
    path := "./demo.txt" // 文件路径
    WriteFile(path) // 写
    ReadFile(path) // 读
}

拷贝文件

实现一个拷贝文件的样例。
使用go build xxx.go 生成一个可执行文件
执行 ./copyFile x1.jpg x2.jpg 完成拷贝

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    list := os.Args // 获取命令行参数
    if len(list) != 3{ // 参数数量不足三个
        fmt.Println("usage: xxx srcFile dstFile")
        return
    }

    srcFileName := list[1]
    dstFileName := list[2]

    if srcFileName == dstFileName {
        fmt.Println("源文件和目的文件名称不能相同")
        return
    }

    // 只读方式打开源文件
    sF,err1 := os.Open(srcFileName)
    if err1 != nil {
        fmt.Println("err1", err1)
        return
    }

    // 新建目的文件
    dF,err2 := os.Create(dstFileName)
    if err2 != nil {
        fmt.Println("err2", err2)
        return
    }

    // 操作完毕后,关闭文件
    defer sF.Close()
    defer dF.Close()

    // 核心数据处理,从源文件读取内容,写入到目的文件,读多少写多少
    buf := make([]byte, 4*1024) //4k大小临时缓冲区
    for{
        n, err:= sF.Read(buf)
        if err != nil{
            if err == io.EOF{ // 文件读取完毕
                break
            }
            fmt.Println("err = ", err)
        }
        dF.Write(buf[:n])
    }
}

本文发表于2020年02月04日 23:28
阅读 2633 讨论 0 喜欢 1

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1