go 语言之文件操作***
基本介绍
文件并不陌生,文件是数据源(保存数据的地方)的一种,例如经常使用的word文档,txt文件,Excel文件都是文件,文件最重要的作用就是保存数据,它既可以保存一张图片,也可以保存视频声音
文件在程序中是以流的形式来操作的

流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流: 数据从数据源(文件)到程序(内存)的路径
输出流:数据从程序(内存)到数据源(文件)的路径
操作
os.File 封装了所有文件相关的操作

File代表一个打开的文件对象

文件基本操作
打开文件
func Open(name string) (file *File, err error) os.Open(name string) (file *File, err error)
Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。
关闭文件
func (f *File) Close() error File.Close()
示例
package main
import(
"os"
"fmt"
)
func main(){
//大开文件
//file 对象
//
file,err := os.Open("D:/课程资料/crict.yaml")
if err !=nil{
fmt.Println("open file err =",err)
}else{
fmt.Printf("文件内容=%v",file)
}
err = file.Close()
if err != nil {
fmt.Println("close file err=",err)
}
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom01\main.go
// 文件内容=&{0xc000070a08}
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom01\main.go
// 文件内容=&{0xc000070a08}
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom01\main.go
// open file err = open D:/课程资料/crictl0.yaml: The system cannot find the file specified.
// close file err= invalid argument
文件读取操作
1)读取文件的内容并显示在终端(带缓冲区的方式),使用os.Open,file.Close,bufio.NewReader(),reader.ReadString函数和方法
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main(){
//file,err:=os.Open("")
file,err := os.Open("D:/BaiduNetdiskDownload/第5章-基于云原生分布式存储Ceph实现K8S数据持久化/做实验需要的资料/cephfs-pod-1.yaml")
if err !=nil{
fmt.Println("open file err =",err)
}
defer file.Close()//及时关闭文件
//创建一个*Reade,默认4096字节
/*const (
defaultBufSize = 4096
)*/
reade := bufio.NewReader(file)
for {
str,err:=reade.ReadString('\n') //读到换行符结束一行
if err == io.EOF{ //io.EOF,表示文件结尾
break
}
fmt.Print(str)
}
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom02\mian.go
// apiVersion: v1
// kind: Pod
// metadata:
// name: cephfs-pod-1
// spec:
// containers:
// - image: nginx
// name: nginx
// imagePullPolicy: IfNotPresent
// volumeMounts:
// - name: test-v1
// mountPath: /mnt
// volumes:
// - name: test-v1
// persistentVolumeClaim:
// claimName: cephfs-pvc
2)读取文件的内容并显示在终端(使用os.ReadFile一次性将整个文件读取到内存中),这种方式不适用于文件不大的情况,相关方法和函数os.ReadFile(ioutil.ReadFile 从 Go 1.16 开始,ioutil.ReadFile 已经不推荐使用了 )
package main
import (
"fmt"
"os"
//"strings"
)
func main(){
//file,err:=os.Open("")
file :="D:/BaiduNetdiskDownload/第5章-基于云原生分布式存储Ceph实现K8S数据持久化/做实验需要的资料/cephfs-pvc.yaml"
t,err :=os.ReadFile(file)
if err!=nil{
return
}
fmt.Printf("%v",string(t))//t 默认是byte 切片所有这里需要使用强转转为string类型
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom03\mian.go
// kind: PersistentVolumeClaim
// apiVersion: v1
// metadata:
// name: cephfs-pvc
// spec:
// accessModes:
// - ReadWriteMany
// volumeName: cephfs-pv
// resources:
// requests:
// storage: 1Gi
bufio.Scanner 每行不能超过64kb,否则报错
package main
import (
"bufio"
"fmt"
"os"
//"strings"
)
func main(){
//file,err:=os.Open("")
// file :="D:/BaiduNetdiskDownload/第5章-基于云原生分布式存储Ceph实现K8S数据持久化/做实验需要的资料/cephfs-pvc.yaml"//只适合小文件
// t,err :=os.ReadFile(file)
// if err!=nil{
// return
// }
// fmt.Printf("%v",string(t))//t 默认是byte 切片所有这里需要使用强转转为string类型
s,err:= os.Open("D:/BaiduNetdiskDownload/第5章-基于云原生分布式存储Ceph实现K8S数据持久化/做实验需要的资料/cephfs-pvc.yaml")
if err !=nil{
return
}
defer s.Close()
t :=bufio.NewScanner(s)
for t.Scan() { //此方法返回布尔值
line := t.Text() // 当前行
fmt.Println(line)
}
if err := t.Err(); err != nil {
fmt.Println("读取错误:", err)
}
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom03\mian.go
// kind: PersistentVolumeClaim
// apiVersion: v1
// metadata:
// name: cephfs-pvc
// spec:
// accessModes:
// - ReadWriteMany
// volumeName: cephfs-pv
// resources:
// requests:
// storage: 1Gi
写文件操作
func OpenFile(name string, flag int, perm FileMode) (file *File, err error) OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。
第二个参数:文件打开模式(可以组合)
const (
O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
O_RDWR int = syscall.O_RDWR // 读写模式打开文件
O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
)
第三个参数:权限控制
r ->4
w->2
x ->1
const (
// 单字符是被String方法用于格式化的属性缩写。
ModeDir FileMode = 1 << (32 - 1 - iota) // d: 目录
ModeAppend // a: 只能写入,且只能写入到末尾
ModeExclusive // l: 用于执行
ModeTemporary // T: 临时文件(非备份文件)
ModeSymlink // L: 符号链接(不是快捷方式文件)
ModeDevice // D: 设备
ModeNamedPipe // p: 命名管道(FIFO)
ModeSocket // S: Unix域socket
ModeSetuid // u: 表示文件具有其创建者用户id权限
ModeSetgid // g: 表示文件具有其创建者组id的权限
ModeCharDevice // c: 字符设备,需已设置ModeDevice
ModeSticky // t: 只有root/创建者能删除/移动文件
// 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置
ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
)
示例1创建新文件写入
package main
import (
"bufio"
"fmt"
"os"
//"strings"
)
func main(){
//1.打开文件
file,err:= os.OpenFile("d:/abc.txt",os.O_WRONLY | os.O_CREATE,0666)
if err!=nil{
fmt.Printf("open file %v\n",err)
return
}
defer file.Close()
//准备写入内容
str := "hello,Gardon\n"
//写入时使用带缓存的*Writer
Writer:=bufio.NewWriter(file)
for i:=0;i<5;i++{
Writer.WriteString(str)
}
//因此writer 带缓存到内存的,因此要同步磁盘
Writer.Flush()//同步到磁盘
//
}
示例2 修改源文件内容;os.O_TRUNC
package main
import (
"bufio"
"fmt"
"os"
//"strings"
)
func main(){
//1.打开文件
file,err:= os.OpenFile("d:/abc.txt", os.O_WRONLY|os.O_TRUNC,0666)
if err!=nil{
fmt.Printf("open file %v\n",err)
return
}
defer file.Close()
//准备写入内容
str := "你好晨曦\r\n"
//写入时使用带缓存的*Writer
Writer:=bufio.NewWriter(file)
for i:=0;i<10;i++{
Writer.WriteString(str)
}
//因此writer 带缓存到内存的,因此要同步磁盘
Writer.Flush()//同步到磁盘
//
}
打开已存在的文件在原来文件追加 'ABC!ENGLISH!'
package main
import (
"bufio"
"fmt"
"os"
//"strings"
)
func main(){
//1.打开文件
file,err:= os.OpenFile("d:/abc.txt", os.O_WRONLY|os.O_APPEND,0666)
if err!=nil{
fmt.Printf("open file %v\n",err)
return
}
defer file.Close()
//准备写入内容
str := "'ABC!ENGLISH!\r\n'"
//写入时使用带缓存的*Writer
Writer:=bufio.NewWriter(file)
for i:=0;i<10;i++{
Writer.WriteString(str)
}
//因此writer 带缓存到内存的,因此要同步磁盘
Writer.Flush()//同步到磁盘
//
}
打开已存在的文件,将原来内容显示,并在后面追加5“hello,北京”
方式1
package main
import (
"bufio"
"fmt"
"os"
//"strings"
)
func main(){
file2,err2 := os.Open("D:/abc.txt")
if err2 !=nil{
fmt.Println("open file err =",err2)
}
defer file2.Close()
t := bufio.NewScanner(file2)
for t.Scan(){
line := t.Text() // 当前行
fmt.Println(line)
}
//1.打开文件
file,err:= os.OpenFile("d:/abc.txt", os.O_WRONLY|os.O_APPEND,0666)
if err!=nil{
fmt.Printf("open file %v\n",err)
return
}
defer file.Close()
//准备写入内容
str := "'hello,北京\r\n'"
//写入时使用带缓存的*Writer
Writer:=bufio.NewWriter(file)
for i:=0;i<5;i++{
Writer.WriteString(str)
}
//因此writer 带缓存到内存的,因此要同步磁盘
Writer.Flush()//同步到磁盘
//
}
方式2
package main
import (
"bufio"
"fmt"
"os"
"io"
//"strings"
)
func main(){
//1.打开文件
file,err:= os.OpenFile("d:/abc.txt", os.O_RDWR|os.O_APPEND,0666)
if err!=nil{
fmt.Printf("open file %v\n",err)
return
}
defer file.Close()
read:=bufio.NewReader(file)
for {
str,err:=read.ReadString('\n') //读到换行符结束一行
if err == io.EOF{ //io.EOF,表示文件结尾
break
}
fmt.Print(str)
}
//准备写入内容
str := "'hello,北京\r\n'"
//写入时使用带缓存的*Writer
Writer:=bufio.NewWriter(file)
for i:=0;i<5;i++{
Writer.WriteString(str)
}
//因此writer 带缓存到内存的,因此要同步磁盘
Writer.Flush()//同步到磁盘
//
}
从一个文件读取内容到另一个文件
package main
import (
//"bufio"
"fmt"
//"io"
//"io/ioutil"
//"io/ioutil"
"os"
)
func main(){
//将d:/adc.txt文件内容导入d:/kkk.txt
//首先将d:/adc.txt 内容读取到内存
//2将读取到内容写入kkk.txt
filepath1:= "D:/abc.txt"
filepath2:= "D:/kkk.txt"
data,err :=os.ReadFile(filepath1)
if err !=nil{
fmt.Println("错误:",err)
}
err =os.WriteFile(filepath2,data,0666)
if err!=nil{
fmt.Println("writeFile err=",err)
}
}
判断文件是否存在
Golang 判断文件或文件夹是否存在的方法为使用os.Stat()函数返回的错误值进行判断:
1)如果返回错误为nil,说明文件或文件存在
2)如果返回错误类型使用os.lsNotExist()判断为true。说明文件夹或文件不存在
3)如果返回的错误为其他类型,则不确定是否存在
func Stat(name string) (fi FileInfo, err error)
Stat返回一个描述name指定的文件对象的FileInfo。如果指定的文件对象是一个符号链接,返回的FileInfo描述该符号链接指向的文件的信息,本函数会尝试跳转该链接。如果出错,返回的错误值为*PathError类型。
文件拷贝
func Copy(dst Writer, src Reader) (written int64, err error) 将src的数据拷贝到dst,直到在src上到达EOF或发生错误。返回拷贝的字节数和遇到的第一个错误。 对成功的调用,返回值err为nil而非EOF,因为Copy定义为从src读取直到EOF,它不会将读取到EOF视为应报告的错误。如果src实现了WriterTo接口,本函数会调用src.WriteTo(dst)进行拷贝;否则如果dst实现了ReaderFrom接口,本函数会调用dst.ReadFrom(src)进行拷贝。
示例拷贝文件
package main
import (
//"bufio"
"bufio"
"fmt"
"io"
//"internal/syscall/windows"
//"io"
//"io/ioutil"
//"io/ioutil"
"os"
)
func CopyFile(detFileName string,srcFileName string)(written int64,err error){
srcFile,err:= os.Open(srcFileName)
if err !=nil{
fmt.Printf("源文件异常:%v\n",err)
}
defer srcFile.Close()
//通过文件句柄
reade :=bufio.NewReader(srcFile)
detFile,err:=os.OpenFile(detFileName,os.O_WRONLY|os.O_CREATE,0666)
if err !=nil{
fmt.Printf("open file err=%v\n",err)
}
defer detFile.Close()
// 通过disFile,获取Write
writer:= bufio.NewWriter(detFile)
return io.Copy(writer,reade)
}
func main(){
//将"C:/Users/尘曦/Desktop/2x.jpg"拷贝到D:/abc.jpg
//1
src:="C:/Users/尘曦/Desktop/2x.jpg"
dst:="d:/1.jpg"
_,err:=CopyFile(dst,src)
if err == nil{
fmt.Println("拷贝完成")
}else{
fmt.Println("拷贝失败")
}
}
//执行结果
//PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom10\mian.go
//拷贝完成
统计不同类型的英文、数字、空格和其他字符数量
package main
import (
"bufio"
"fmt"
"io"
//"math/rand"
"os"
"unicode"
)
//定义一个结构体用于保存结果
type CharCount struct{
CharCount int //记录英文个数
NumCount int //记录数字个数
SpaceCount int //记录空格个数
OtherCount int //记录其他字符
Chr int
}
func main(){
//思路: 打开一个文件,创一个Reader
//每读取一行,就去统计该行有多少个英文、数字、空格和其他字符
//然后将结果保存到一个结构体中
fileName:="D:/abc.txt"
file,err := os.Open(fileName)
if err !=nil{
fmt.Println("open file err=",err)//
return
}
defer file.Close()
//定义CharCount 实力
var count CharCount
//创建一个reader
reader:=bufio.NewReader(file)
for {
str,err:=reader.ReadString('\n')
for _,r:=range str{
switch {
case unicode.Is(unicode.Han, r): //匹配中文
count.Chr++
case (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z'):
count.CharCount++
case r >= '0' && r <= '9':
count.NumCount++
case r == ' ' || r == '\t':
count.SpaceCount++
default:
count.OtherCount++
}
}
if err == io.EOF{
break
}
}
fmt.Printf("字符个数%v,数字个数%v,空格个数%v,其他字符个数%v,中文%v",
count.CharCount, count.NumCount, count.SpaceCount,count.OtherCount,count.Chr)
}
命令行参数
希望能够获取到命令行输入的各种参数,该如何处理
基本介绍os.Args是一个string的切片,用来存储所有的命令行参数
package main
import (
"fmt"
"os"
)
func main(){
fmt.Println("命令行的参数个数有",len(os.Args))
//遍历这个切片
for i,v:= range os.Args{
fmt.Printf("agrs[%v]=%v\n",i,v)
}
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go build -o chapter15\deom12\test.exe chapter15\deom12\mian.go
// PS D:\golang\goproject\src\src01\go_code\src> chapter15\deom12\test.exe tom 123 d:/1.txt 909
// 命令行的参数个数有 5
// agrs[0]=D:\golang\goproject\src\src01\go_code\src\chapter15\deom12\test.exe
// agrs[1]=tom
// agrs[2]=123
// agrs[3]=d:/1.txt
// agrs[4]=909
flag 包解析命令行参数
说明:前面的方式是比较原生的方式,对解析参数不是特别的方便,特别是带参数形式的命令行
例如:cmd>main.exe -f c:/aaa.txt -p200 -u root 这样的形式命令行,go 设计者给我们提供flag包,可以方便的解析命令行参数,而且参数顺序可以随意
func (*FlagSet) IntVar
func (f *FlagSet) IntVar(p *int, name string, value int, usage string) IntVar用指定的名称、默认值、使用信息注册一个int类型flag,并将flag的值保存到p指向的变量。
func Parse
func Parse() 从os.Args[1:]中解析注册的flag。必须在所有flag都注册好而未访问其值时执行。未注册却使用flag -help时,会返回ErrHelp。
shil
package main
import (
"fmt"
//"os"
"flag"
)
func main(){
//定义几个变量,用于接收
var user string
var pwd string
var host string
var prot int
//&user用于接收用户命令行输入的-u,后面参数值
//u 就是-u 这个参数
//"" 表示默认值
//"用户名默认为空" 对参数说明
flag.StringVar(&user,"u","","用户名默认为空")
flag.StringVar(&pwd,"pwd","","密码默认为空")
flag.StringVar(&host,"h","localhost","主机默认为localhost")
flag.IntVar(&prot,"port",3306,"默认3306")
//这里有一个非常重要操作,转换,必须调用方法
flag.Parse()
fmt.Printf("user=%v;pwd=%v;host=%v;prot=%v\n",user,pwd,host,prot)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\deom13\mian.go -u chenxi -pwd 123.com -h 127.0.0.1 -port 3306
// user=chenxi;pwd=123.com;host=127.0.0.1;prot=3306
JSON 介绍
json 是一种轻量级的数据,易于人阅读编写,同时也易于机器解析和生成。json 是在2001年开始推广使用的数据格式,目前已经成为主流的数据格式;json易于机器解析和生成,并有效地提升网络传输效率,通常程序在网络传输时会优先将数据(结构体、map等)序列化成json字符串,到接收方得到json字符串时,在反序列化恢复成原来的数据类型(结构体、map等)。这种方式已然成为各个语言的标准

json 数据格式说明
在js 语言中,一切接对象,因此,任何的数据类型都可以通过JSON来表示,如字符串、数字、对象、数组、map、结构体等
JSON键值对是用来保存数据一种形式方法
键/值对组合中的键名写在前面并用双引号“”包裹,使用冒号:分隔然后紧接着值:
例如
{"firstName":"json"}
{"name":"tom","age":"18","address":["北京","上海"]}
[{"name":"tom","age":"18","address":["北京","上海"]},
{"name":"mary","age":"28","address":["北京","上海"]}]
json数据线上解析网址:https://www.json.cn/
json 的序列化
介绍
JSON序列化是指,将key-value 结构的数据类型(如结构体,map,切片)序列化成JSON字符串操作
package main
import (
"encoding/json"
"fmt"
//"strings"
)
type Monster struct{
Name string
Age int
Birthday string
Sal float64
Skill string
}
func tsetStruct() {
//
monster:=Monster{
Name: "牛魔王",
Age: 2500,
Birthday: "1年1月16日",
Sal: 8900,
Skill: "牛魔拳",
}
//将moster序列化
data,err:=json.Marshal(&monster)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
func testMap(){
//定义一个map
var a map[string]interface{}
//
a= make(map[string]interface{})
a["name"]="红孩儿"
a["age"]=30
a["adderss"]="火云洞"
//将map 序列号
data,err:=json.Marshal(a)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
func testSlice(){
var slice []map[string]interface{}
//slice=append(slice, map[string]interface{}{"名字":"雷锋"})
var m1 map[string]interface{}
m1= make(map[string]interface{})
m1["name"]="jack"
m1["age"]= 6
m1["address"]="北京"
slice = append(slice, m1)
var m2 map[string]interface{}
m2=make(map[string]interface{})
m2["Name"]="小龙"
m2["age"]=7
m2["address"]="上海"
slice=append(slice, m2)
data,err:=json.Marshal(slice)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
//对基本数据类型序列号没有什么意义
func tsetInt(){
var num1 float64=123.67
data,err:=json.Marshal(num1)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
func main(){
//演示将结构体、map、切片进行序列化
tsetStruct()
testMap()
testSlice()
tsetInt()
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\json\struct\mian.go
// 序列化后数据={"Name":"牛魔王","Age":2500,"Birthday":"1年1月16日","Sal":8900,"Skill":"牛魔拳"}
// 序列化后数据={"adderss":"火云洞","age":30,"name":"红孩儿"}
// 序列化后数据=[{"address":"北京","age":6,"name":"jack"},{"Name":"小龙","address":"上海","age":7}]
// 序列化后数据=123.67
序列化时指定自定义结构体格式 tag `json:"name"` //tag 指定序列号后的字段格式;在定义结构体字段后指定
package main
import (
"encoding/json"
"fmt"
//"strings"
)
type Monster struct{
Name string `json:"name"` //tag 指定序列号后的字段格式
Age int `json:"age"` //tag 指序列后的字段格式
Birthday string
Sal float64
Skill string
}
func tsetStruct() {
//
monster:=Monster{
Name: "牛魔王" ,
Age: 2500 ,
Birthday: "1年1月16日",
Sal: 8900,
Skill: "牛魔拳",
}
//将moster序列化
data,err:=json.Marshal(&monster)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
func testMap(){
//定义一个map
var a map[string]interface{}
//
a= make(map[string]interface{})
a["name"]="红孩儿"
a["age"]=30
a["adderss"]="火云洞"
//将map 序列号
data,err:=json.Marshal(a)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
func testSlice(){
var slice []map[string]interface{}
//slice=append(slice, map[string]interface{}{"名字":"雷锋"})
var m1 map[string]interface{}
m1= make(map[string]interface{})
m1["name"]="jack"
m1["age"]= 6
m1["address"]="北京"
slice = append(slice, m1)
var m2 map[string]interface{}
m2=make(map[string]interface{})
m2["Name"]="小龙"
m2["age"]=7
m2["address"]="上海"
slice=append(slice, m2)
data,err:=json.Marshal(slice)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
//对基本数据类型序列号没有什么意义
func tsetInt(){
var num1 float64=123.67
data,err:=json.Marshal(num1)
if err !=nil{
fmt.Println("序列号失败",err)
return
}
//输出系列化后结果
fmt.Printf("序列化后数据=%v\n",string(data))
}
func main(){
//演示将结构体、map、切片进行序列化
tsetStruct()
testMap()
testSlice()
tsetInt()
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\json\struct\mian.go
// 序列化后数据={"name":"牛魔王","age":2500,"Birthday":"1年1月16日","Sal":8900,"Skill":"牛魔拳"}
// 序列化后数据={"adderss":"火云洞","age":30,"name":"红孩儿"}
// 序列化后数据=[{"address":"北京","age":6,"name":"jack"},{"Name":"小龙","address":"上海","age":7}]
// 序列化后数据=123.67
反序列化
JSON 反序列号是指,将JSON字符串反序列化成对应的数据类型(结构体、map、切片)的操作
package main
import (
"fmt"
"encoding/json"
)
type Monster struct{
Name string `json:"name"` //tag 指定序列号后的字段格式
Age int `json:"age"` //tag 指序列后的字段格式
Birthday string
Sal float64
Skill string
}
//演示将JSON字符串,反序列化成struct
func unmarshalStruct(){
// 说明str 在项目开发中,是通过网络传输获取到的。。。或者读文件获取到的
str:="{\"name\":\"牛魔王\",\"age\":2500,\"Birthday\":\"1年1月16日\",\"Sal\":8900,\"Skill\":\"牛魔拳\"}"
var monster Monster
//反序列化操作
err:=json.Unmarshal([]byte(str),&monster)
if err !=nil{
fmt.Printf("Unmarshal err=%v\n",err)
}
fmt.Println(monster)
}
//演示将JSON字符串,反序列化成map
func unmarshalmap(){
var a map[string]interface{}
str := "{\"name\":\"牛魔王\",\"age\":2500,\"Birthday\":\"1年1月16日\",\"Sal\":8900,\"Skill\":\"牛魔拳\"}"
//直接反序列化不需要make;因为make操作直接被封装在json.Unmarshal函数里了
err:=json.Unmarshal([]byte(str),&a)
if err !=nil{
fmt.Printf("Unmarshal err=%v\n",err)
}
fmt.Println(a)
}
//将json 反序列切片
func unmarshalslice(){
var slice []map[string]interface{}
str := "[{\"address\":\"北京\",\"age\":6,\"name\":\"jack\"},{\"Name\":\"小龙\",\"address\":\"上海\",\"age\":7}]"
// err:=json.Unmarshal([]byte(str),slice)
// if err!=nil{
// fmt.Printf("Unmarshal err=%v\n",err)
// }
err:=json.Unmarshal([]byte(str),&slice)
if err !=nil{
fmt.Printf("Unmarshal err=%v\n",err)
}
fmt.Println(slice)
}
func main(){
unmarshalStruct()
unmarshalmap()
unmarshalslice()
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter15\unmarshal\main.go
// {牛魔王 2500 1年1月16日 8900 牛魔拳}
// map[Birthday:1年1月16日 Sal:8900 Skill:牛魔拳 age:2500 name:牛魔王]
// [map[address:北京 age:6 name:jack] map[Name:小龙 address:上海 age:7]]
1)在反序列化一个字符串时,要确保反序列化数据类型和序列化前的数据一致(特别)
2)如果json字符串是通过网络程序或者文件读取则不需要再进行“”转义处理。

浙公网安备 33010602011771号