Day05 Go语言文件操作,结构体,构造函数,方法接收器,json序列化

Posted 澐湮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day05 Go语言文件操作,结构体,构造函数,方法接收器,json序列化相关的知识,希望对你有一定的参考价值。

01上节回顾

今日重点:结构体和文件操作

函数回顾

函数:一种代码组织形式

打印菱形,解决代码冗余问题,可维护性

package main

import (
   "fmt"
   "reflect"
)

func  foo() string 
   fmt.Println("foo...")
   return "foo"


func main() 
   //[3]int [4]int 长度为3的数组类型,长度为4的数组类型,不一样
   var x=100
   fmt.Println(x)
   fmt.Println(foo,reflect.TypeOf(foo)) //0xc6c560 打印出来一个地址
   foo()

   bar:=foo //加括号,返回值赋给bar。不加括号把函数拷贝给bar
   bar() //存储的相同的内容,不是一块儿内存空间
  

上节核心考点值传递

 

参数回顾

示例1 参数

package main

import (
   "fmt"
   "reflect"
)

func add(x,y int) int 
   return x+y


func main() 
   //参数
   fmt.Println(add(1,5))

示例2 作用域

package main

import "fmt"

func add(a,b int) int 
   a=100
   return a+b


func main() 
   //参数
   var a,b=1,2
   fmt.Println(add(a,b)) // 102
   fmt.Println(a,b) // a和b还是1和2 注意作用域问题

指针类型回顾

取地址能做什么?

指针声明和赋值

package main

import (
   "fmt"
   "reflect"
)

func main() 
   var x = "hello"
   //var p =&x
   var p *string
   p=&x //取址
   fmt.Println(p,reflect.TypeOf(p))
   //取值 *指针变量
   fmt.Println(*p) //hello

指针应用

指针应用1 没有使用指针时

package main

import (
   "fmt"
   "reflect"
)

func bar(t int) 
   t=100


func main() 
   //指针应用
   var t = 1
   bar(t)
   fmt.Println(t)

打印结果还是1 

指针应用2 打印出地址

package main

import (
   "fmt"
)

func bar(p *int) 
   *p=100
   fmt.Println("bar函数p地址",p)


func main() 
   //指针应用2
   var t=1
   var p =&t
   fmt.Println("main p地址",p)
   bar(p)

图解

通过指向同一地址空间,实现修改

 

指针应用3 修改指针对应的值

package main

import (
   "fmt"
)

func bar(p *int) 
   *p=100
   fmt.Println("bar函数p地址",p)


func main() 
   //指针应用
   var t=1
   var p =&t
   fmt.Println("main p地址",p)
   bar(p)
   fmt.Println("main t",t)

02 上节回顾2

 

匿名函数

 

匿名函数可以在使用函数的时候声明调用

package main

import "fmt"

func main() 
    //(1)
   (func() 
      fmt.Println("yuan")
   )()
   
   //(2)
   var z=(func(x,y int)int 
      return x+y
   )(1,2)
   fmt.Println(z)

高阶函数

2个点

  函数作为参数

  函数作为返回值

函数作为参数

值拷贝,存的函数,拷贝函数,赋给f

 

package main

func test02() 



func test01(f func())



func main() 
   test01(test02)

 

函数作为返回值

outer为高阶函数

 

package main

func outer() func() 
   return func() 

   

 

闭包

流程判断相关:循环、 if else 是否开辟作用域?? 开辟了作用域

 

package main

import "fmt"

func main() 
    if true 
      var x=100
      fmt.Println(x)
   
   fmt.Println(x) //报错,作用域问题

 

一个内部的函数,引用了外部的自由变量

闭包函数一调用,返回匿名函数

 

不是闭包函数

没有引用外部非全局变量

//不是闭包函数
func biBao() func() 
   var ret=func()
      var x=10
      fmt.Println(x)
   
   return ret


func main()    
   f:=biBao()
   f()

闭包函数

被引用的x,被保留下来了。

 

package main

import "fmt"

func biBao() func()  //闭包
   var x=10
   var ret=func()
      fmt.Println(x)
   
   return ret

 

闭包函数2 地址空间

