一、JSON
Go语言内建对 JSON 的支持,使用内置的 encoding/json 标准库,开发人员可以轻松使用Go程序生成和解析 JSON 格式的数据。
json.NewEncoder(filePtr) 创建Json编码器 encoder.Encode(info)
json.NewDecoder(filePtr1) 创建Json解码器 decoder.Decode(&info)
import (
"encoding/json"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name,attr"`
Url string
Course []string
}
func main() {
info := []Website{{"Golang", "http://c.biancheng.net/golang/", []string{"http://c.biancheng.net/cplus/", "http://c.biancheng.net/linux_tutorial/"}}, {"Java", "http://c.biancheng.net/java/", []string{"http://c.biancheng.net/socket/", "http://c.biancheng.net/python/"}}}
str,_:=os.Getwd() //获取当前目录
fmt.Println(str)
filePtr, err := os.Create("info.json") //创建文件,在当前目录下创建
if err != nil {
fmt.Println("文件创建失败", err.Error())
return
}
defer filePtr.Close()
//编码
encoder := json.NewEncoder(filePtr) // 创建Json编码器
err = encoder.Encode(info)
if err != nil {
fmt.Println("编码错误", err.Error())
} else {
fmt.Println("编码成功")
}
}
import (
"encoding/json"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name,attr"`
Url string
Course []string
}
func main() {
filePtr1,err := os.Open("./info.json") //.表示当前目录
if err != nil{
fmt.Println("文件打开失败",err.Error())
return
}
defer filePtr1.Close()
//解码
var info1 []Website
decoder := json.NewDecoder(filePtr1) // 创建json解码器
err = decoder.Decode(&info1)
if err !=nil {
fmt.Println("解码失败",err.Error())
} else {
fmt.Println("解码成功")
fmt.Println(info1)
}
}
二、XML
Go语言内置的 encoding/xml 包可以用在结构体和 XML 格式之间进行编解码,其方式跟 encoding/json 包类似。然而与 JSON 相比 XML 的编码和解码在功能上更苛刻得多,这是由于 encoding/xml 包要求结构体的字段包含格式合理的标签,而 JSON 格式却不需要。
encoder := xml.NewEncoder(filePtr) encoder.Encode(info)
decoder := xml.NewDecoder(filePtr) decoder.Decode(&info)
import (
"encoding/xml"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name,attr"`
Url string
Course []string
}
func main(){
info := Website{"C语言中文网", "http://c.biancheng.net/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("编码成功")
}
}
import (
"encoding/xml"
"fmt"
"os"
)
type Website struct {
Name string `xml:"name,attr"`
Url string
Course []string
}
func main(){
file,err := os.Open("./info.xml")
if err != nil{
fmt.Println("打开文件失败",err.Error())
return
}
defer file.Close()
//解码
info1 := Website{}
decoder := xml.NewDecoder(file)
err = decoder.Decode(&info1)
if err != nil{
fmt.Println("解码失败",err.Error())
return
} else {
fmt.Println("解码成功")
fmt.Println(info1)
}
}
将结构体转换为XML输出时,需要注意以下规则:
- XMLName字段,如上所述,会省略
- 具有标签"-"的字段会省略
- 具有标签"name,attr"的字段会成为该XML元素的名为name的属性
- 具有标签",attr"的字段会成为该XML元素的名为字段名的属性
- 具有标签",chardata"的字段会作为字符数据写入,而非XML元素
- 具有标签",innerxml"的字段会原样写入,而不会经过正常的序列化过程
- 具有标签",comment"的字段作为XML注释写入,而不经过正常的序列化过程,该字段内不能有"–"字符串
- 标签中包含"omitempty"选项的字段如果为空值会省略
空值为false、0、nil指针、nil接口、长度为0的数组、切片、映射 - 匿名字段(其标签无效)会被处理为其字段是外层结构体的字段
- 如果一个字段的标签为"a>b>c",则元素c将会嵌套进其上层元素a和b中。如果该字段相邻的字段标签指定了同样的上层元素,则会放在同一个XML元素里。
解析XML编码时,需要遵守以下规则:
- 如果结构体字段的类型为字符串或者[]byte,且标签为",innerxml",
Unmarshal函数直接将对应原始XML文本写入该字段,其余规则仍适用。 - 如果结构体字段类型为xml.Name且名为XMLName,Unmarshal会将元素名写入该字段
- 如果字段XMLName的标签的格式为"name"或"namespace-URL name",
XML元素必须有给定的名字(以及可选的名字空间),否则Unmarshal会返回错误。 - 如果XML元素的属性的名字匹配某个标签",attr"为字段的字段名,或者匹配某个标签为"name,attr"的字段的标签名,Unmarshal会将该属性的值写入该字段。
- 如果XML元素包含字符数据,该数据会存入结构体中第一个具有标签",chardata"的字段中,
该字段可以是字符串类型或者[]byte类型。如果没有这样的字段,字符数据会丢弃。 - 如果XML元素包含注释,该数据会存入结构体中第一个具有标签",comment"的字段中,
该字段可以是字符串类型或者[]byte类型。如果没有这样的字段,字符数据会丢弃。 - 如果XML元素包含一个子元素,其名称匹配格式为"a"或"a>b>c"的标签的前缀,反序列化会深入XML结构中寻找具有指定名称的元素,并将最后端的元素映射到该标签所在的结构体字段。
以">“开始的标签等价于以字段名开始并紧跟着”>" 的标签。 - 如果XML元素包含一个子元素,其名称匹配某个结构体类型字段的XMLName字段的标签名,
且该结构体字段本身没有显式指定标签名,Unmarshal会将该元素映射到该字段。 - 如果XML元素的包含一个子元素,其名称匹配够格结构体字段的字段名,且该字段没有任何模式选项(",attr"、",chardata"等),Unmarshal会将该元素映射到该字段。
- 如果XML元素包含的某个子元素不匹配以上任一条,而存在某个字段其标签为",any",
Unmarshal会将该元素映射到该字段。 - 匿名字段被处理为其字段好像位于外层结构体中一样。
- 标签为"-"的结构体字段永不会被反序列化填写。
三、Gob
Gob 是Go语言自己以二进制形式序列化和反序列化程序数据的格式,可以在 encoding 包中找到。这种格式的数据简称为 Gob(即 Go binary 的缩写)。类似于 Python]的“pickle”和 Java的“Serialization”。
Gob 特定的用于纯 Go 的环境中,例如两个用Go语言写的服务之间的通信。这样的话服务可以被实现得更加高效和优化。
import (
"encoding/gob"
"fmt"
"os"
)
func main(){
info := map[string]string{
"name":"百度",
"website":"http://baidu.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)
}
}
import (
"encoding/gob"
"fmt"
"os"
)
func main(){
var M map[string]string
File1, _ := os.Open("demo.gob")
defer File1.Close()
//解码
D := gob.NewDecoder(File1)
D.Decode(&M)
fmt.Println(M)
}
四、纯文本文件
import (
"bufio"
"fmt"
"os"
"io"
)
func main(){
filePath := "./output.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Printf("打开文件错误= %v \n", err)
return
}
defer file.Close()
str := "http://c.biancheng.net/golang/\n"
writer := bufio.NewWriter(file) //写入时,使用带缓存的 *Writer
for i :=0;i<3;i++{
writer.WriteString(str)
}
writer.Flush() //调用 flush方法,将缓存的数据真正写入到文件中。
}
import (
"bufio"
"fmt"
"os"
"io"
)
func main(){
file1, err := os.Open("./output.txt")
if err != nil {
fmt.Println("文件打开失败 = ", err)
}
defer file1.Close()
reader := bufio.NewReader(file1)
for{
str,err := reader.ReadString('\n')
if err == io.EOF{
break
}
fmt.Print(str)
}
fmt.Println("文件读取结束")
}