一、异常
1、error
errors 包
package main
import (
"errors"
"fmt"
)
func main() {
result, err := MyDiv(1, 0)
if err != nil {
fmt.Println("err = ", err)
} else {
fmt.Println("result = ", result)
}
}
func MyDiv(a, b float32) (result float32, err error) {
if b == 0 {
// err = fmt.Errorf("分母不能为零")
err = errors.New("分母不能为零")
} else {
result = a / b
}
return
}
2、panic
调用panic会导致程序中断
package main
import (
"fmt"
)
func main() {
fmt.Println("1")
fmt.Println("2")
panic("test")
fmt.Println("3")
}
3、recover
(1)程序在崩溃时继续运行
(2)recover 仅在延迟函数 defer 中有效
(3)类似于java中的 try/catch
package main
import (
"fmt"
)
func main() {
fmt.Println("1")
test()
fmt.Println("3")
}
func test() {
// 在defer中使用recover,如果代码异常,不会崩溃
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
panic("panic 导致崩溃")
fmt.Println("2")
}
二、文本处理
1、字符串操作
strings 包
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("\nContains 返回是否包含指定字符串")
fmt.Println(strings.Contains("hello", "h"))
fmt.Println(strings.Contains("hello", "a"))
fmt.Println("\nJoin 将切片通过指定字符串链接起来")
s := []string{"h", "e", "l", "l", "o"}
fmt.Println(strings.Join(s, "-"))
fmt.Println("\nIndex 返回指定字符串的起始位置,不包含返回-1")
fmt.Println(strings.Index("hello", "h"))
fmt.Println(strings.Index("hello", "a"))
fmt.Println("\nRepeat 将字符串重复指定次数")
fmt.Println(strings.Repeat("hello", 3))
fmt.Println("\nSplit 将字符串按照指定次字符串拆分,中途相邻两个会被拆分成\"\"")
fmt.Println(strings.Split("hello", "l"))
fmt.Println("\nTrim 去掉字符串前后的指定字符串")
fmt.Println(strings.Trim("hello", "h"))
fmt.Println("\nFields 去掉字符串前后的空格,并将字符串去除空格拆分")
fmt.Println(strings.Fields(" he l lo "))
}
2、字符串转换
strconv 包
package main
import (
"fmt"
"strconv"
)
func main() {
// Append:将其他类型转换成字符串后追加到字节数组中
s := []byte{}
s = strconv.AppendBool(s, true)
fmt.Println(string(s))
// Format:其他类型转换成字符串
s1 := strconv.FormatBool(true)
fmt.Println(s1)
// Format:其他类型转换成字符串
b1, err := strconv.ParseBool("true")
fmt.Println(b1, err)
}
3、正则
(1)regexp 包
(2)regexp文档:https://studygolang.com/pkgdoc
单字符:
. 任意字符(标志s==true时还包括换行符)
[xyz] 字符族
[^xyz] 反向字符族
\d Perl预定义字符族
\D 反向Perl预定义字符族
[:alpha:] ASCII字符族
[:^alpha:] 反向ASCII字符族
\pN Unicode字符族(单字符名),参见unicode包
\PN 反向Unicode字符族(单字符名)
\p{Greek} Unicode字符族(完整字符名)
\P{Greek} 反向Unicode字符族(完整字符名)
结合:
xy 匹配x后接着匹配y
x|y 匹配x或y(优先匹配x)
重复:
x* 重复>=0次匹配x,越多越好(优先重复匹配x)
x+ 重复>=1次匹配x,越多越好(优先重复匹配x)
x? 0或1次匹配x,优先1次
x{n,m} n到m次匹配x,越多越好(优先重复匹配x)
x{n,} 重复>=n次匹配x,越多越好(优先重复匹配x)
x{n} 重复n次匹配x
x*? 重复>=0次匹配x,越少越好(优先跳出重复)
x+? 重复>=1次匹配x,越少越好(优先跳出重复)
x?? 0或1次匹配x,优先0次
x{n,m}? n到m次匹配x,越少越好(优先跳出重复)
x{n,}? 重复>=n次匹配x,越少越好(优先跳出重复)
x{n}? 重复n次匹配x
分组:
(re) 编号的捕获分组
(?P<name>re) 命名并编号的捕获分组
(?:re) 不捕获的分组
(?flags) 只是为了设置当前分组的标志,不会进行匹配
(?flags:re) 设置re段的标志,不捕获的分组
标志的语法为xyz(设置)、-xyz(清楚)、xy-z(设置xy,清楚z),标志如下:
I 大小写敏感(默认关闭)
m ^和$在匹配文本开始和结尾之外,还可以匹配行首和行尾(默认开启)
s 让.可以匹配\n(默认关闭)
U 非贪婪的:交换x*和x*?、x+和x+?……的含义(默认关闭)
边界匹配:
^ 匹配文本开始,标志m为真时,还匹配行首
$ 匹配文本结尾,标志m为真时,还匹配行尾
\A 匹配文本开始
\b 单词边界(一边字符属于\w,另一边为文首、文尾、行首、行尾或属于\W)
\B 非单词边界
\z 匹配文本结尾
转义序列:
\a 响铃符(\007)
\f 换纸符(\014)
\t 水平制表符(\011)
\n 换行符(\012)
\r 回车符(\015)
\v 垂直制表符(\013)
\123 八进制表示的字符码(最多三个数字)
\x7F 十六进制表示的字符码(必须两个数字)
\x{10FFFF} 十六进制表示的字符码
\* 字面值'*'
\Q...\E 反斜线后面的字符的字面值
字符族(预定义字符族之外,方括号内部)的语法:
x 单个字符
A-Z 字符范围(方括号内部才可以用)
\d Perl字符族
[:foo:] ASCII字符族
\pF 单字符名的Unicode字符族
\p{Foo} 完整字符名的Unicode字符族
预定义字符族作为字符族的元素:
[\d] == \d
[^\d] == \D
[\D] == \D
[^\D] == \d
[[:name:]] == [:name:]
[^[:name:]] == [:^name:]
[\p{Name}] == \p{Name}
[^\p{Name}] == \P{Name}
Perl字符族:
\d == [0-9]
\D == [^0-9]
\s == [\t\n\f\r ]
\S == [^\t\n\f\r ]
\w == [0-9A-Za-z_]
\W == [^0-9A-Za-z_]
ASCII字符族:
[:alnum:] == [0-9A-Za-z]
[:alpha:] == [A-Za-z]
[:ascii:] == [\x00-\x7F]
[:blank:] == [\t ]
[:cntrl:] == [\x00-\x1F\x7F]
[:digit:] == [0-9]
[:graph:] == [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]
[:lower:] == [a-z]
[:print:] == [ -~] == [ [:graph:]]
[:punct:] == [!-/:-@[-`{-~]
[:space:] == [\t\n\v\f\r ]
[:upper:] == [A-Z]
[:word:] == [0-9A-Za-z_]
[:xdigit:] == [0-9A-Fa-f]
示例:
package main
import (
"fmt"
"regexp"
)
func main() {
str := `
<div>1</div>
<div>2</div>
<div>3
4
5</div>
`
// 解析规则
// (.*?)匹配任意字符任意次数,越少越好
// (?s:())设置括号内的标志为s,s标志可以让 . 匹配\n
reg, err := regexp.Compile(`<div>(?s:(.*?))</div>`)
if err != nil {
fmt.Println(err)
return
}
// 获得所有符合条件的数据
result1 := reg.FindAllStringSubmatch(str, -1)
for _, result2 := range result1 {
fmt.Println(result2[1])
}
}
三、JSON
encoding/json 包
1、结构体与json操作
(1)要想用json编码,首字母必须大写
(2)可以通过 "json:"name"" 或 `json:"name"` 重命名
(3)通过 `json:",string"` 强制转成string
(4)json转换成结构体时,注意第二个参数是指针类型
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
// 要想用json编码,首字母必须大写
// 可以通过 "json:\"name\"" 或 `json:"name"`重命名
Name string `json:"name"`
// 通过 `json:",string"`强制转成string
Age int `json:"age,string"`
}
func main() {
p1 := Person{"LiMing", 18}
// 将结构体转成json
// j, e := json.Marshal(p1)
// 格式化编码
j, e := json.MarshalIndent(p1, "", " ")
if e != nil {
fmt.Println(e)
} else {
fmt.Println(string(j))
}
var p2 Person
p2Json := `{"name": "LiMing","age": "18"}`
// 注意第二个参数是指针
e2 := json.Unmarshal([]byte(p2Json), &p2)
if e2 != nil {
fmt.Println(e2)
} else {
fmt.Println(p2)
}
}
2、map与json操作
package main
import (
"encoding/json"
"fmt"
)
func main() {
m1 := make(map[string]interface{})
m1["name"] = "LiMing"
m1["age"] = 18
// j, e := json.Marshal(m1)
// 格式化编码
j, e := json.MarshalIndent(m1, "", " ")
if e != nil {
fmt.Println(e)
} else {
fmt.Println(string(j))
}
m2Json := `{"name": "LiMing","age": "18"}`
m2 := make(map[string]interface{})
e2 := json.Unmarshal([]byte(m2Json), &m2)
if e2 != nil {
fmt.Println(e2)
} else {
fmt.Println(m2)
}
}
四、文件
设备文件:
屏幕 -> 标准输出设备,fmt.Println() // 向标准输出设备写内容
键盘 -> 标准输入设备,fmt.Scan() // 从标准输入设备读取内容
磁盘文件:放在存储设备上的文件
文本文件 -> 用记事本打开,不是乱码
二进制文件 -> 用记事本打开,是乱码
api
(1)标准设备文件os.Stdout,默认已经打开,用户可以直接使用
(2)os.Create(),打开并创建文件,如果文件已经存在,则会清空
(3)Reader.readBytes()可以读到指定字节停止读取,指定字节也会被读进去
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
path := "./demo.txt"
WriteFile(path)
ReadFile(path)
ReadFileLine(path)
}
func WriteFile(path string) {
// 打开文件,新建文件,如果文件已经存在,就清空文件
f, e := os.Create(path)
if e != nil {
fmt.Println("打开文件失败:", e)
return
}
// 使用完毕关闭文件
defer f.Close()
var buf string
for i := 0; i < 5; i++ {
buf = fmt.Sprintf("第%d行\n", i+1)
fmt.Println(buf)
n, e2 := f.WriteString(buf)
if e2 != nil {
fmt.Println("写入内容失败:", e2)
} else {
fmt.Println("写入数据:", n)
}
}
}
func ReadFile(path string) {
// 打开文件
f, e := os.Open(path)
if e != nil {
fmt.Println("打开文件失败:", e)
return
}
// 使用完毕关闭文件
defer f.Close()
buff := make([]byte, 1024)
count, err := f.Read(buff)
if err != nil {
fmt.Println("文件读取失败:", err)
return
}
fmt.Println(string(buff[:count]))
}
func ReadFileLine(path string) {
// 打开文件
f, e := os.Open(path)
if e != nil {
fmt.Println("打开文件失败:", e)
return
}
// 使用完毕关闭文件
defer f.Close()
r := bufio.NewReader(f)
for {
b, err := r.ReadBytes('\n')
if err != nil {
if err == io.EOF {
fmt.Println("文件已经读完了")
return
}
fmt.Println("读取失败:", err)
return
}
fmt.Print(string(b))
}
}
网友评论