var x=10 x=100 用的是一块地址空间

 

package main

import "fmt"

func biBao() func()  //不是闭包函数
   var x=10
   fmt.Println(&x)
   var ret=func()
      x=100
      fmt.Println(":::",&x)
   
   return ret


func main() 
   f:=biBao()
   f()

打印结果
0xc00000a0b8
::: 0xc00000a0b8

 

内部使用x:=100,var x=10 x:=100 用的不是一块地址

此时仍然是闭包函数,&x引用了外部自由变量

 

package main

import "fmt"

func biBao() func()  //不是闭包函数
   var x=10
   fmt.Println(&x)
   var ret=func()
      fmt.Println(&x)
      x:=100
      fmt.Println(":::",&x)
   
   return ret


func main() 
   f:=biBao()
   f()

打印结果
0xc000102058
0xc000102058
::: 0xc000102090

 

作用域问题

x地址一样

 

func test2() 
   var x=10
   fmt.Println(&x)
   if true 
      //if开辟作用域,也用了外部的变量
      fmt.Println(x)
   

 

x地址不一样,又开辟了空间

 

func test() 
   var x=10
   fmt.Println(&x)
   if true 
      //if开辟作用域,也用了外部的变量
      var x=1
      fmt.Println(x)
   

 

defer语句回顾

遇到return执行defer问题

 

03 编码小历史

编码

程序部分和存储部分分离

 

存储结构:内存和外存

CPU 运算器和控制器

输入和输出设备

 

高低电频

汇编语言:引入英文字母,极大提高性能。

编码系统:字母和二进制数字对应起来

ASCII表:最原始的编码表

 

利用多大空间存储:

  bit

  8bit1字节 存256个二进制数字

 

ASCII表 用来127

ASC扩展: 拉美使用了扩展位

0 000  0000

0 48 A 65  a 97

 

GBK- 2个字节 65536

0000 0000  0000 0000

---- ----  ---- ----

 

Unicode编码:一个符号4字节

0000 0000  0000 0000  0000 0000  0000 0000

 

UTF8编码(可伸缩的编码方式)

针对ASCII就用一个字节

针对汉字使用三个字节

package main

import "fmt"

func main() 
    var a=\'0\'
   fmt.Println(a)
   var b = 48
   fmt.Printf("%c",b)

打印结果
48
0

04 Go的字符和字节

Go的字符与字节

byte就是字节,一个字节就是8个二进制位。uint8无符号整型,

byteuint8本质没区别,都是ASCII码表的一个字符

 

package main

import "fmt"


func main() 
   var x uint8
   x=255
   fmt.Println(x) //255
   var  b byte
   b=\'A\'
   fmt.Println(b) //65
   fmt.Printf("%c:%d\\n",b,b) //A:65

 

run占用4字节,32bit位,run本质和int32没区别,表示一个Unicode字符

package main

import "fmt"

func main() 
   var r rune
   r=\'a\'
   fmt.Printf("%c:%d\\n",r,r) //a:97
   r=\'中\'
   fmt.Printf("%c:%d\\n",r,r) //中:20013

字符串和字节串转换

编码与解码

package main

import (
   "fmt"
   "reflect"
)

func main() 
   //字符串与字节串之间的转换
   var s="沙河"
   fmt.Println(s,reflect.TypeOf(s))
   var b = []byte(s)
   fmt.Println(b,reflect.TypeOf(b)) //3个字节对应一个汉字 [230 178 153 230 178 179] []uint8

   fmt.Println(string(b))

编码和解码

func main() 
   //编码
   var s = "沙河"
   b:=[]byte(s)
   fmt.Println(b,reflect.TypeOf(b))
   //解码
   fmt.Println(string(b))

下午 05 字符串

遍历字符串

三要素for循环

func main() 
    //遍历字符串
   //方式1 索引方式(会出现乱码)
   var hi= "hello 你好"
   for i:=0;i<len(hi);i++ 
      //fmt.Println(string(hi[i]))
      fmt.Printf("%c",hi[i])
   

range

    //遍历字符串
   //方式2 用range方式遍历
   for i,v:=range hi 
      fmt.Println(i,string(v))
   

