文章目录
- Reader对象
- 创建Reader对象
- 操作Reader对象
- Writer对象
- 创建Writer对象
- 操作Writer 对象
- 读写文件操作案例
- 判断文件是否存在
- 命令行参数
- 断点续传
- Seeker接口
- 实现案例
- 读写JSON文件
- 读写XML文件
- 读写gob文件
- 自定义二进制文件读写
- zip归档文件的读写操作
- tar归档文件的读写操作
- 文件锁操作
- json(反)序列化技巧
Reader对象
创建Reader对象
- *NewReader(rd io.Reader) Reader
- 按照缓冲区默认长度创建Reader对象,Reader对象会从底层io.Reader接口读取尽量多的数据进行缓存。
- *NewReaderSize(rd io.Reader, size int) Reader
- 指定缓冲区长度创建Reader对象
操作Reader对象
- (b * Reader) Read(p []byte) (n int, err error)
- 读取数据存放到字节切片p中,执行结束返回已读取的字节数n和错误err,当字节流结束时,n为0,err为io.EOF
- (b * Reader) ReadByte() (c byte, err error)
- 读取并返回一个字节,如果没有字节可读,则返回错误信息
- (b * Reader) ReadBytes(delim byte) (line []byte, err error)
- 读取数据直到遇到“delim”分隔符,并返回读取的字节序列(包括“delim”),如果分隔符不存在读取所有,返回EOF错误
- (b * Reader)ReadLine() (line []byte, isPrefix bool, err error)
- 读取一行数据,如果一行数据太长,isprefix会被设置为true,返回之前的数据,继续调用返回之后的数据直到遇到换行符
- 如果是读取一行数据建议使用
ReadString('n')
或者ReadBytes('n')
- (b * Reader) ReadRune() (r rune, size int, err error)
- 读取一个UTF-8编码的字符,并返回字节数
- (b * Reader)ReadSlice(delim byte) (line []byte, err error)
- 读取数据直到遇到分隔符,返回读取的字节切片
- (b * Reader) ReadString(delim byte) (line string, err error)
- 读取数据直到遇到分隔符,返回读取的字符串
- (b * Reader)UnreadByte() error
- 撤销已读最后一个字节,重新放入缓冲区的头部
- (b * Reader) UnreadRune() error
- 撤销已读最后一个字符,重新放入缓冲区的头部
- (b * Reader) Buffered() (n int, err error)
- 返回可从缓冲区读出数据的字节数
- (b * Reader) Peek(n int) ([]byte], err error)
- 读取指定字节的数据,读取的数据不会从缓冲区清除
Writer对象
创建Writer对象
- NewWriter(wr io.Writer) * Writer
- 按照默认缓冲区长度创建
- NewWriterSize(wr io.Writer, size int) * Writer
- 指定缓冲区长度
操作Writer 对象
- (b * Writer) Available() int
- 返回缓冲区中未使用的字节数
- (b * Writer) Buffered() int
- 返回已写入当前缓冲区中的字节数
- (b * Writer) Flush() error
- 将缓冲区的数据写入底层io.Writer
- (b * Writer) Write(p []byte) (nn int, err error)
- 将字节切片写入缓冲区,返回已经写入的字节数
- (b * Writer) WriteByte(c byte) error
- 写入一个字节
- (b * Writer) WriteRune(r rune) (size int, err error)
- 写入一个Unicode字符,返回写入的字节数
- (b * Writer) WriteString(s string) (int, error)
- 写入一个字符串,返回写入的字节数
读写文件操作案例
打开文件和关闭文件
-
func Open(name string) (file * File, err error)
以O_RDONLY只读模式打开文件
-
func ( * File)Close() error
关闭文件
读文件
-
读取文件内容并显示在终端(带缓冲区的方式)
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package main import ( "bufio" "fmt" "io" "os" ) func main() { file, err := os.Open("C:\Users\zhouzy1\Desktop\my_study_notes\go学习\代码\study_go\day1\abc.txt") if err != nil { fmt.Println("打开文件错误:",err) } // 打开文件一定记得最后关闭 defer file.Close() // 默认缓冲区大小为4096 reader := bufio.NewReader(file) for { str, err := reader.ReadString('n') fmt.Print(str) if err == io.EOF { // 文件结束符为EOF break } } }
-
一次性读取文件所有内容至缓冲区中,适用于文件不大的情况:
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14package main import ( "fmt" "io/ioutil" ) func main() { file := "C:\Users\zhouzy1\Desktop\my_study_notes\go学习\代码\study_go\day1\abc.txt" content, err := ioutil.ReadFile(file) if err != nil { fmt.Printf("read file err=%v", err) } fmt.Printf("%v", string(content)) }
-
按行读取文件
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package main import ( "bufio" "fmt" "io" "os" ) func main() { path := "C:\Users\zhouzy1\Desktop\my_study_notes\go学习\代码\study_go\day1\abc.txt" f, err := os.Open(path) if err != nil { fmt.Println("err = ", err) return } defer f.Close() r := bufio.NewReader(f) for { buf, err := r.ReadBytes('n') if err != nil { if err == io.EOF { break } fmt.Println("err = ", err) } fmt.Printf("buf = #%s#n", string(buf)) } }
写文件
-
os.OpenFile(name string, flag int, perm FileMode) (file * File, err error)
以指定模式,指定权限打开文件
-
打开或者创建文件并写入内容
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package main import ( "bufio" "fmt" "os" ) func main() { filePath := "a.txt" file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_CREATE, 0666) if err != nil { fmt.Printf("open file err=%vn", err) return } defer file.Close() str := "hello go!" writer := bufio.NewWriter(file) for i := 0; i < 5; i++ { writer.WriteString(str) } // 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件 writer.Flush() }
-
打开文件,写入并覆盖原有内容
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package main import ( "bufio" "fmt" "os" ) func main() { filePath := "a.txt" file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_TRUNC, 0666) if err != nil { fmt.Printf("open file err=%vn", err) return } defer file.Close() str := "覆盖原有内容!" writer := bufio.NewWriter(file) for i := 0; i < 5; i++ { writer.WriteString(str) } // 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件 writer.Flush() }
-
打开文件,追加内容
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package main import ( "bufio" "fmt" "os" ) func main() { filePath := "a.txt" file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_APPEND, 0666) if err != nil { fmt.Printf("open file err=%vn", err) return } defer file.Close() str := "追加内容!rn" writer := bufio.NewWriter(file) for i := 0; i < 5; i++ { writer.WriteString(str) } // 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件 writer.Flush() }
-
打开文件,读取文件内容,并追加内容
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32package main import ( "bufio" "fmt" "io" "os" ) func main() { filePath := "a.txt" file, err := os.OpenFile(filePath, os.O_RDWR | os.O_APPEND, 0666) if err != nil { fmt.Printf("open file err=%vn", err) return } defer file.Close() reader := bufio.NewReader(file) for { str, err := reader.ReadString('n') if err == io.EOF { break } fmt.Print(str) } str := "追加内容!rn" writer := bufio.NewWriter(file) for i := 0; i < 5; i++ { writer.WriteString(str) } // 使用的缓冲区写入,flush后才会将缓冲区的内容写入文件 writer.Flush() }
-
读取一个文件的内容写入另一个文件
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package main import ( "fmt" "io/ioutil" ) func main() { file1Path := "a.txt" file2Path := "b.txt" data, err := ioutil.ReadFile(file1Path) if err != nil { fmt.Printf("read file err = %vn", err) return } err = ioutil.WriteFile(file2Path, data, 0666) if err != nil { fmt.Printf("write file error = %vn", err) } }
判断文件是否存在
- 判断文件或者文件夹是否存在
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package main import ( "fmt" "os" ) func main() { file1Path := "a.txt" file2Path := "not_exit_file.txt" fileInfo, err := os.Stat(file1Path) _, err2 := os.Stat(file2Path) // 如果err 为nil 说明文件一定存在 if err == nil { fmt.Println("文件存在") } fmt.Printf("%Tn", fileInfo) // 文件名 fmt.Println(fileInfo.Name()) // 文件大小 fmt.Println(fileInfo.Size()) // 是否是目录 fmt.Println(fileInfo.IsDir()) // 修改时间 fmt.Println(fileInfo.ModTime()) // 如果err 不为nil 需要通过os.IsNotExist判断错误类型为不存在 // 否则可能为别的错误类型 if os.IsNotExist(err2) { fmt.Println("文件不存在2") } }
命令行参数
- 使用
os.Args
存储所有的命令行参数 - flag 包解析命令行参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package main import ( "flag" "fmt" ) func main() { var user string var pwd string var host string var port int flag.StringVar(&user, "u", "", "用户名默认为空") flag.StringVar(&pwd, "p", "", "密码默认为空") flag.StringVar(&host, "h", "localhost", "主机名默认为localhost") flag.IntVar(&port, "port", 3306, "端口默认为3306") flag.Parse() fmt.Printf("user=%v pwd=%v host=%v port=%v", user, pwd, host, port) }
断点续传
Seeker接口
- Seeker是包装基本Seek方法的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41package main import ( "fmt" "io" "os" ) func main() { /** seek(offset, whence), 设置指针光标的位置 第一个参数:偏移量 第二个参数:如何设置 0: seekStart 表示相对于文件开始 1: seekCurrent 表示相对于当前偏移量 2: seek end 表示相对于结束 const ( SeekStart = 0 SeekCurrent = 1 SeekEnd = 2 ) 随机读取文件: 可以设置指针光标的位置 */ file, _ := os.OpenFile("a.txt", os.O_RDWR, 0) defer file.Close() bs := []byte{0, 1} file.Read(bs) fmt.Println(string(bs)) file.Seek(4, io.SeekStart) file.Read(bs) fmt.Println(string(bs)) file.Seek(2, 0) file.Read(bs) fmt.Println(string(bs)) file.Seek(3, io.SeekCurrent) file.Read(bs) fmt.Println(string(bs)) file.Seek(0, io.SeekEnd) file.WriteString("ABC") }
实现案例
-
实现断点续传,主要要记录读写文件位置,实现思路:在读写文件的同时,建立一个临时文件用于同步读写数据的位置,当需要断点续传的时候,从临时文件中获取指定位置,然后通过
Seek()
方法定位读写位置,继续读写。复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57package main import ( "fmt" "io" "os" "strconv" ) func main() { /* 断点续传: 复制文件a.png 复制到b.png */ srcFile := "a.png" destFile := "b.png" tmpFIle := destFile + "tmp.txt" file1, _ := os.Open(srcFile) file2, _ := os.OpenFile(destFile, os.O_CREATE | os.O_WRONLY, os.ModePerm) file3, _ := os.OpenFile(tmpFIle, os.O_CREATE | os.O_RDWR, os.ModePerm) defer file1.Close() defer file2.Close() // 1. 读取临时文件中的数据,根据seek file3.Seek(0, io.SeekStart) bs := make([]byte, 100, 100) n1, err := file3.Read(bs) fmt.Println(n1) countStr := string(bs[:n1]) fmt.Println(countStr) count, _ := strconv.ParseInt(countStr, 10, 64) fmt.Println(count) // 2. 设置读,写的偏移量 file1.Seek(count, 0) file2.Seek(count, 0) data := make([]byte, 1024, 1024) n2 := -1 n3 := -1 total := int(count) for { // 3.读取数据 n2, err = file1.Read(data) if err == io.EOF { fmt.Println("文件复制完毕") file3.Close() os.Remove(tmpFIle) break } // 将数据写入目标文件 n3, _ = file2.Write(data[:n2]) total += n3 // 将复制总量,存储到临时文件中 file3.Seek(0, io.SeekStart) file3.WriteString(strconv.Itoa(total)) if total > 1024{ panic("异常断开") } } }
读写JSON文件
写入JSON文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package main import ( "encoding/json" "fmt" "os" ) type Website struct { Name string `xml:"name, attr"` Url string Course []string } func main() { info := []Website{ {"Golang", "http://清华尹成大神/golang/", []string{"http://清华尹成大神/cplus/", "http://清华尹成大神/linux_tutorial/"}}, {"Java", "http://清华尹成大神/java/", []string{"http://清华尹成大神/socket/", "http://清华尹成大神/python/"}}, } filePtr, err := os.Create("info.json") if err != nil { fmt.Println("err:", err.Error()) return } defer filePtr.Close() encoder := json.NewEncoder(filePtr) err = encoder.Encode(info) if err != nil { fmt.Println("编码错误", err.Error()) }else { fmt.Println("success") } }
读取JSON文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package main import ( "encoding/json" "fmt" "os" ) type Website struct { Name string `xml:"name, attr"` Url string Course []string } func main() { filePtr, err := os.Open("info.json") if err != nil { fmt.Println("文件打开失败【err:%s】", err.Error()) return } defer filePtr.Close() var info []Website // 创建json解码器 decoder := json.NewDecoder(filePtr) err = decoder.Decode(&info) if err != nil { fmt.Println("解码失败", err.Error()) } else { fmt.Println("解码成功") fmt.Println(info) } }
读写XML文件
写入xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package main import ( "encoding/xml" "fmt" "os" ) type Website struct { Name string `xml:"name, attr"` Url string Course []string } func main() { info := Website{"清华尹成大神网", "http://清华尹成大神/golang/", []string{"Go语言入门教程", "Golang入门教程"}} f, err := os.Create("info.xml") if err != nil { fmt.Println("文件创建失败", err.Error()) return } defer f.Close() // 序列化到文件中 encoder := xml.NewEncoder(f) err = encoder.Encode(info) if err != nil { fmt.Println("编码错误:", err.Error()) return } else { fmt.Println("编码成功") } }
读XML文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package main import ( "encoding/xml" "fmt" "os" ) type Website struct { Name string `xml:"name, attr"` Url string Course []string } func main() { f, err := os.Open("info.xml") if err != nil { fmt.Println("文件打开失败", err.Error()) return } defer f.Close() info := Website{} // 创建xml解码器 decoder := xml.NewDecoder(f) err = decoder.Decode(&info) if err != nil { fmt.Println("解码错误:", err.Error()) return } else { fmt.Println("解码成功") fmt.Println(info) } }
读写gob文件
- gob go语言自己以二进制形式序列化和反序列化程序数据的格式
- 编码和解码过程中用到了Go的反射,通常用于远程方法调用参数和结果的传输,以及机器和程序之间的数据传输
- 零值会被忽略
创建gob文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package main import ( "encoding/gob" "fmt" "os" ) func main() { info := map[string]string{ "name": "清华大声", "website": "badidu.com", } name := "demo.gob" File, _ := os.OpenFile(name, os.O_RDWR|os.O_CREATE,0777) defer File.Close() enc := gob.NewEncoder(File) if err := enc.Encode(info); err != nil { fmt.Println(err) } }
读取gob文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14package main import ( "encoding/gob" "fmt" "os" ) func main() { var M map[string]string File, _ := os.Open("demo.gob") D := gob.NewDecoder(File) D.Decode(&M) fmt.Println(M) }
自定义二进制文件读写
写自定义二进制文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package main import ( "bytes" "encoding/binary" "fmt" "os" ) type Website struct { Url int32 } func main() { file, err := os.Create("output.bin") for i := 1; i <= 10; i++ { info := Website{Url: int32(i)} if err != nil { fmt.Println("文件创建失败") return } defer file.Close() var bin_buf bytes.Buffer binary.Write(&bin_buf, binary.LittleEndian, info) b := bin_buf.Bytes() _, err = file.Write(b) if err != nil { fmt.Println("编码失败", err.Error()) return } } fmt.Println("编码成功") }
读二进制文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38package main import ( "bytes" "encoding/binary" "fmt" "os" ) type Website struct { Url int32 } func main() { file, err := os.Open("output.bin") defer file.Close() if err != nil { fmt.Println("文件打开失败", err.Error()) return } m := Website{} for i := 1; i <= 10; i++ { data := readNextBytes(file, 4) buffer := bytes.NewBuffer(data) err = binary.Read(buffer, binary.LittleEndian, &m) if err != nil { fmt.Println("二进制文件读取失败", err) return } fmt.Println(i) } } func readNextBytes(file *os.File, number int) []byte { bytes := make([]byte, number) _, err := file.Read(bytes) if err != nil { fmt.Println("解码失败",err) } return bytes }
zip归档文件的读写操作
创建zip归档文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40package main import ( "archive/zip" "bytes" "fmt" "os" ) func main() { // 使用buffer创建压缩文档 buf := new(bytes.Buffer) w := zip.NewWriter(buf) // 将文件加入压缩文档 var files = []struct{ Name, Body string }{ {"Golang.txt", "清华大神"}, } for _, file := range files { f, err := w.Create(file.Name) if err != nil { fmt.Println(err) } _, err = f.Write([]byte(file.Body)) if err != nil { fmt.Println(err) } } // 关闭压缩文档 err := w.Close() if err != nil { fmt.Println(err) } // 将压缩文档内容写入文件 f, err := os.OpenFile("file.zip", os.O_CREATE|os.O_WRONLY, 0666) if err != nil { fmt.Println(err) } buf.WriteTo(f) }
读取zip归档文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29package main import ( "archive/zip" "fmt" "io" "os" ) func main() { // 打开一个zip格式文件 r, err := zip.OpenReader("file.zip") if err != nil { fmt.Printf(err.Error()) } defer r.Close() // 迭代压缩文件中的文件,打印文件中的内容 for _,f := range r.File { fmt.Printf("文件名:%sn", f.Name) rc, err := f.Open() if err != nil { fmt.Printf(err.Error()) } _, err = io.CopyN(os.Stdout, rc, int64(f.UncompressedSize64)) if err != nil { fmt.Printf(err.Error()) } rc.Close() } }
tar归档文件的读写操作
打包tar文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package main import ( "archive/tar" "fmt" "io" "os" ) func main() { // 创建tar文件 f, err := os.Create("./output.tar") if err != nil { fmt.Println(err) return } defer f.Close() tw := tar.NewWriter(f) defer tw.Close() // 获取文件相关信息 fileInfo, err := os.Stat("./main.go") if err != nil { fmt.Println(err) } hdr, err := tar.FileInfoHeader(fileInfo, "") if err != nil { fmt.Println(err) } err = tw.WriteHeader(hdr) if err != nil { fmt.Println(err) } f1, err := os.Open("./main.go") if err != nil { fmt.Println(err) return } m, err := io.Copy(tw, f1) if err != nil { fmt.Println(err) } fmt.Println(m) }
解压tar归档文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package main import ( "archive/tar" "fmt" "io" "os" ) func main() { // 创建tar文件 f, err := os.Create("./output.tar") if err != nil { fmt.Println(err) return } defer f.Close() tw := tar.NewWriter(f) defer tw.Close() // 获取文件相关信息 fileInfo, err := os.Stat("./main.go") if err != nil { fmt.Println(err) } hdr, err := tar.FileInfoHeader(fileInfo, "") if err != nil { fmt.Println(err) } err = tw.WriteHeader(hdr) if err != nil { fmt.Println(err) } f1, err := os.Open("./main.go") if err != nil { fmt.Println(err) return } m, err := io.Copy(tw, f1) if err != nil { fmt.Println(err) } fmt.Println(m) }
文件锁操作
- flock是对于整个文件的建议性锁。也就是说,如果一个进程在一个文件上放了锁,其他进程是可以知道的。
- 它的第一个参数是文件描述符,在文件描述符关闭时,锁会自动释放。而当进程终止时,所有的文件描述符均会被关闭
- flock主要三种操作类型:
- LOCK_SH: 共享锁,多个进程可以使用同一把锁,常被用作读共享锁
- LOCK_EX: 排它锁,同时只允许一个进程使用,常备用所写锁
- LOCK_UN: 释放锁
json(反)序列化技巧
使用json tag 指定字段名
1
2
3
4
5
6type Person struct { Name string `json:"name"` Age int64 Weight float64 }
忽略某个字段
1
2
3
4
5
6type Person struct { Name string `json:"name"` Age int64 Weight float64 `json:"-"` }
忽略空值字段
1
2
3
4
5
6
7type Person struct { Name string `json:"name"` Age int64 `json:"age,omitempty"` Weight float64 `json:"-"` }
忽略嵌套结构体空值字段
- 嵌套结构体嵌套序列化显示需要使用指针
1
2
3
4
5
6
7
8
9
10type Profile struct { Website string `json:"website"` Slogan string `json:"slogan"` } type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` *Profile `json:"profile,omitempty"` }
不修改原结构体忽略空值字段
- 创建另外的结构体匿名嵌套原结构体,并制定字段为匿名结构体指针类型
1
2
3
4
5
6
7
8
9type User struct { Name string `json:"name"` Password string `json:"password"` } type PublicUser struct { *User Password *struct{} `json:"password,omitempty"` }
优雅处理字符串格式的数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package main import ( "encoding/json" "fmt" ) func main() { type Card struct { ID int64 `json:"id,string"` Score float64 `json:"score,string"` } jsonStr := `{"id": "12345", "score": "88.5"}` var c Card if err := json.Unmarshal([]byte(jsonStr), &c); err != nil { fmt.Printf("json.Unmarsha jsonStr failed, err:%vn", err) return } fmt.Printf("c:%#vn", c) }
整数变浮点数
-
JSON协议没有整型和浮点型之分,统称为number。JSON反序列化后都会转为float64:
复制代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package main import ( "encoding/json" "fmt" ) func main() { var m = make(map[string]interface{}, 1) m["count"] = 1 b, err := json.Marshal(m) if err != nil { fmt.Printf("marshal failed, err:%vn", err) } fmt.Printf("str:%#vn", string(b)) var m2 map[string]interface{} err = json.Unmarshal(b, &m2) if err != nil{ fmt.Printf("unmarshal failed, err:%vn", err) return } fmt.Printf("value:%vn", m2["count"]) //1 fmt.Printf("type::%Tn", m2["count"]) // float64 }
想要更合理的处理数字需要使用decoder:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35package main import ( "bytes" "encoding/json" "fmt" ) func main() { var m = make(map[string]interface{}, 1) m["count"] = 1 b, err := json.Marshal(m) if err != nil { fmt.Printf("marshal failed, err:%vn", err) } fmt.Printf("str:%#vn", string(b)) var m2 map[string]interface{} // 使用decoder方式反序列化,指定使用number类型 decoder := json.NewDecoder(bytes.NewReader(b)) decoder.UseNumber() err = decoder.Decode(&m2) if err != nil{ fmt.Printf("unmarshal failed, err:%vn", err) return } fmt.Printf("value:%vn", m2["count"]) fmt.Printf("type::%Tn", m2["count"]) // 将m2["count"]转为json.Number之后调用Int64()方法获得int64类型的值 count, err := m2["count"].(json.Number).Int64() if err != nil { fmt.Printf("parse to int64 failed, err:%vn", err) return } fmt.Printf("type:%Tn", int(count)) //int }
使用匿名结构体添加字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package main import ( "encoding/json" "fmt" ) func main() { type UserInfo struct { ID int `json:"id"` Name string `json:"name"` } u1 := UserInfo{ ID: 12345, Name: "zzy", } // 使用匿名结构体内嵌User并添加额外字段Token b, err := json.Marshal(struct { *UserInfo Token string `json:"token"` }{ &u1, "9asd2d35asd", }) if err != nil { fmt.Printf("json.Marsha failed, err:%vn", err) return } fmt.Printf("str:%sn", b) // str:{"id":12345,"name":"zzy","token":"9asd2d35asd"} }
使用匿名结构体组合多个结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45package main import ( "encoding/json" "fmt" ) func main() { type Comment struct { Content string } type Image struct { Title string `json:"title"` URL string `json:"url"` } c1 := Comment { Content: "永远不要高估自己", } i1 := Image{ Title: "赞赏码", URL: "demo.com", } b, err := json.Marshal(struct { *Comment *Image }{&c1, &i1}) if err != nil { fmt.Printf("json.Marshal failed, err:%vn", err) return } fmt.Printf("str:%sn", b) // 反序列化 jsonStr := `{"Content":"永远不要高估自己","title":"赞赏码","url":"https://www.liwenzhou.com/images/zanshang_qr.jpg"}` var ( c2 Comment i2 Image ) if err := json.Unmarshal([]byte(jsonStr), &struct { *Comment *Image }{&c2, &i2});err != nil { fmt.Printf("json.Unmarshal failed, err:%vn", err) return } fmt.Printf("c2:%#v i2%$vn", c2, i2) }
处理不确定层级的json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package main import ( "encoding/json" "fmt" ) func main() { type sendMsg struct { User string `json:"user"` Msg string `json:"msg"` } jsonStr := `{"sendMsg":{"user":"q1mi","msg":"永远不要高估自己"},"say":"Hello"}` // 定义一个map, value 类型为json.RawMessage, 方便后续更灵活的处理 var data map[string]json.RawMessage if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { fmt.Printf("1json.Unmarshal jsonStr failed, err: %vn",err) return } var msg sendMsg if err := json.Unmarshal(data["sendMsg"], &msg); err != nil { fmt.Printf("json.Unmarshal failed, err:%vn", err) return } fmt.Printf("msg:%#vn", msg) }
最后
以上就是现实小甜瓜最近收集整理的关于go基础学习之文件编程总结的全部内容,更多相关go基础学习之文件编程总结内容请搜索靠谱客的其他文章。
发表评论 取消回复