综合练习,写一个Student结构体,并绑定两个带参数的方法Store()ReStore(),并利用到go语言中的,encoding/json, io包、bufio包以及os包。从而完成将结构体实例内容序列化,写入到文件中,然后再从文件中取出,并反序列化,还原成结构体的内容。

model/student.go

package model

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
)
//`json:`为Tag 标签,可以输出首字母为小写的字符串或者任何定义的字符串
type Student struct {
	StuNum int `json:"stuNum"`
	Age int `json:"age"`
	Name string `json:"name"`
	Skill string  `json:"skill"`
	Score float64 `json:"score"`
}
//定义一个结构体数组
type Students []Student

type Operate interface {
	Store(filename string) bool
	ReStore(filename string) (*Students,bool)
}

//序列化的函数方法
func Serialize(this interface{}) []byte {
	dataBytes,err := json.Marshal(this)
	if err != nil {
		fmt.Printf("marshal error =%v\n",err)
		return nil
	}
	return dataBytes
}

//定义一个[]Students结构体的Store()的方法
//并采用os.OpenFile()和bufio包的NewWriter()的方法来打开文件,如果没有此文件则创建
//并将打开的文件清空后,写入新的内容
func (ss *Students) Store(filepath string) bool {
	
	contentBytes := Serialize(&ss)
	
	file,err := os.OpenFile(filepath,os.O_RDWR | os.O_CREATE | os.O_TRUNC,0777)
	if err != nil {
		fmt.Printf("open file error = %v\n",err)
		return false
	}
	defer file.Close()
    //构造一个writer函数,
	writer := bufio.NewWriter(file)
	for i := 0; i < len(string(contentBytes)); i++ {
        //调用WriteByte()按字节写入
		writer.WriteByte(contentBytes[i])
	}
    //从缓冲中取出
	writer.Flush()
	fmt.Println(string(contentBytes))
	return true
}
//定义一个[]Strudents结构体的ReStore()的方法
//采用os.Open()和ioutil.ReadAll(),来读取较大的文件
func (ss *Students) ReStore(filename string) (*Students,bool) {
	file, err := os.Open(filename)
	if err != nil {
		fmt.Printf("Open file error =%v\n",err)
	}
	defer file.Close()
	contentBytes,err := ioutil.ReadAll(file)
	if err != nil {
		fmt.Println("Read file error =",err)
	}
	
	err = json.Unmarshal(contentBytes,&ss)
		if err != nil  {
			fmt.Println("Unmarshal data error = ",err)
		}
	return ss,true
} 

//读取文件的另一种函数方法
//采用os.Open()和file.Read()的方法,即以文件对象调用Read()的方法
func ReadFile(filename string) {
    fileObj,err := os.Open(filename) 
	if err == nil {
        defer fileObj.Close()
        //定义一个新的byte切片列表,空间设置1024,根据要读入的文件大小自定义。如果太小了,会造成文件读取不完整。
        buf := make([]byte, 1024)
        n,err := fileObj.Read(buf)
		if err == nil {
			fmt.Println("The number of bytes read:",n,"Buf length:",len(buf))
			fmt.Println("Use os.Open and File's Read method to read a file:",string(buf))
        }
    }
}

main/main.go

package main

import (
	"fmt"
	"go_code/.../model"
)


func main() {

	filepath := "./student.txt"
	var stus = &model.Students{model.Student{
			StuNum: 1,
			Name : "许小明",
			Age : 17,
			Skill : "游泳",
			Score: 613.5,
			},
		model.Student{
			StuNum: 2,
			Name : "王怡人",
			Age : 16,
			Skill : "乒乓",
			Score: 583.5,
		},
		model.Student{
			StuNum: 3,
			Name : "李安然",
			Age : 17,
			Skill : "篮球",
			Score: 683.5,
		},
	}
	//重新定义个operate,并将stus赋值给operate
	var operate model.Operate = stus
	
	ok := operate.Store(filepath)
		if ok {
			fmt.Println("this data stroed successfully...")
		}
	stus,flag := operate.ReStore(filepath)
		if flag {		
			fmt.Printf("this data retrieved from this path: %q, contents is : %v\n",filepath,*stus)			
		}else {
			fmt.Println("this data retrieved failed...")
		}
	model.ReadFile(filepath)			
}

输出的结果:

[{"stuNum":1,"age":17,"name":"许小明","skill":"游泳","score":613.5},{"stuNum":2,"age":16,"name":"王怡人","skill":"乒乓","score":583.5},{"stuNum":3,"age":17,"name":"李安然","skill":"篮球","score":683.5}]

this data stroed successfully...

this data retrieved from this path: "./student.txt", contents is : [{1 17 许小明 游泳 613.5} {2 16 王怡人 乒乓 583.5} {3 17 李安然 篮球 683.5}]

The number of bytes read: 217 Buf length: 1024

Use os.Open and File's Read method to read a file: [{"stuNum":1,"age":17,"name":"许小明","skill":"游泳","score":613.5},{"stuNum":2,"age":16,"name":"王怡人","skill":"乒乓","score":583.5},{"stuNum":3,"age":17,"name":"李安然","skill":"篮球","score":683.5}]