Go语言自学笔记(五)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_18800771/article/details/97391304

Go语言的异常处理:

通过err处理异常:非致命错误,实则变量和参数都是string类型。

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

err接口的应用:除法函数

func div (a,b int) (result int, err error){
    if b==0{
        ree=reeors.New("分母不能为0")
    }else {
        result = a/b
    }
    return 
}
func main(){
    result,err:=div(10,0)
    if err!=nil{
        fmt.Println(err)
    }else{
        fmt.Println(result)
    }
}    

通过panic处理异常:程序致命错误。

显式调用panic导致程序中断:

func test(){
    panic("this is a panic test")        //自动打印
}

panic函数的应用:数组越界错误。

func test(x int){
    var a [10]int
    a[x]=1    //数组越界则会产生panic错误
}

通过recover处理错误:必须要放在defer后面使用,不会导致程序崩溃,可以打印错误信息。

func test(x int){
    defer func(){    //匿名函数判断错误
        if err := recover(); err!=nil{
            fmt.Println(err)
        }
    }()
    var a [10]int
    a[x]=1

文本和文件的处理:

字符串处理:

字符串长度处理:需要导入包strings

import "strings"
func Contains (s, substr string) bool
//功能:字符串s中是否包含substr,返回bool值
func Join (a []string, sep string) string
//功能:字符串链接,把slice a通过sep链接起来
func Index (s, sep string) int
//功能:在字符串s中查找sep所在位置,返回位置值,找不到返回-1
func Repeat (s string, count int) string
//功能:重复s字符串count次,最后返回重复的字符串
func Replace (s, old, new string, n int) string
//功能:在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小宇0表示全部替换
func Split (s,sep string) []string
//功能:把s字符串按照sep分割,返回slice
func Trim (s string, cutset string) string
//功能:在s字符串的头部和尾部取出cutset指定的字符串
func Fields (s sting) []string
//功能:取出s字符串的空格符,并且按照空格分割返回slice

字符串的转换:需要导入包strconv

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

str:=make([]byte, 0, 100)
str=strconv.AppendInt(str, 4567, 10)    //整数转换常用,10代表以十进制追加
str=strconv.AppendBool(str, false)
str=strconv.AppendQuote(str, "abc")
str=strconv.AppendQuoteRune(str, "单")

Format系列函数把其他类型的转换为字符串。

a:=strconv.FormatBool(false)
b:=strconv.FormatInt(1234,10)
c:=strconv.FormatUint(1234,10)
d:=strconv.Itoa(1234)

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

flag, err:=strconv.ParseBool("true")    //err返回报错信息
aint, err:=strconv.Atoi("567")    //整型转换

正则表达式:模式匹配和文本操纵,比strings包来进行搜索,替换,解析更为强大,但效率较低,不够清晰可读性差。

需要导入包“regexp”,实现了正则表达式的搜索。正则表达式采用RE2语法(出了\c,\C),和Perl、Python等语言的正则基本一致。

可以通过以下网址查找详细信息:

http://code.google.com/p/re2/wiki/Syntax

https://studygolang.com/pkgdoc 

提取字符串中想相应字段:

package main
import "fmt"
import "regexp"
func main(){
    buf := `abcbaxcaacc`    //可以通过反引号``也可以通过双引号"",反引号代表原生字符串
    //解析规则,它会解析正则表达式,如果成功返回解释器*Regexp
    reg1 := regexp.MustCompile(`a.c`)
    if reg==nil{    //解析失败
        fmt.Println("err")
        return
    }
    //根据规则提取关键信息
    result := reg1.FindAlllStringSubmatch(buf, -1)    //匹配个数,-1匹配全部
}
buf := `ab9cbaxcb3cc`    
reg1 := regexp.MustCompile(`b[0-9]c`)    //或用`b\dc`
if reg==nil{
    fmt.Println("err")
    return
}
result := reg1.FindAlllStringSubmatch(buf, -1)

 提取字符串中的所有小数:

buf := `43.14 5. 7. .8 46.3 3.14 25.22`    
reg1 := regexp.MustCompile(`\d+\.\d+`)    //+匹配前一个字符的1次或多次
if reg==nil{
    fmt.Println("err")
    return
}
//result := reg1.FindAlllString(buf, -1)
result := reg1.FindAlllStringSubmatch(buf, -1)    //详细打印

正则表达式读取网页:

buf := `/*网页源代码*/`    
reg1 := regexp.MustCompile(`<div>(.*)</div>`)    //取标题
reg2 := regexp.MustCompile(`<div>(?s:(.*))</div>`)    //匹配换行
reg2 := regexp.MustCompile(`<div>(?s:(.*?))</div>`)    //重复匹配,越少越好
if reg==nil{
    fmt.Println("err")
    return
}
//result := reg1.FindAlllString(buf, -1)
result := reg1.FindAlllStringSubmatch(buf, -1)    //详细打印
//迭代器过滤<></>
for _,text := range result {
    //fmt.Println("text[0]")        //带<></>
    fmt.Println("text[1]")         //不带<></>

json处理:数据格式的交换文本,可前往www.json.cn进行格式检查。需要导入包:“encoding/json”

生成(编码)json文本信息:

通过结构体生成文本:

package main
import "encoding/json"
import "fmt"
type IT struct {    //成员变量名字一定要大写
    Company string
    Subjects []string
    IsOk bool
    Price sloat64
}
func main(){
    s:=IT{"itcast",[]string{"Go","C++","Python","Test"},true,666.666}  //定义初始化结构体
    buf, err := json.Marshal(s)    //编码,根据内容生成json文本
    //buf, err := json.MarshalIndent(s, "", "    ")    //格式化编码,格式更加准确.""空字符."    "tap
    if err != nil{
        fmt.Println(err)
        return 
    }
    fmt.Println(string(buf))
    
}

二次编码:

type IT struct {
    Company string    `json:"company"`    //首字母小写输出
    Subjects []string    `json:"-"`    //不输出到屏幕
    IsOk bool    `json:",string"`    //转换成字符串输出
    Price sloat64
}

通过map生成文本:不同类型运用空接口

m:=make(map[string]interface{}, 4)    //创建map
m["company"] = "itcast"
m["subjects"] = []string{"Go","C++","Python","Test"}
m["isok"] = true
m["price"] = 666.666
result, err := json.MarshalIndent(s, "", "    ")    //格式化编码,格式更加准确.""空字符."    "tap
if err != nil{
    fmt.Println(err)
    return 
}
fmt.Println(string(result))

编码反过程:解码

json解析到结构体:

package main
import "encoding/json"
import "fmt"
type IT struct {
    Company string        `json:"company"`
    Subjects []string        `json:"subjects"`
    IsOk bool        `json:"isok"`
    Price sloat64        `json:"price"`
}
func main(){
    jsonBuf := `/*json文本*/`
    var tmp IT
    err := json.Unmarshal([]byte(jsonBuf), &tmp)
    if err != nil{
        fmt.Println(err)
        return 
    }
    fmt.Printf("%+v", tmp)
}

如果对单一的json文段解码:可重新定义一个结构体并只包含单一文段。

json解析到map:解析简单但判断类型更为复杂

m:=make(map[string]interface{}, 4)
err := json.Unmarshal([]byte(jsonBuf), &m)
if err != nil{
    fmt.Println(err)
    return 
}
fmt.Printf("%+v", m)
//取字段内容,只能通过类型断言,较为复杂。
for key, value := range m{
    switch data:=value.(type){
    case string:
        fmt.Printf("map[%s]的值类型为string,值为:%s\n",key,data)
    case bool:
        fmt.Printf("map[%s]的值类型为bool,值为:%v\n",key,data)
    case float64:
        fmt.Printf("map[%s]的值类型为float64,值为:%f\n",key,data)
    case []string:
        fmt.Printf("map[%s]的值类型为[]string,值为:%v\n",key,data)
    case []interface{}:
        fmt.Printf("map[%s]的值类型为[]nterface{},值为:%v\n",key,data)
    }
}

文件分类:

设备文件:

1.屏幕(标准输出设备)fmt.Println()  向标准输出设备输出内容

2.键盘(标准输入设备)fmt.Scan()  从标准输入设备读取内容

磁盘文件:在磁盘上存储的文件:

1.文本文件:可以直接通过记事本看到正常内容。

2.二进制文件:不可以直接以记事本形式打开,打开后只能看到乱码。

问什么需要文件储存内容:内存掉电之后数据就会丢失,程序结束内存中的内容也会消失。磁盘文件在程序结束后,文件内容仍然存在。

os.Stdout.Close()    //关闭标准设备文件输出,默认打开
fmt.Println()    //无法使用
os.Studout.WriteString()    //无法使用

os.Stdin.Close()    //关闭标准设备输入,默认打开
fmt.Scan()    //无法使用

文件操作:需要导入包“os”

import "os"

文件的创建:

func Create(name string) (file *File, err Error)
//根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的
func NewFile(fd unitptr, name string) *File
//根据文件描述符创建相应的文件,返回一个文件对象

文件的打开:

func Open(name string) (file *File, err Error)
//该方法打开一个名称为name的文件,但是是制度方式,内部实现其调用了OpenFile
func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
//打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限

文件的写入:

func (file *File) Write(b []byte) (n int, err Error)
//写入byte类型的信息到文件
func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
//在指定位置开始写入byte类型的信息
func (file *File) WriteString(s string) (ret int, err Error)
//写入string信息到文件

文件的读取:

func (dile *File) Read(b []byte) (n int, err Error)
//读取数据到b中
func (dile *File) ReadAt(b []byte, off int64) (n int, err Error)
//从off开始读取数据到b中

文件的删除:

func Remove(name string) Error
//调用改函数就可以删除文件名为name的文件

文件的创建以及写入实例:

package main
import "fmt"
import "os"
func WriteFile(path string) {
	f, err := os.Create(path) //新建文件
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close() //文件关闭
	buf := fmt.Sprintf("输入文本")
	n, errx := f.WriteString(buf)
	if errx != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(n)    //文件长度
}
func main() {
	path := "./demo.txt"    //文件路径:程序当前目录下的demo
	WriteFile(path)
}

文件的读取实例:

package main
import "fmt"
import "os"
import "io"
func ReadFile(path string) {
	f, err := os.Open(path)          //打开文件
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()
	buf := make([]byte, 1024*2) //2kB大小
	n, errx := f.Read(buf)
	if errx != nil && errx != io.EOF { //文件未到结尾出错
		fmt.Println(err)
		return
	}
	fmt.Println(string(buf[:n]))
}
func main() {
	path := "./demo.txt"
	ReadFile(path)
}

借助bufio实现按行读取内容:

package main
import "fmt"
import "os"
import "io"
import "bufio"
func ReadFileLine(path string) {
	f, err := os.Open(path)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()
	r := bufio.NewReader(f) //新建一个缓存区暂存内容
	for {
		//以换行分割,'\n'换行也会一并被读入
		buf, errx := r.ReadBytes('\n') //以\n分割并标记
		if errx != nil {
			if errx == io.EOF { //文件读取完毕
				fmt.Println(string(buf))
				break
			}
			fmt.Println(err)
		}
		fmt.Println(string(buf))
	}
}
func main() {
	path := "./demo.txt"
	ReadFileLine(path)
}

文件案例:拷贝文件:

package main

import "fmt"
import "os"
import "io"

func main() {
	list := os.Args //获取命令行参数
	if len(list) != 3 {
		fmt.Println("err:文件参数不足3")
		return
	}
	srcFileName := list[1]
	dstFileName := list[2]
	if srcFileName == dstFileName {
		fmt.Println("起始文件与目标文件不能同名")
		return
	}
	sF, err1 := os.Open(srcFileName) //只读方式打开源文件
	if err1 != nil {
		fmt.Println("err:", err1)
		return
	}
	dF, err2 := os.Create(dstFileName) //新建目的文件
	if err1 != nil {
		fmt.Println("err:", err2)
		return
	}
	defer sF.Close() //关闭文件
	defer dF.Close()
	//核心处理,从源文件读取内容写入目标文件
	buf := make([]byte, 4*1024) //4kB大小临时缓冲区
	for {
		n, err := sF.Read(buf) //从源文件读取内容
		if err != nil {
			if err == io.EOF { //文件读取完毕
				dF.Write(buf[:n])
				break
			}
			fmt.Println("err:", err)
		}
		dF.Write(buf[:n]) //写入目标文件
	}
}

通过命令行:go run name.go file1.type file2.type完成拷贝。

猜你喜欢

转载自blog.csdn.net/qq_18800771/article/details/97391304