Go语言头秃之路(五)

本文介绍Go语言中的文件操作方法,包括文件的打开、读取、写入及缓冲区的应用,并详细讲解了JSON的序列化和反序列化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

更新系列

Go语言头秃之路(零)
Go语言头秃之路(一)
Go语言头秃之路(二)
Go语言头秃之路(三)
Go语言头秃之路(四)
Go语言头秃之路(六)
Go语言头秃之路(七)


  • 文件操作
    输入流:文件 -> 程序
    输出流:程序 -> 文件
    • 打开文件:os.OpenFile(filename, open_mode, perm)
      其中文件权限perm只在Linux适用,同Linux文件权限,比如0666表示所有人/所属组/其他人都拥有读写缺陷。
      打开模式open_mode如下,详见官文 - Constants

      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 // 如果可能,打开时清空文件
      )

    • 在缓冲区读取/写入:
      reader := bufio.NewReader(*File)
      text := reader.ReadString(’\n’)
      表示到\n为结束读取符
      writer := bufio.NewWriter(*File)
      writer.WriteString(string)
      writer.Flush()
      写入缓冲区,最后需要Flush才能写入文件
      饭粒:

      package main
      
      import (
      	"os"
      	"fmt"
      	"bufio"
      	"io"
      )
      
      func main()  {
      	filePath := "e:/Go/hsp/abc.txt"
      	file, err := os.OpenFile(filePath, os.O_RDWR | os.O_APPEND, 0666)
      	if err != nil {
      		fmt.Println("open err:", err)
      		return
      	}
      	defer file.Close()
      	reader := bufio.NewReader(file)
      	for {
      		content, err := reader.ReadString('\n')
      		if err == io.EOF {
      			fmt.Println("文件读取完毕。")
      			break
      		}
      		fmt.Print(content)
      	}
      	// 以缓冲区写入
      	writer := bufio.NewWriter(file)
      	str := "你好啊 world!!!\r\n"
      	for i:=0;i<5;i++ {
      		writer.WriteString(str)
      	}
      	// 将缓冲区内容写入文件
      	writer.Flush()
      }
      
    • 一次性读取所有文件内容
      使用io/ioutil包,打开关闭文件逻辑都已经封装到包里面。
      饭粒:拷贝文件

      package main
      
      import (
      	"fmt"
      	"io/ioutil"
      )
      
      func main()  {
      	fileSource := "e:/Go/hsp/abc.txt"
      	fileDist := "e:/Go/hsp/dd.txt"
      	// 一次性读取所有文件内容
      	data, err1 := ioutil.ReadFile(fileSource)
      	if err1 != nil {
      		fmt.Println("read err:", err1)
      	}
      	err2 := ioutil.WriteFile(fileDist, data, 0666)
      	if err2 != nil {
      		fmt.Println("write err:", err2)
      	}
      }
      

  • json

    • 序列化
      json.Marshal
      序列化结构体时,最好传入地址,即前面加上&
      给结构体字段设置标签tag:json:"标签名"
      常用于序列化操作。
    package main
    
    import (
    	"fmt"
    	"encoding/json"
    )
    
    type Company struct {
    	Name string `json:"name"`   // 给结构体字段设置标签tag
    	Age int `json:"age,omitempty"`   // omitempty表示没有值时不赋零值
    	staff_num int `json: "StaffNum,string"`  // 这样生成的json对象中,age就为字符串
    	Address string `json: "-"`   // 不需要进行序列化
    }
    
    func main() {
    	c1 := Company{"yyfax", 6}
    	fmt.Println(c1)
    	cJson, _ := json.Marshal(c1)
    	fmt.Println(string(cJson))
    }
    
    
    • 反序列化
      json.Unmarshal(data []byte, v interface{})
      func UnSeliaMap(strJson string)  {
      	var map1 map[string]interface{}
      	// 这里不需要进行make()  json.Unmarshal方法内部以封装make操作
      	err3 := json.Unmarshal([]byte(strJson), &map1)
      	if err3 != nil {
      		fmt.Println("err:", err3)
      		return
      	}
      	fmt.Println("反序列化map结果:", map1)
      }
      
      注意:
    1. 在反序列化一个json字符串时,要确保反序列化后的数据类型和原来序列化钱的数据类型一致;
    2. 如果json字符串是自定义的,需要对"进行转义;如果json字符串时通过程序获取到的,则不需要进行转义。
  • 号外

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    const tagName = "Testing"
    
    type Info struct {
    	Name string `Testing:"-"`
    	Age  int    `Testing:"age,min=17,max=60"`
    	Sex  string `Testing:"sex,required"`
    }
    
    func main() {
    	info := Info{
    		Name: "benben",
    		Age:  23,
    		Sex:  "male",
    	}
    
    	//通过反射,我们获取变量的动态类型
    	t := reflect.TypeOf(info)
    	fmt.Println("Type:", t.Name())
    	fmt.Println("Kind:", t.Kind())
    
    	for i := 0; i < t.NumField(); i++ {
    		field := t.Field(i) //获取结构体的每一个字段
    		tag := field.Tag.Get(tagName)
    		fmt.Printf("%d. %v (%v), tag: '%v'\n", i+1, field.Name, field.Type.Name(), tag)
    	}
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值