go语言中的字符串字符不可以修改

    //go语言中的字符串字符不可以修改
   fmt.Println(hi[0])
   hi[0]=\'i\'

下午06 读文件

读文件:读到内存

写文件: 从内存写入

打开文件

var data = make([]byte,3)
fmt.Println("data init",data) //data init [0 0 0]

首字母大写表示公开的,小写表示私有的

package main

import (
   "fmt"
   "os"
)

func main() 
   //打开文件
   var file,err=os.Open("天道")
   //报错处理
   if err != nil 
      fmt.Println("err",err)
   
   //延迟注册
   defer file.Close()

   //读文件数据
   var data = make([]byte,3)
   fmt.Println("data init",data) //data init [0 0 0]

   n,err:=file.Read(data)
   if err != nil 
      fmt.Println("err::",err)
   
   fmt.Println("n:",n) //n: 3

1 按字节读文件(使用不多)

package main

import (
   "fmt"
   "os"
)
func readBytes(file *os.File)
   var data = make([]byte,3)
   fmt.Println("data init",data)
   n,err:=file.Read(data)
   if err != nil 
      fmt.Println("err::",err)
   
   fmt.Println(n)
   fmt.Println("data:",string(data))


func main() 
   //打开文件
   var file,err=os.Open("天道")
   //报错处理
   if err != nil 
      fmt.Println("err",err)
   
   //延迟注册
   defer file.Close()

   //按字节读文件数据
   readBytes(file)

2 按字符串读

示例1

分隔符,字节类型

打印换行问题

原内容有换行,println又增加了一个换行,使用print fmt.Print(line)

 

package main

import (
   "bufio"
   "fmt"
   "io"
   "os"
)

