golang 第5章 (包管理、序列化和反序列化、反射、文件操作)

本文介绍了Go语言中的包管理,包括结构体定义、包导入与重命名,以及序列化与反序列化(Marshal和Unmarshal)的使用。此外,详细讲解了反射机制,涉及`reflect.Type`,`reflect.Value`,`Kind`,`NumField`,`Field`等概念,并展示了文件操作如读写、复制、创建文件夹、删除和重命名等技巧。
摘要由CSDN通过智能技术生成


包管理

change.go

package ch1

import "fmt"
//ch1 声明一个struct
type Person struct {
	Name string
	Sex  string
	Age  int
}


tempchange.go

package ch1
//不同文件 同包名 对Person结构体(*Perwson 指针类型) 创建方法 Work
import "fmt"
//Work 需要大写 用于可暴露可访问
func (p *Person) Work(x string) string {
	return fmt.Sprintf("%v岁的%v性%v的工作是%v", p.Age, p.Sex, p.Name, x)
}

package main
import (
	"fmt"
	myPkg "testPkg/gopl.io/ch1"
)
//main包中 导入重命名 myPkg(ch1)
func main() {
	v := myPkg.Person{
		Name: "张三",
		Age:  12,
		Sex:  "男",
	}
	//调用指针类型的 Person结构体的实例方法 Work
	fmt.Println((&v).Work("干饭"))
}

1.序列化

Marshal

func Marshal(v interface{})([]byte,error)
package main

import (
   "encoding/json"
   "fmt"
)

func main() {
   p := Person{Name: "小王", Age: 12}
   data, err := json.Marshal(p)
   if err != nil {
      fmt.Println(err)
   } else {
   //返回一个[]byte//使用string转换//{"Name":"小王","Age":12}
      fmt.Println(string(data))
   }
}

type Person struct {
   Name string
   Age  int
}

2.反序列化

Unmarshal

func Unmarshal([]byte,*type)
package main

import (
   "encoding/json"
   "fmt"
)

func main() {
   p := Person{Name: "小王", Age: 12}
   data, err := json.Marshal(p)
   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(string(data))

   }
   var b Person
   json.Unmarshal(data, &b)
   fmt.Println(b)
   //反序列化
}

type Person struct {
   Name string
   Age  int
}

反射

reflect

import "reflect"

1.反射可以在运行时动态获取变量的各种信息,比如变量的类型(type),类别(kind)

2.如果是结构体变量,还可以获取结构体本身的信息(包括结构体的字段、方法)

1、reflect.TypeOf()和reflect.ValueOf()

interface{}类型变量其具体类型可以使用reflect.Tpye来表示,而其具体值则使用reflect.Value来表示。而reflect.Type和reflect.Value分别提供reflect.TypeOf()和reflect.ValueOf()来获取interface{}的具体类型及具体值。

package main

import (
	"fmt"
	"reflect"
)

type order struct {
	ordId     int
	customeId int
}

func query(i interface{}) {
	t := reflect.TypeOf(i)
	v := reflect.ValueOf(i)
	fmt.Println(t)
	fmt.Println(v)
}
func main() {
	o := order{
		ordId:     1,
		customeId: 2,
	}
	query(o)
	//main.order
	//{1 2}
}

2、reflect.Kind()//获取的是底层类型(struct、ptr等)

reflect.Name()获取的是类型名称

import (
	"fmt"
	"reflect"
)

func reflectFn(i interface{}) {
	v := reflect.TypeOf(i)
	fmt.Println(reflect.ValueOf(i))
	fmt.Println("v.Name():", v.Name()) //
	fmt.Println("v.Kind():", v.Kind())
}

type Person struct {
	name string
}

func main() {
	p := Person{name: "123"}
	var h = 25
	reflectFn(&h) // Name Person Kind Struct
	reflectFn(p)
}
0xc0000a6058
v.Name():    
v.Kind(): ptr
&{123}       
v.Name():    
v.Kind(): ptr

在reflect还有一个比较重要的类型Kind,也是代表类型,看起来和我们前面提到的reflect.Type很相似,其实两者有着很大的差异:

package main

import (
	"fmt"
	"reflect"
)

type order struct {
	ordId     int
	customeId int
}

func query(i interface{}) {
	t := reflect.TypeOf(i)
	v := reflect.ValueOf(i)
	k := t.Kind()
	fmt.Println(t)
	fmt.Println(v)
	fmt.Println(k)
}
func main() {
	o := order{
		ordId:     1,
		customeId: 2,
	}
	query(o)
	//main.order
	//{1 2}
	//struct
}

通过输出结果我们能够很清楚的看出来reflect.Type和reflect.Kind:Type代表interface{}实际类型main.order;而Kind代表具体类型struct。

