前言
这是我学习Go语法的笔记。由于有C和Python的基础,上手Go很快。笔记很粗糙,好在自己够用。
此篇包括了Go相关的:错误处理,字符串处理,正则,JSON,文本操作。
异常处理
error
官方errors包源码如下:
// Package errors implements functions to manipulate errors.
package errors
// New returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
即New()
函数是返回一个errorString类型的变量,这种类型的变量拥有Error()
方法,用法如下:
err := errors.New("this is a err")
fmt.Println(err.Error())
// 输出:
this is a err
另一种error来自于fmt包:
err := fmt.Errorf("%s", "this is error in fmt")
fmt.Println(err)
// 输出:
this is error in fmt
一个完整的errors的使用:
func myDiv(a, b int) (result int, err error) {
if b == 0 {
err = errors.New("除数不能为0")
} else {
result = a / b
}
return
}
func main() {
result, err := myDiv(10, 0)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("结果为:", result)
}
}
panic
致命错误panic()
recover
必须放在defer后面使用。恢复程序。
func testb(x int) {
defer func() {
if err := recover(); err != nil { // 只在出现panic错误的起作用
fmt.Println(err)
}
}()
var a[10] int
a[x] = 111 // 当x>=10之后,属于越界访问
}
func main() {
testb(100)
}
// 输出:
runtime error: index out of range
当没有错误时,recover()
函数返回nil,如果有错误,则返回错误信息。
字符串处理
字符串操作(strings)
Contains
// 前者(str)是否包含后者(substr) fmt.Println(strings.Contains("hello world", "hello")) // true fmt.Println(strings.Contains("hello world", "abc")) // false
Join
// 组合,类似Python中的 "".join() s := []string{"abc", "zty", "guan", "suanle"} fmt.Println(strings.Join(s, ",")) // abc,zty,guan,suanle
Index
// 子字符串在字符串中出现的位置,第一个字符的索引,不存在返回-1 fmt.Println(strings.Index("helloworld", "wor")) // 5 fmt.Println(strings.Index("helloworld", "go")) // -1
Repeat
// 重复次数 buf := strings.Repeat("zty", 3) fmt.Println(buf) // ztyztyzty
Replace
// 替换 fmt.Println(strings.Replace("abcbe", "b", "!", 2)) // a!c!e
Split
// 按指定sep拆分,返回切片 str := "zty-zty-zty" result := strings.Split(str, "-") fmt.Println(result) // [zty zty zty]
Trim
// 去掉两头 words := "fre--fre--fre" fmt.Println(strings.Trim(words, "fre")) // --fre--
Fields
// 去除字符串中的所有空格,返回切片 fmt.Println(strings.Fields(" ef er 3 op")) // [ef er 3 op]
字符串转换(strconv)
Append
// 转换成字符串后追加到字节数组 func main() { // 定义一个切片 slice := make([]byte, 0, 1024) // 追加一个bool类型的变量 slice = strconv.AppendBool(slice, true) // 追加一个1234的值,10进制 slice = strconv.AppendInt(slice, 1234, 10) // 追加一个字符串 slice = strconv.AppendQuote(slice, "hello") fmt.Printf("%s", slice) // 输出:true1234"hello" }
Format
// 其他类型转化成字符串 // prec控制精度(排除指数部分): // 对'f'、'e'、'E',它表示小数点后的数字个数; // 对'g'、'G',它控制总的数字个数。 // 如果prec 为-1,则代表使用最少数量的、但又必需的数字来表示f。 str := strconv.FormatFloat(3.14, 'f', -1, 64) fmt.Printf("内容:%s, 类型:%T", str, str) // 输出:内容:3.14, 类型:string
// 整型转字符串
num := 512
numStr := strconv.Itoa(num)
fmt.Printf("numStr的类型是 %T\n", numStr)
// 输出:numStr的类型是 string
Parse
// 字符串转换成其他类型 // 字符串转bool flag, _ := strconv.ParseBool("true") fmt.Printf("flag = %v,其类型为:%T\n", flag, flag) // 字符串转整型 // base: 取值2-36,表示进位制。如果base=0,根据字符串前缀判断 num, _ := strconv.ParseInt("512", 10, 64) fmt.Printf("num = %d,其类型为:%T\n", num, num) // num = 512,其类型为:int64 anotherNum, _ := strconv.ParseInt("0xA", 0, 64) fmt.Printf("anotherNum = %d,其类型为:%T\n", anotherNum, anotherNum) // anotherNum = 10,其类型为:int64 // 另一种字符串转整型 newNum, _ := strconv.Atoi("512") fmt.Printf("newNum = %d,其类型为:%T\n", newNum, newNum) // newNum = 512,其类型为:int
正则
package main
import (
"fmt"
"regexp" // 正则包
)
func main() {
str := "12334dew32kor435md.fer"
// 生成规则
reg := regexp.MustCompile( `\d+`)
// reg为空时表示失败
if reg != nil {
fmt.Println(reg)
}
// -1表示匹配所有,1表示只匹配一个
res := reg.FindAllString(str, -1) // 匹配
fmt.Println(res)
// 输出:[12334 32 435]
}
JSON
编码
通过结构体生成JSON:
package main
import (
"encoding/json"
"fmt"
)
// 成员变量名首字母必须大写
type IT struct {
Company string
Subject []string
IsOK bool
Price float64
}
func main() {
ajson := IT{"alibaba", []string{"C++", "Go", "Python"}, true, 512}
// 编码。生成json格式的文本
buf, _ := json.MarshalIndent(ajson, "", " ") // 保留缩进
// buf, _ := json.Marshal(ajson) // 无缩进信息
fmt.Println(string(buf))
}
// 输出:
{
"Company": "alibaba",
"Subject": [
"C++",
"Go",
"Python"
],
"IsOK": true,
"Price": 512
}
// 二次编码
type IT struct {
Company string `json:"-"` // 不要输出到屏幕
Subject []string `json:"subject"` // 变量名以subject的方式显示
IsOK bool `json:",string"` // 键值以字符串的格式显示
Price float64 `json:",string"`
}
// 对应输出:
{
"subject": [
"C++",
"Go",
"Python"
],
"IsOK": "true",
"Price": "512"
}
通过map生成JSON:
func main() {
ajson := make(map[string]interface{}, 4)
ajson["company"] = "alibaba"
ajson["subject"] = []string{"C++", "Go", "Python"}
ajson["isok"] = true
ajson["price"] = 512
res, _ := json.Marshal(ajson)
fmt.Println(string(res))
}
// 输出:
{"company":"alibaba","isok":true,"price":512,"subject":["C++","Go","Python"]}
解码
对于结构体:
type IT struct {
Company string `json:"company"`
Subject []string `json:"subject"`
Isok bool `json:"isok"`
Price float64 `json:"price"`
}
func main() {
jsonstr := `{"company":"alibaba","isok":true,"price":512,"subject":["C++","Go","Python"]}`
var it IT
// 第二个参数必须是指针,这样才能改变里面的值
if err := json.Unmarshal([]byte(jsonstr), &it); err != nil {
fmt.Println(err)
} else {
fmt.Println(it)
}
}
对于map:
func main() {
jsonstr := `{"company":"alibaba","isok":true,"price":512,"subject":["C++","Go","Python"]}`
jsonmap := make(map[string]interface{}, 4) // 切片
if err := json.Unmarshal([]byte(jsonstr), &jsonmap); err != nil {
fmt.Println(err)
} else {
fmt.Println(jsonmap)
}
var (
str string
slice []interface{}
)
// 通过类型断言(反推类型),取出每个字段的内容
for _, value := range jsonmap{
switch data := value.(type) {
case string:
str = data
case []interface{}: // 注意为空类型的切片,而不是字符串切片
slice = data
}
}
fmt.Println(str) // 输出:alibaba
fmt.Println(slice) // 输出:[C++ Go Python]
}
文本操作
写内容:
func WriteToFile(path string) {
f , _ := os.Create(path) // 创建一个文件
for i := 0; i < 10; i++ {
s := fmt.Sprintf("this is %d\n", i)
_, err := f.WriteString(s) // 写入字符串
if err != nil {
fmt.Printf("error: %v", err)
return
}
}
defer f.Close()
}
读内容:
func ReadFromFile(path string) {
f, _ := os.Open(path) // 打开一个文件
content := make([]byte, 1024 * 2) // 创建一个切片,存放读取内容
// n 表示读取了多少个字节
n, err := f.Read(content) // 读取内容
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(content[:n])) // content[:n] 只打印有内容的部分
defer f.Close()
}
注意:os.Create()
与os.Open()
都是对os.OpenFile()
做了封装。
结合bufio一行一行的读取:
f, _ := os.Open(path)
bf := bufio.NewReader(f)
for {
// 以`\n`来读
// buf存储读取到的内容,包含`\n`
buf, err := bf.ReadBytes('\n')
if err != nil {
// 文件内容读取完
if err == io.EOF {
break
}
}
fmt.Printf(string(buf))
}
defer f.Close()
还不快抢沙发