func main() 
   //打开文件
   var file, err = os.Open("天道")
   //报错处理
   if err != nil 
      fmt.Println("err", err)
   
   //延迟注册
   defer file.Close()

   //(2)按字符串
   reader:=bufio.NewReader(file)
   for true 
      line,err:=reader.ReadString(\'\\n\')
      fmt.Print(line)
      if err==io.EOF 
         break
      
   

 

示例2 放入函数中

package main

import (
   "bufio"
   "fmt"
   "io"
   "os"
)

func readString(file *os.File) 
   reader:=bufio.NewReader(file)
   for true 
      line,err:=reader.ReadString(\'\\n\')
      fmt.Print(line)
      if err==io.EOF 
         break
      
   


func main() 
   //打开文件
   var file, err = os.Open("天道")
   //报错处理
   if err != nil 
      fmt.Println("err", err)
   
   //延迟注册
   defer file.Close()

   //(2)按字符串
   readString(file)

3 读取整个文件

package main

import (
   "fmt"
   "io/ioutil"
   "os"
)

func main() 
   //打开文件
   var file, err = os.Open("天道")
   //报错处理
   if err != nil 
      fmt.Println("err", err)
   
   //延迟注册
   defer file.Close()
   //(3)读取整个文件
   content,err:=ioutil.ReadFile("天道")
   fmt.Println(string(content))

注意:文件中有空行符就都会打印

下午07 写文件

1 写字节

打开文件OpenFile

package main

import (
   "fmt"
   "os"
)

func main() 
   //文件名 模式 权限
   file,err:=os.OpenFile("天道2",os.O_CREATE|os.O_WRONLY|os.O_TRUNC,0666)
   if err != nil 
      fmt.Println("open file failed,err",err)
   
   defer file.Close()
   //写字节
   var s="悟道休言天命2"
   //file.Write([]byte(s)) //写字节
   file.WriteString(s)

 

2 写字符串

package main

import (
   "bufio"
   "fmt"
   "os"
)

func main() 
   //文件名 模式 权限
   file,err:=os.OpenFile("天道2",os.O_CREATE|os.O_WRONLY|os.O_TRUNC,0666)
   if err != nil 
      fmt.Println("open file failed,err",err)
   
   defer file.Close()
   //(2)写字符串
   writer:=bufio.NewWriter(file)
   writer.WriteString("修行勿取真经。")
   //更新磁盘
   writer.Flush()

3写文件

WriteFile是覆盖,文件不存在时,会创建

 

package main

import (
   "io/ioutil"
)

func main() 
   //(3)
   s:=`
   悟道休言天命
   修行勿取真经`
   ioutil.WriteFile("天道3",[]byte(s),0666)

 

下午08 声明结构体并实例化

声明结构体

格式

字段名必须唯一,可以通过逗号隔开

 

type 类型名 struct    //标识结构体的类型名,在同一个包内不能重复
   字段1 字段1类型  //字段名必须唯一
   字段2 字段2类型

 

同类型的变量也可以写在一行,用逗号隔开

type Book struct 
   title,author string
   price int

示例

//声明一个结构体
type Student struct 
   name string //结构体的成员变量
   age int
   score map[string]int

实例结构体对象

结构体和结构体的实例对象

先有对象,具有相同属性和行为的对象,称为类。

有这些属性的个体,称为对象。

 

方式1 先声明,再赋值

package main

import "fmt"

//声明一个结构体
type Student struct 
   name string //结构体的成员变量
   age int
   score map[string]int



func main() 
   //实例结构体对象

   //方式1 直接声明  先声明,再赋值
   var s Student //结构体是值类型
   fmt.Println("s",s) //s  0 map[]

图示:开辟内存空间

 

 

 

赋值

package main

import "fmt"

//声明一个结构体
type Student struct 
   name  string //结构体的成员变量
   age   int
   score map[string]int


func main() 
   //实例结构体对象,支持.操作

   //方式1 先声明,再赋值
   var s Student       //结构体是值类型
   fmt.Println("s", s) //s  0 map[]
   s.name = "zhangsan"
   s.age = 22
   s.score = map[string]int"语文": 95, "数学": 98, "英语": 93
   fmt.Println(s.age) //22
   fmt.Println(s)     //zhangsan 22 map[数学:98 英语:93 语文:95]

下午 09 结构体实例化方式

方式2 声明并赋值(键值对赋值)

package main

import "fmt"

//声明一个结构体
type Student struct 
   name  string
   age   int
   score map[string]int


func main() 
   //实例结构体对象,支持.操作

   //方式2 声明并赋值
   var s2 Student
   s2 = Studentname: "rain", age: 32, score: map[string]int"语文": 100, "数学": 90, "英语": 80
   fmt.Println(s2)              //rain 32 map[数学:90 英语:80 语文:100]
   fmt.Println(s2.age)          //32
   fmt.Println(s2.score["数学"]) //90

方式3 声明并赋值(多值赋值)

    //方式3 声明并赋值 多值赋值
   s3:=Student"alvin",18, map[string]int"yuwen":100,"shuxue":90,"yingyu":89
   fmt.Println(s3)

s3的地址和s3.name的地址一样吗?

一样

package main

import "fmt"

//声明一个结构体
type Student struct 
   name string
   age int
   score map[string]int


func main() 
   //实例结构体对象,支持.操作

   //方式3 声明并赋值 多值赋值
   s3:=Student"alvin",18, map[string]int"yuwen":100,"shuxue":90,"yingyu":89
   fmt.Println(s3)
   fmt.Printf("%p,%p\\n",&s3,&s3.name) //0xc0000444a0,0xc0000444a0

练习中的思考

练习补充1:结构体中切片元素添加

对学生管理结构体中添加学生成绩

package main

import "fmt"

type Student struct 
   Name string //结构体成员变量
   Age int
   Score [3]int


type StudentManager struct 
   AllStu []Student

func main() 
   smm:=StudentManager[]Student
   var stu1 Student=Student"张三",18,[3]int90,98,97
   stu2:=Student"李四",19,[3]int91,92,93
   stu3:=Student"zhngsan",20,[3]int99,98,95
   smm.AllStu=append(smm.AllStu,stu1)
   smm.AllStu=append(smm.AllStu,stu2)
   smm.AllStu=append(smm.AllStu,stu3)
   fmt.Println(smm) 

打印结果
[张三 18 [90 98 97] 李四 19 [91 92 93] zhngsan 20 [99 98 95]]

练习补充2:结构体中map对象添加元素(开辟空间)

package main

import "fmt"

type Student struct 
   Name string
   Age    int
   score [3]int

type StuManager struct 
   Id int
   allStu map[string]Student

func main() 
   smm:=StuManager
   //需要先开辟空间,否则报错
   smm.allStu=make(map[string]Student)
   fmt.Println(smm)

   stu1:=Student"zhangsan",19,[3]int90,98,97
   smm.Id=1001
   smm.allStu["1001"]=stu1
   stu2:=Student"lisi",20,[3]int80,90,95

   //注意:Id是值元素,再赋值时覆盖
   smm.Id=1002
   //map元素 不存在时添加,存在时修改
   smm.allStu["1002"]=stu2

   //stu3:=Student"lisi",20,[3]int80,90,95
   //smm.allStu["1001"]=stu3 //会覆盖map键对应"1001"的值
   fmt.Println(smm) //1002 map[1001:zhangsan 19 [90 98 97] 1002:lisi 20 [80 90 95]]

练习补充3:结构体中map对象添加元素2(开辟空间)

有两个学生对象,添加到结构体中(结构体中对象是map类型)

 

package main

import "fmt"

type Student struct 
   Name string
   Age    int
   score [3]int

type StuManager struct 
   allStu map[string]Student

func main() 
   smm:=StuManager
/* //需要先开辟空间,否则报错
   smm.allStu=make(map[string]Student)
   fmt.Println(smm)*/

   stu1:=Student"zhangsan",19,[3]int90,98,97
   stu2:=Student"lisi",20,[3]int80,90,95

   //smm.allStu["1001"]=stu1
   s1:=map[string]Student"1001":stu1
   s2:=map[string]Student"1002":stu2


   //当有两个学生对象,如何加入结构体?还是需要先开辟空间,再遍历

/* //这种会导致覆盖
   smm.allStu=s1
   smm.allStu=s2*/

   smm.allStu=make(map[string]Student)
   for k,v:=range s1 
      smm.allStu[k]=v
   
   for k,v:=range s2 
      smm.allStu[k]=v
   
   fmt.Println(smm) //map[1001:zhangsan 19 [90 98 97] 1002:lisi 20 [80 90 95]]

 

练习补充4:再回顾map

如果不是声明并赋值map[string]string1001:stu1这种使用map的方式,

直接使用map[1001]=stu1需开辟空间

 

package main

import "fmt"

func main() 
   var smm map[string]map[string]string
   stu1:=map[string]string"sid":"1001","name":"zhangsan","age":"18","yuwen":"99","shuxue":"98","yingyu":"95"
   smm= map[string]map[string]string"1001":stu1
   //smm["1001"]=stu1 //这种报错,没有开辟空间
   stu2:=map[string]string"sid":"1002","name":"lisi","age":"19","yuwen":"99","shuxue":"98","yingyu":"95"
   smm["1002"]=stu2
   fmt.Println(smm)

 

下午10 结构体的指针变量

值拷贝

变量赋值后,修改s2,s.name发生变化吗? 不变,已经是不同的地址空间

 

package main

import "fmt"

//声明一个结构体
type Student struct 
   name string
   age int
   score map[string]int


func main() 

   var s=Studentname:"rain",age: 30,score: map[string]int"语文":100,"数学":90,"英语":80
   s2:=s
   s2.name="yuan"
   fmt.Println(s.name)

 

图解

 

 

 

值拷贝,函数传入结构体指针

package main

import "fmt"

//声明一个结构体
type Student struct 
   name string
   age int
   score map[string]int


func foo(p *Student) 
   //如果p是一个结构体的指针变量,name执行p.name的时候,编译器会翻译成(*p).name
   p.name="yuan"  
   fmt.Println(*p)
   //(*p).name = "yuan"


func main() 

   //s是一个结构体对象
   var s=Studentname:"rain",age: 30,score: map[string]int"语文":100,"数学":90,"英语":80
   //案例1
   /*s2:=s
   s2.name="yuan"
   fmt.Println(s.name)*/

/* //案例2
   foo(s)
   fmt.Println(s) //不变 rain 30 map[数学:90 英语:80 语文:100]*/
   //案例2 
   var p=&s //是一个Student结构体的指针对象
   foo(p)
   fmt.Println(s)

下午11 模拟构造函数

示例1 通过调用函数,获取结构体对象

package main

import "fmt"

type Student struct 
   name string
   age int
   score map[string]int


func NewStudent(name string,age int,score map[string]int) Student
   return Studentname:name,age:age,score: score


func main() 
   //var s = Studentname: "rain", age: 32, score: map[string]int"yuwen": 100, "shuxue": 90, "yingyu": 80
   s:=NewStudent("zhangsan",18, map[string]int"语文":100,"数学":90,"英语":89)
   fmt.Println(s) //zhangsan 18 map[数学:90 英语:89 语文:100]

示例2

package main

import "fmt"

type Student struct 
   name string // 结构体的成员变量
   age int
   score map[string]int


func NewStudent(name string,age int,score map[string]int) *Student 
   return &Studentname:name,age:age,score:score


func main() 
   s:=NewStudent("yuan",23, map[string]int"yuwen":100,"shuxue":90,"yingyu":89)
   fmt.Println(s)
   fmt.Println(s.name)

下午12 方法接收器

示例1 声明结构体

package main

//声明一个结构体
type Player struct 
   name string //结构体的成员变量
   healthPoint int
   magic int


func NewPlayer(name string,healthPoint int,magic int) *Player 
   return &Playername:name,healthPoint: healthPoint,magic: magic


func main() 
   p:=NewPlay("yuan",100,80)
   fmt.Println(p.name)
   fmt.Println(p.healthyPoint)


打印结果
yuan
100

示例2 声明接收器方法

调用是会把yuan赋值给小p

这时候用p.name

 

package main

import "fmt"

//声明一个结构体
type Player struct 
   name string //结构体的成员变量
   healthPoint int
   magic int


func NewPlayer(name string,healthPoint int,magic int) *Player 
   return &Playername:name,healthPoint: healthPoint,magic: magic


func (p Player)attack() 
   fmt.Println(p.name,"发起攻击")


func (p Player)attacked() 
   fmt.Println("被攻击")



func main()
   yuan:=NewPlayer("yuan",100,100)
   rain:=NewPlayer("rain",100,100)

   yuan.attack()
   rain.attack()


打印结果
yuan 发起攻击
rain 被攻击

 

示例3 修改修改被攻击的对象

package main

import "fmt"

type Player struct 
   name string
   healthyPoint int
   magic int


func (p Player)attack() 
   fmt.Println(p.name,"发起攻击")


func (p Player)attacked() 
   fmt.Println(p.name,"被攻击")
   p.healthyPoint=p.healthyPoint-30

图示

执行rain.attacked时,rain发生值拷贝,开辟p空间

执行 -30p发生-30操作

 

 

示例4 对外部的值做操作,传指针。

package main

import "fmt"

//声明一个结构体
type Player struct 
   name string //结构体的成员变量
   healthPoint int
   magic int


func NewPlayer(name string,healthPoint int,magic int) *Player 
   return &Playername:name,healthPoint: healthPoint,magic: magic


func (p Player)attack() 
   fmt.Println(p.name,"发起攻击")


func (p *Player)attacked() 
   fmt.Println("被攻击")
   p.healthPoint=p.healthPoint-30



func main()
   yuan:=NewPlayer("yuan",100,100)
   rain:=NewPlayer("rain",100,100)

   yuan.attack()
   rain.attacked()
   fmt.Println(rain.healthPoint)

下午13 json序列化

是一种数据交换格式

go语言数据类型

json支持的类型

整型、浮点型

整型、浮点型

字符串(双引号)

字符串双引号

逻辑值(truefalse

逻辑值(truefalse

数组,切片

数组(在方括号中)

map

对象(再花括号中)

nil

null

 

示例1 map序列化

package main

import (
   "encoding/json"
   "fmt"
)

func main()
   //var map01 = map[int]string1:"111",2:"222",3:"333"
   var map01=map[string]interface"name":"yuan","isMarried":false,"score":[3]int100,90,89
   content,_:=json.Marshal(map01)
   fmt.Println(string(content)) //"isMarried":false,"name":"yuan","score":[100,90,89]

示例2 struct序列化

package main

import (
   "encoding/json"
   "fmt"
)

type Student struct 
   name string
   age int
   score [3]int


func main() 
   s:=Student
      name:"yuan",
      age:22,
      score: [3]int1,2,3,
   
   content,_:=json.Marshal(s)
   fmt.Println(string(content)) //

会打印出来空的,为什么空?

小写,是私有的

 

需要首字母大写

package main

import (
   "encoding/json"
   "fmt"
)

type Student struct 
   Name string //结构体成员变量
   Age int
   Score [3]int


func main() 
   s:=Student
      Name:"yuan",
      Age:22,
      Score: [3]int1,2,3,
   
   content,_:=json.Marshal(s)
   fmt.Println(string(content)) //"Name":"yuan","Age":22,"Score":[1,2,3]

序列化后,写入文件中

package main

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
)

type Student struct 
   Name string //结构体成员变量
   Age int
   Score [3]int


func main() 
   s:=Student
      Name:"yuan",
      Age:22,
      Score: [3]int1,2,3,
   
   content,_:=json.Marshal(s)
   fmt.Println(string(content)) //"Name":"yuan","Age":22,"Score":[1,2,3]

    //写入文件中
   //ioutil.WriteFile("data.txt",[]byte(s),0666) //结构体不能直接转
   ioutil.WriteFile("data.txt",content,0666)

读文件

读取出来是字符串

package main

import (
   "fmt"
   "io/ioutil"
)

func main() 
   //读文件
   content,_:=ioutil.ReadFile("data.txt")
   fmt.Println(string(content)) //"name":"yuan","age":18,"score":[1,2,3]

data.txt文件内容

 

"name":"yuan","age":18,"score":[1,2,3]

反序列化

Unmarshal(字节串,&结构体)

不加&符,发生值拷贝,目的是需要改s2对应的值(即通过指针,修改)

 

package main

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
)

type Student struct 
   Name  string `json:"name"`
   Age   int  `json:"age"`
   Score [3]int `json:"score"`


func NewStudent(name string, age int, score [3]int) Student 
   return StudentName: name, Age: age, Score: score

func main() 
   //读文件
   content,_:=ioutil.ReadFile("data.txt")
   //fmt.Println(string(content)) //"name":"yuan","age":18,"score":[1,2,3]

   //反序列化 json字符串转换成golang支持的数据类型
   var s Student
   json.Unmarshal(content,&s)
   fmt.Println(s) //yuan 18 [1 2 3]
   fmt.Println(s.Name) //yuan
   fmt.Println(s.Age) // 18

 

gojs代码交换

JSON.stringify(s)

 

 

package main

import (
   "encoding/json"
   "fmt"
)

func main() 
//go与js进行json交换
   s1:=`"name":"yuan","age":18,"gf":null`
   var m1=make(map[string]interface)
   json.Unmarshal([]byte(s1),&m1)
   fmt.Println(m1)
   fmt.Println(m1["name"])

打印结果
map[age:18 gf:<nil> name:yuan]
yuan

问题

文件中存的是单引号,是否有影响?

"name":\'yuan\',"age":18,"score":[1,2,3]

是字符串,不是json字符串,

Unmarshal之前必须给个json字符串

 

package main

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
)

type Student struct 
   Name  string `json:"name"`
   Age   int  `json:"age"`
   Score [3]int `json:"score"`


func main() 
    content,_:=ioutil.ReadFile("data.txt")
   fmt.Println(string(content)) //"name":\'yuan\',"age":18,"score":[1,2,3]

   var stu Student
   json.Unmarshal(content,&stu)
   fmt.Println(stu) // 0 [0 0 0] 换成单引号,不是json字符串,打印默认值 

 

作业:结构体版 学生管理系统

1、结构体实现

2、持久化

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

以上是关于Day05 Go语言文件操作,结构体,构造函数,方法接收器,json序列化的主要内容,如果未能解决你的问题,请参考以下文章

Go语言学习——结构体构造函数方法和接收者给自定义类型添加方法

Go语言学习之旅--结构体

Go语言学习之旅--结构体

Go语言学习之旅--结构体

Go语言结构体

Go语言结构体