3、NumField() 和Field()

NumField()方法获取一个struct所有的fields,Field(i int)获取指定第i个field的reflect.Value,结合具体实例:

package main

import (
	"fmt"
	"reflect"
)

type order struct {
	ordId     int
	customeId int
}

func query(i interface{}) {
	t := reflect.TypeOf(i)
	v := reflect.ValueOf(i)
	k := t.Kind()
	fmt.Println(t)
	fmt.Println(v)
	fmt.Println(k)
	if reflect.ValueOf(i).Kind() == reflect.Struct {
		value := reflect.ValueOf(i)                       //获取i的值
		fmt.Println("Number of fields", value.NumField()) //获取字段总个数
		for j := 0; j < value.NumField(); j++ {
			fmt.Printf("Field:%d type:%T value:%v\n", j, v.Field(j), v.Field(j)) //获取第j个字段的 reflect.Value的类型 和reflect.value
		}
	}
}
func main() {
	o := order{
		ordId:     1,
		customeId: 2,
	}
	query(o)
	//main.order
	//{1 2}
	//struct
	//Number of fields 2
	//Field:0 type:reflect.Value value:1
	//Field:1 type:reflect.Value value:2
}

4、Int() 和String()

Int()和String()主要用于从reflect.Value提取对应值作为int64和string类型

package main
 
import (  
    "fmt"
    "reflect"
)
 
func main() {  
    a := 56
    x := reflect.ValueOf(a).Int()
    fmt.Printf("type:%T value:%v\n", x, x)
    b := "Naveen"
    y := reflect.ValueOf(b).String()
    fmt.Printf("type:%T value:%v\n", y, y)
 
}
//type:int64 value:56  
//type:string value:Naveen

示例:

package main

import (
	"fmt"
	"reflect"
)

type person struct {
	name string
	age  int
}

func main() {
	p := person{
		name: "嚣张",
		age:  123,
	}
	fmt.Println(reflect.TypeOf(p))
	fmt.Println(reflect.ValueOf(p).Kind())
	x := reflect.ValueOf(p)
	fmt.Println(x.NumField())//reflect.Value的字段个数
	fmt.Println(x.Field(0))//reflect.Value第一个字段的值
	fmt.Println(x.Field(1))//第二个字段的值
	fmt.Printf("%T", x.Field(1))//打印第二个字段的值类型//
	fmt.Printf("%T",x.Field(1).String())//使用String()转类型
}
main.person
struct
2     
嚣张  
123   
reflect.Value
string

1.interface{}类型的值到反射reflecton对象.
根源上来说, reflection的原理就是检查interface中保存的一对值和类型, 所以在reflect包中,有两个类型我们需要记住, Type和Value两个类型. 通过这两个类型,我们可以访问一个interface变量的内容. 调用reflect.ValueOf和reflect.TypeOf可以检索出一个interface的值和具体类型. 当然通过reflect.Value我们也可以获得reflect.Type。
2.反射reflection对象到interface{}类型的值.
通过reflect.Value的Interface方法,我们可以获得一个Interface值。实际上这个方法将一个type和value打包回interface
3.当修改一个反射reflection时, 其值必须是settable.

5.Elem()

当传入的是一个指针类型时候

使用Elem()获取具体的元素值

package main

import (
	"fmt"
	"reflect"
)

func reflectSetValue1(x interface{}) {
	//var a = reflect.ValueOf(x)//ptr 获取到的是指针
	//if a.Kind() == reflect.Int64 {
	//	a.SetInt(120)
	//}
	v := reflect.ValueOf(x)
	fmt.Println(v)//ptr 获取到的是指针
	//v.Elem()获取具体的元素值.Kind()获取类型 
	if v.Elem().Kind() == reflect.Int64 {
	//使用setInt修改
		v.Elem().SetInt(123)
	}

}

func reflectSetValue2(x interface{}) {

}
func main() {
	var a int64 = 100
	reflectSetValue1(&a)//传入指针
	fmt.Println(a)
}

文件操作

读取

1.os.Open//只读方式打开文件

package main

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

func main() {
   //绝对路径
   //os.Open("E:/GO/demo03/main.go")
   //相对路径
   file, err := os.Open("E:/GO/demo03/main.go")
   defer file.Close()
   if err != nil {
      fmt.Println("打开文件失败", err)
      return
   }
   fmt.Println(file)
   //2读取文件里面的记录
   var tempSlice = make([]byte, 128) //
   var strSlice []byte
   for {
      //
      n, err := file.Read(tempSlice)
      if err == io.EOF {
         fmt.Println("读取完毕")
         break
      }
      if err != nil {
         fmt.Println("读取失败")
         return
      }

      fmt.Println("读取到了", n, "字节")
      strSlice = append(strSlice, tempSlice[:n]...)
   }
   fmt.Println(string(strSlice), "string")
}

