14 错误处理
常用:使用一个单独的返回值来传递消息
go语言的处理方式可以清晰地知道哪个函数返回了错误,并能使用简单的if...else...处理错误
函数里面:
函数的返回值类型中,在后面加一个error(代表函数可能返回错误)
return 需要同时return两个值:
- 出现错误:return nil 和 error
- 没有错误:return 结果 和 nil
package main
import (
"fmt"
"errors"
)
type user struct{
name string
password string
}
func findUser(users []user,name string)(v *user, err error){
fmt.Println(users)
// [{Tom 0001} {Jack 0002}]
// [{Tom 0001} {Jack 0002}]
for _,u := range users{
if u.name == name{
return &u,nil
}
}
return nil, errors.New("not found")
}
func main(){
u,err := findUser([]user{{"Tom","0001"},{"Jack","0002"}},"Jack")
if err != nil{
fmt.Println(err)
return
}
fmt.Println(u.name) // Jack
if u,err := findUser([]user{{"Tom","0001"},{"Jack","0002"}},"Mary");err != nil{
fmt.Println(err) // not found
return
}else{
fmt.Println(u.name)
}
}
15 字符串操作
len(str):字符串长度(注意中文字符长度!!!)
r := []rune(str):处理字符串遍历时出现中文的问题
n,err := strconv.Atoi("123"):字符串转整数
str = strconv.Itoa(12345):整数转字符串
var bytes = []byte("hello world"):字符串转[]byte切片
str := string([]byte{97,98,99}):[]byte 转字符串
str = strconv.FormatInt(123,2):十进制转二进制
strings.Contains("hello world", "world"):查找字符串中是否包含指定字符串
strings.Count("hello world", "l"):统计字符串中有几个指定的字符串
strings.EqualFold("acBD", "AcBd"):不区分大小写的字符串比较
strings.Index("hello world", "o"):返回字符串中第一次出现指定字符串的index值,否则返回-1
strings.LastIndex("hello world", "o"):返回字符串中最后一次出现指定字符串的index值,否则返回-1
strings.Replace("hello world, hello Solar system", "hello", "hi",n):n可以指定替换几个,n=-1表示全部替换
strings.Split("hello world, hello Solar system", ","):将字符串拆成字符串数组
strings.ToLower("Hello World"):将字符串字母转为小写
strings.ToUpper("Hello World"):将字符串字母转为大写
strings.TrimSpace(" hello world, hello Solar system "):去除字符串左右两边的空格
strings.Trim(",,,,,hello world, hello Solar system,,,,,,,", ","):去除字符串左右两边的指定字符
strings.TrimRight(",,,,,hello world, hello Solar system,,,,,,,", ","):去除字符串右边的指定字符
strings.TrimLeft(",,,,,hello world, hello Solar system,,,,,,,", ","):去除字符串左边的指定字符
strings.HasPrefix("hello world, hello Solar system", "hello"):判断字符串是否以指定字符串开头
strings.HasSuffix("hello world, hello Solar system", "tem"):判断字符串是否以指定字符串结尾
strings.Join([]string{"he","llo"," ","wor","ld","!"}, ""):将多个字符串连接成一个字符串
strings.Repeat("hello", 5):重复字符串
package main
import (
"fmt"
"strconv"
"strings"
)
func main(){
fmt.Println(len("hello world")) // 11
fmt.Println(len("你好,世界")) // 15
r := []rune("hello,世界")
for i:=0;i<len(r);i++{
fmt.Printf("r的第%d个字符是:%c\n",i,r[i])
// r的第0个字符是:h
// r的第1个字符是:e
// r的第2个字符是:l
// r的第3个字符是:l
// r的第4个字符是:o
// r的第5个字符是:,
// r的第6个字符是:世
// r的第7个字符是:界
}
n, err := strconv.Atoi("123")
if err != nil {
fmt.Println("转换错误", err)
} else {
fmt.Println("转成的结果是:", n) // 转成的结果是: 123
}
fmt.Printf("转成的结果是:%v,数据类型是:%T\n",strconv.Itoa(12345),strconv.Itoa(12345))
// 转成的结果是:12345,数据类型是:string
fmt.Println([]byte("hello world")) // [104 101 108 108 111 32 119 111 114 108 100]
fmt.Println(string([]byte{97,98,99})) // abc
fmt.Println(strconv.FormatInt(123,2)) // 1111011
fmt.Println(strings.Contains("hello world", "world")) // true
fmt.Println(strings.Count("hello world", "l")) // 3
fmt.Println(strings.EqualFold("acBD", "AcBd")) // true
fmt.Println(strings.Index("hello world", "o")) // 4
fmt.Println(strings.LastIndex("hello world", "o")) // 7
fmt.Println(strings.Replace("hello world, hello Solar system", "hello", "hi",-1)) // hi world, hi Solar system
fmt.Println(strings.Split("hello,world,hello,Solar,system", ",")) // [hello world hello Solar system]
fmt.Println(strings.ToLower("Hello World")) // hello world
fmt.Println(strings.ToUpper("Hello World")) // HELLO WORLD
fmt.Println(strings.TrimSpace(" hello world, hello Solar system ")) // hello world, hello Solar system
fmt.Println(strings.Trim(",,,,,hello world, hello Solar system,,,,,,,", ",")) // hello world, hello Solar system
fmt.Println(strings.TrimRight(",,,,,hello world, hello Solar system,,,,,,,", ",")) // ,,,,,hello world, hello Solar system
fmt.Println(strings.TrimLeft(",,,,,hello world, hello Solar system,,,,,,,", ",")) // hello world, hello Solar system,,,,,,,
fmt.Println(strings.HasPrefix("hello world, hello Solar system", "hello")) // true
fmt.Println(strings.HasSuffix("hello world, hello Solar system", "tem")) // true
fmt.Println(strings.Join([]string{"he","llo"," ","wor","ld","!"}, "")) // hello world!
fmt.Println(strings.Repeat("hello", 5)) // hellohellohellohellohello
}
16 字符串格式化
可以使用printf和%v打印任意类型的变量,不需要区分数字字符串
可以使用%+v打印详细结果,或%#v打印更详细结果
package main
import "fmt"
type point struct{
x,y int
}
func main(){
s := "hello"
n := 123
p := point{1,2}
fmt.Println(s,n) // hello 123
fmt.Println(p) // {1 2}
fmt.Printf("s=%v\n",s) // s=hello
fmt.Printf("n=%v\n",n) // n=123
fmt.Printf("p=%v\n",p) // p={1 2}
fmt.Printf("p=%+v\n",p) // p={x:1 y:2}
fmt.Printf("p=%#v\n",p) // p=main.point{x:1, y:2}
f := 3.141592653579
fmt.Println(f) // 3.141592653579
fmt.Printf("保留三位小数:%.3f\n",f) // 保留三位小数:3.142
}
17 JSON处理
已有的结构体:
保证每个字段的第一个字母是大写,即公开字段,则结构体可用JSON.marshaler序列化,变成JSON字符串
序列化的字符串:
能用JSON.unmarshaler去反序列化到一个变量中,序列化的字符串是大写字母开头,可以使用json.tag等语法修改字段名
package main
import (
"fmt"
"encoding/json"
)
type userInfo struct{
Name string
Age int `json:"age"`
Hobby []string
}
func main(){
a := userInfo{Name: "Tom",Age: 18, Hobby: []string{"basketball","soccer"}}
buf, err := json.Marshal(a)
if err != nil{
panic(err)
}
fmt.Println(buf) // [123 34 78 97 109 101 34 58 34 84 111 109 34 44 34 97 103 101 34 58 49 56 44 34 72 111 98 98 121 34 58 91 34 98 97 115 107 101 116 98 97 108 108 34 44 34 115 111 99 99 101 114 34 93 125]
fmt.Println(string(buf)) // {"Name":"Tom","age":18,"Hobby":["basketball","soccer"]}
buf, err = json.MarshalIndent(a,"","\t")
if err != nil{
panic(err)
}
fmt.Println(string(buf))
// {
// "Name": "Tom",
// "age": 18,
// "Hobby": [
// "basketball",
// "soccer"
// ]
// }
var b userInfo
err = json.Unmarshal(buf,&b)
if err != nil{
panic(err)
}
fmt.Println(b) // {Tom 18 [basketball soccer]}
fmt.Printf("%#v\n",b) // main.userInfo{Name:"Tom", Age:18, Hobby:[]string{"basketball", "soccer"}}
}
18 时间处理
- 使用time.Now()获取当前时间
- 使用time.Date()构造带时区的时间
- 使用.Sub()对两个时间进行减法
- 使用.Unix()获得时间戳
- time.Format("2006-01-02 15:04:05")
- time.Parse("2006-01-02 15:04:05", "...")
package main
import (
"fmt"
"time"
)
func main(){
now := time.Now()
fmt.Println(now) // 2023-05-14 17:09:56.3776997 +0800 CST m=+0.002607101
t := time.Date(2023,4,1,13,20,56,0,time.UTC)
t2 := time.Date(2023,4,1,14,23,56,0,time.UTC)
fmt.Println(t) // 2023-04-01 13:20:56 +0000 UTC
fmt.Println(t.Year(),t.Month(),t.Day(),t.Hour(),t.Minute()) // 2023 April 1 13 20
fmt.Println(t.Format("2006-01-02 15:04:05")) // 2023-04-01 13:20:56
diff := t2.Sub(t)
fmt.Println(diff) // 1h3m0s
fmt.Println(diff.Minutes(),diff.Seconds()) // 63 3780
t3,err := time.Parse("2006-01-02 15:04:05", "2023-04-01 13:20:56")
if err != nil{
panic(err)
}
fmt.Println(t3 == t) // true
fmt.Println(now.Unix()) // 1684055521
}
19 数字解析——字符串和数字转换
字符串和数字类型转换需引入strconv包(string convert)
- strconv.parseInt()或strconv.parseFloat()将字符串转为数字
- strconv.Atoi()将十进制字符串转为数字
- strconv.Itoa()将数字转为字符串
- strconv.FormatInt()进行进制转换
package main
import (
"fmt"
"strconv"
)
func main(){
f, _ := strconv.ParseFloat("3.1415",64)
fmt.Println(f) // 3.1415
n, _ := strconv.ParseInt("111",10,64)
fmt.Println(n) // 111
n, _ = strconv.ParseInt("0x1000",0,64)
fmt.Println(n) // 4096
num := strconv.FormatInt(15,16)
fmt.Println(num) // f
n2, err := strconv.Atoi("AAA")
if err != nil {
fmt.Println("转换错误", err) // 转换错误 strconv.Atoi: parsing "AAA": invalid syntax
} else {
fmt.Println("转成的结果是:", n2)
}
n3, _ := strconv.Atoi("123")
fmt.Println(n3) // 123
fmt.Printf("转成的结果是:%v,数据类型是:%T\n",strconv.Itoa(12345),strconv.Itoa(12345))
// 转成的结果是:12345,数据类型是:string
}
20 进程信息
go中可以使用os.Args得到程序执行时的指定的命令行参数
package main
import (
"fmt"
"os"
"os/exec"
)
func main(){
fmt.Println(os.Args) // [......go-build1188148154\b001\exe\20_进程信息.exe]
fmt.Println(os.Getenv("PATH")) // ...Go\bin...
fmt.Println(os.Setenv("AA","BB"))
buf, err := exec.Command("grep","127.0.0.1","/etc/hosts").CombinedOutput()
if err != nil{
panic(err)
}
fmt.Println(string(buf))
}