概述
文章目录
- 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
关闭文件
读文件
-
读取文件内容并显示在终端(带缓冲区的方式)
package 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 } } }
-
一次性读取文件所有内容至缓冲区中,适用于文件不大的情况:
package 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)) }
-
按行读取文件
package 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)
以指定模式,指定权限打开文件
-
打开或者创建文件并写入内容
package 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() }
-
打开文件,写入并覆盖原有内容
package 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() }
-
打开文件,追加内容
package 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() }
-
打开文件,读取文件内容,并追加内容
package 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() }
-
读取一个文件的内容写入另一个文件
package 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) } }
判断文件是否存在
- 判断文件或者文件夹是否存在
package 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 包解析命令行参数
package 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方法的接口
package 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()
方法定位读写位置,继续读写。package 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文件
package 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文件
package 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文件
package 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文件
package 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文件
package 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文件
package 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)
}
自定义二进制文件读写
写自定义二进制文件
package 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("编码成功")
}
读二进制文件
package 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归档文件
package 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归档文件
package 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文件
package 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归档文件
package 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 指定字段名
type Person struct {
Name string `json:"name"`
Age int64
Weight float64
}
忽略某个字段
type Person struct {
Name string `json:"name"`
Age int64
Weight float64 `json:"-"`
}
忽略空值字段
type Person struct {
Name string `json:"name"`
Age int64
`json:"age,omitempty"`
Weight float64 `json:"-"`
}
忽略嵌套结构体空值字段
- 嵌套结构体嵌套序列化显示需要使用指针
type 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"`
}
不修改原结构体忽略空值字段
- 创建另外的结构体匿名嵌套原结构体,并制定字段为匿名结构体指针类型
type User struct {
Name string `json:"name"`
Password string `json:"password"`
}
type PublicUser struct {
*User
Password *struct{} `json:"password,omitempty"`
}
优雅处理字符串格式的数字
package 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:
package 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:
package 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
}
使用匿名结构体添加字段
package 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"}
}
使用匿名结构体组合多个结构体
package 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
package 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基础学习之文件编程总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复