2.bufio

package main

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

func main() {
	file, err := os.Open("E:/GO/demo01/main.go")
	defer file.Close()
	if err != nil {
		fmt.Println(err)
		return
	}
	var fileStr string
	//bufio读取文件
	reader := bufio.NewReader(file)

	for {
		str, err := reader.ReadString('\n') //表示一次读取一行
		if err == io.EOF {//读取完了可能还会返回io
			fileStr += str
			fmt.Println("文件读取完毕")
			break
		}
		if err != nil {
			fmt.Println("err=", err)
			return
		}
		fmt.Println(str)
	}
	fmt.Println(fileStr)
}

3.readFile(小的简单的文件使用)

package main

import (
	"fmt"
	"os"
)

func main() {
	str, err := os.ReadFile("E:/GO/deo02/main.go")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(str))

}

写入

方法1:

file.Write

package main

import (
	"fmt"
	"os"
)

// 第一种写入文件的方法
func main() {
	file, err := os.OpenFile("E:/GO/README.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	defer file.Close()
	if err != nil {
		fmt.Println("失败", err)
		return
	}
	var str = "卧槽\n"
	//写入文件[]byte
	file.Write([]byte(str))
	//写入文件 string
	//file.WriteString(str)

}

方法2:

bufio操作写入

package main

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

func main() {
	file, err := os.OpenFile("E:/GO/README.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
	defer file.Close()
	if err != nil {
		fmt.Println(err)
		return
	}
	var str = "你好222\n"
	Writer := bufio.NewWriter(file) // bufio.NewWriter传入file对象,创建Writer对象
	//Writer.WriteString(str)         //将数据先写入缓存
	Writer.Write([]byte(str))
	Writer.Flush() //将缓存中的内容写入文件
}

方法2:

os.WriteFile(名字,byte类型切片,权限)

package main

import (
	"fmt"
	"os"
)

func main() {
	//绝对路径
	//os.Open("E:/GO/demo03/main.go")
	//相对路径
	var str = "你好 golang\n"
	err := os.WriteFile("E:/GO/README.txt", []byte(str), 0666)
	if err != nil {
		fmt.Println("失败", err)
	}
}

复制

第一种:os

package main

import (
	"fmt"
	"os"
)

func copy(srcFileName string, dstFileName string) (err error) {
	//读取文件
	byteStr, err := os.ReadFile(srcFileName)
	if err != nil {
		fmt.Println(err)
		return err
	}
	err1 := os.WriteFile(dstFileName, byteStr, 0666)
	if err1 != nil {
		fmt.Println(err1)
		return err1
	}
	fmt.Println("复制文件成功")
	return nil
}
func main() {
	copy("E:/GO/README.txt", "D:/README.txt")
}

第二种:

package main

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

func copy(srcFileName string, dstFileName string) (err error) {
	sFile1, err1 := os.Open(srcFileName)
	defer sFile1.Close()
	sFile2, err2 := os.OpenFile(dstFileName, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)//创建 读写 追加
	defer sFile2.Close()
	if err1 != nil {
		return err1
	}
	if err2 != nil {
		return err2
	}
	var tempSlice = make([]byte, 128)
	for {
		//读取数据
		n1, err := sFile1.Read(tempSlice)

		if err == io.EOF {
			fmt.Println("读取完成")
			break
		}
		if err != nil {
			return err
		}
		//写入数据
		if _, err1 := sFile2.Write(tempSlice[:n1]); err1 != nil {
			return err1
		}

	}
	return nil
}
func main() {
	copy("E:/GO/README.txt", "D:/README.txt")
}

创建文件夹

单个文件夹创建

err:=os.Mkdir("./abc",0666)//在当前目录创建文件夹abc
if err!=nil{
	fmt.Println(err)
}

//重复创建

mkdir ./abc: Cannot create a file when that file already exists.

多级创建

err1 := os.MkdirAll("./dir1/dir2/dir3", 0666)
	if err1 != nil {
		fmt.Println(err1)
	}

删除

删除文件和删除一个目录
package main

import (
	"fmt"
	"os"
)

func main() {
	err := os.Remove("D:/README.txt")
	if err != nil {
		fmt.Println(err)
	}
}
err := os.Remove("abc")
	if err != nil {
		fmt.Println(err)
	}

删除所有的目录

err1 := os.RemoveAll("dir1")
	if err1 != nil {
		fmt.Println(err1)
	}

重命名

err := os.Rename("D:/README.txt", "D:/README1.txt")
	if err != nil {
		fmt.Println(err)
	}
  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值