一、异常处理
1.err接口的使用
err1 := fmt.Errorf("%s", "this is normal error")
fmt.Println("err1=", err1)
err2 := errors.New("this is normal error,too")
fmt.Println("err2=", err2)
2.接口的应用
func MyDiv(a, b int) (result int, err error) {
err = nil
if b == 0 {
err = errors.New("分母不能为0")
return
} else {
result = a / b
}
return
}
func main() {
result, err := MyDiv(10, 0)
if err != nil {
fmt.Println("err=", err)
} else {
fmt.Println("result=", result)
}
}
3.显式调用panic函数
func testa() {
fmt.Println("aaaaaaaaaa")
}
func testb() {
//fmt.Println("bbbbbbbbbbbb")
//显示调用panic函数,导致程序中断
panic("this is a panic test")
}
func testc() {
fmt.Println("ccccccccccccccc")
}
func main() {
testa()
testb()
testc()
}
4.数组越界导致panic
func testa() {
fmt.Println("aaaaaaaaa")
}
func testb(x int) {
var a [10]int
a[x] = 111
//当x为20的时候就会导致数组越界,就会产生一个panic,导致程序崩溃
}
func testc() {
fmt.Println("ccccccccc")
}
func main() {
testa()
testb(20)
testc()
}
5.recover的使用
func testa() {
fmt.Println("aaaaaaaaaa")
}
func testb(x int) {
//设置recover
defer func() {
//recover()就可以打印出panic的错误信息
if err := recover(); err != nil {//产生了panic异常
fmt.Println(err)
}
}()//匿名函数用()调用
var a [10]int
a[x] = 111
}
func testc() {
fmt.Println("cccccccccccc")
}
func main() {
testa()
testb(20)
testc()
}
二、文本文件处理
1.字符串操作
//查看“hellogo”是否包含“hello”,包含返回true,否则返回false
fmt.Println(strings.Contains("hellogo", "hello"))//true
fmt.Println(strings.Contains("hello", "abc"))//false
//join组合
s := []string{"abc", "hello", "mike", "go"}
buf := strings.Join(s, "@")//用@把切片元素连接起来
fmt.Println("buf=", buf)
//index,查找子串的位置
fmt.Println(strings.Index("abcdhello", "hello"))
fmt.Println(strings.Index("abcd", "go"))//不包含的返回-1
//repeat重复显示
buf = strings.Repeat("go", 3)
fmt.Println("buf=", buf)
//split拆分,以指定分隔符拆分,存到切片中
buf = "Hello@abc@go@mike"
s2 := strings.Split(buf, "@")
fmt.Println("s2=", s2)
//trim去掉字符串两端的指定字符,存到字符串里
buf = strings.Trim(" are u ok? ", " ")
fmt.Println("buf=", buf)
//fields,去掉字符串空格,把元素放到切片中
s3 := strings.Fields(" are u ok? ")
fmt.Println("s3=", s3)
2.字符串转换
头文件"strconv"
//转换为字符串后追加到字节数组
slice := make([]byte, 0, 1024)
slice = strconv.AppendBool(slice, true)
//第二个数为要追加的数,第三个为指定10进制方式追加
slice = strconv.AppendInt(slice, 1234, 10)
slice = strconv.AppendQuote(slice, "abcdhello")
fmt.Println("slice=", string(slice))
//其他类型转换为字符串类型
var str string
str = strconv.FormatBool(false)
fmt.Println("str=", str)
//'f'指打印格式,以小数方式,-1指小数点位数(紧缩模式),64以float64位处理
str = strconv.FormatFloat(3.14, 'f', -1, 64)
fmt.Println("str=", str)
//整型转字符串,常用
str = strconv.Itoa(666)
fmt.Println("str=", str)
//字符串转其它类型
var flag bool
var err error
//字符串转布尔类型
flag, err = strconv.ParseBool("true1")
if err == nil {
fmt.Println("flag=", flag)
} else {
fmt.Println("err=", err)
}
//字符串转整型
a, _ := strconv.Atoi("567")
fmt.Println("a=", a)
3.正则表达式
头文件"regexp"
buf := "abc azc a7c aac 888 a9c tac"
//1.解释规则,它会解析这个正则表达式,如果成功就返回解析器
reg1 := regexp.MustCompile(`a[\d]c`)
if reg1 == nil {//解析失败,reg1=nil
fmt.Println("err=")
return
}
//2.根据规则提取关键信息
result1 := reg1.FindAllStringSubmatch(buf, -1)//-1是匹配所有的
fmt.Println("result=", result1)
buf := "83.14 567 abc 1.23 7. 9.0 asfg 6.78 7.9"
//解析正则表达式,+匹配前一个字符的1次或多次
reg := regexp.MustCompile(`\d+\.\d+`)
if reg == nil {
fmt.Println("MustCompile err")
return
}
//提取关键信息
result := reg.FindAllStringSubmatch(buf, -1)
fmt.Println("result=", result)
buf := `<html lang="zh-CN">
<head>
<title>Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<meta charset="utf-8">
<link rel="shortcut icon" href="/static/img/go.ico">
<link rel="apple-touch-icon" type="image/png" href="/static/img/logo2.png">
<meta name="author" content="polaris <polaris@studygolang.com>">
<meta name="keywords" content="中文, 文档, 标准库, Go语言,Golang,Go社区,Go中文社区,Golang中文社区,Go语言社区,Go语言学习,学习Go语言,Go语言学习园地,Golang 中国,Golang中国,Golang China, Go语言论坛, Go语言中文网">
<meta name="description" content="Go语言文档中文版,Go语言中文网,中国 Golang 社区,Go语言学习园地,致力于构建完善的 Golang 中文社区,Go语言爱好者的学习家园。分享 Go 语言知识,交流使用经验">
</head>
<div>哈哈</div>
<div>嘿嘿
你在吗
不在
</div>
<div>吼吼</div>
<div>测试</div>
<frameset cols="15,85">
<frame src="/static/pkgdoc/i.html">
<frame name="main" src="/static/pkgdoc/main.html" tppabs="main.html" >
<noframes>
</noframes>
</frameset>
</html>`
reg := regexp.MustCompile(`<div>(?s:(.*?))</div>`)
if reg == nil {
fmt.Println("MustCompile err")
return
}
result := reg.FindAllStringSubmatch(buf, -1)
for _, text := range result {
fmt.Println("text[1]=", text[1])//text[0]带<></>
}
三、JSON处理
1.通过结构体生成json
头文件“encoding/json”
//成员变量名首字母必须大写
type IT struct {
Company string
Subject []string
IsOk bool
Price float64
}
func main() {
//定义一个结构体变量,同时初始化
s := IT{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.6}
//编码,根据内容生成json文本
//json.Marshal(s)为非格式化编码
buf, err := json.MarshalIndent(s, "", " ")//格式化编码
if err != nil {
fmt.Println("err=", err)
return
}
fmt.Println("buf=", string(buf))
}
2.通过map生成json
//创建一个Map
m := make(map[string]interface{}, 4)
m["company"] = "itcast"
m["subjects"] = []string{"Go", "C++", "Python", "Test"}
m["isok"] = true
m["price"] = 666.6
//编码成json
result, err := json.MarshalIndent(m, "", " ")//格式化编码
if err != nil {
fmt.Println("err=", err)
return
}
fmt.Println("result=", string(result))
3.json解析到结构体
type IT struct {
Company string `json:"company"`//二次编码
Subjects []string `json:"subjects"`
IsOk bool `json:"isok"`
Price float64 `json:"price"`
}
func main() {
jsonBuf := `
{
"company":"itcast",
"subjects":[
"Go",
"C++",
"Python",
"Test"
],
"isok":true,
"price":666.666
}`
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 {
Subject []string `json:"subjects"`
}
var tmp2 IT2
err = json.Unmarshal([]byte(jsonBuf), &tmp2)
if err != nil {
fmt.Println("err=", err)
return
}
fmt.Printf("tmp2=%+v\n", tmp2)
}
4.json解析到map
jsonBuf := `
{
"company":"itcast",
"subjects":[
"Go",
"C++",
"Python",
"Test"
],
"isok":true,
"price":666.6
}`
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)
//str=string(m["company"])//err,无法直接转换
//通过类型断言来转换
var str string
for key, value := range m {
switch data := value.(type) {
case string:
str = data
fmt.Printf("map[%s]的值类型为string,value=%s\n", key, str)
case bool:
fmt.Printf("map[%s]的值类型为bool,value=%v\n", key, data)
case float64:
fmt.Printf("map[%s]的值类型为float64,value=%v\n", key, data)
case []interface{}:
fmt.Printf("map[%s]的值类型为[]string,value=%v\n", key, data)
}
}
四、文件操作
1.设备文件的使用
头文件"os"
//os.Stdout.Close()关闭后,无法输出
fmt.Println("are u ready?")//往标准输出设备(屏幕)写内容
//标准设备文件(os.Stdout),默认打开,用户可直接使用
os.Stdout.WriteString("are u ready?\n")
//os.Stdin.Close()关闭后就不能输入了
var a int
fmt.Println("请输入a:")
fmt.Scan(&a)//从标准输入设备中读取内容,放在a中
fmt.Println("a=", a)
2.文件的读写
头文件"io","os","bufio","fmt"
func WriteFile(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=%d\n,这个字符串存储在buf中
buf = fmt.Sprintf("i=%d\n", i)
n, err := f.WriteString(buf)
if err != nil {
fmt.Println("err=", err)
}
fmt.Println("n=", n)
}
}
func main(){
path:="./demo.txt"
WriteFile(path)
}
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]))
}
func main(){
path="./demo.txt"
ReadFile(path)
}
//每次读取一行
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 {//遇到\n就停止,但是\n也被读进来了
buf, err1 := r.ReadBytes('\n')
if err1 != nil {
if err1 == io.EOF {//文件结束,跳出循环,也就是读完了
break
}
fmt.Println("err1=", err1)
}
fmt.Printf("buf=#%s\n", string(buf))
}
}
func main() {
path := "./demo.txt"
ReadFileLine(path)
}
3.拷贝文件
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, err3 := sF.Read(buf)
if err3 != nil {
if err3 == io.EOF {//文件读到末尾是循环的结束条件
break
}
fmt.Println("err3=", err3)
}
dF.Write(buf[:n])//读多少,写多少
}
设备文件:
屏幕(标准输出设备)fmt.println往标准输出设备写内容
键盘(标准输入文件)fmt.Scan从标准输入设备读取内容
磁盘文件,放在存储设备上的文件
1)文本文件,以记事本打开,不是乱码
2)二进制文件,记事本打开,是乱码
内存掉电,程序结束,内存中的内容消失
文件存放在磁盘,掉电或程序结束,文件还是存在