版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010986776/article/details/85749828
需求摘要
- 所有的商品都有一些共性,例如都有品名、价格,个性则无千无万;
- 自行封装出三种商品(以模拟30万种商品)
- 随意给出一个商品的集合,将每件商品的所有属性值输出到《品名.txt》文件中;
需求分析
该需求的难点在于,给过来的商品是什么类型都有的,每种不同类型的商品具体有些什么属性值我们完全无法预知——所以我们可以通过反射来得到这些属性的名值;
导入必要的包
import (
"os"
"encoding/json"
"fmt"
"reflect"
)
胡乱地封装出一些商品
type Computer struct {
Name string
Price float64
Cpu string
Memory int
Disk int
}
type TShirt struct {
Name string
Price float64
Color string
Size int
Sex bool
}
type Car struct {
Name string
Price float64
Cap int
Power string
}
创建商品集合
products := make([]interface{}, 0)
products = append(products, Computer{"未来人类",10000,"英特尔i7",16,1024})
products = append(products, TShirt{"爆款T恤",10000,"红色",40,false})
products = append(products, Car{"兰博比基尼",10000,5,"油电混合"})
获得所有商品的名称
这里我们要反射获得一个叫做Name的属性
for _,p := range products{
//先拿到p的值(不在乎类型)
pValue := reflect.ValueOf(p)
//再通过p值,拿到p下面的名为Name的属性值
nameValue := pValue.FieldByName("Name")
//Name属性的值,反射形式化为正射形式(interface{}类型)
nameInterface := nameValue.Interface()
//将空接口断言为string
name := nameInterface.(string)
fmt.Println(name)
WriteObj2File(p,"D:/BJBlockChain180x/demos/W2/day4/file/"+name+".txt")
}
上述代码还可以简写为
for _,p := range products{
name := reflect.ValueOf(p).FieldByName("Name").Interface().(string)
fmt.Println(name)
WriteObj2File(p,"D:/BJBlockChain180x/demos/W2/day4/file/"+name+".txt")
}
输出商品信息到指定文件
这里我们通过反射获得了任意对象的所有属性名值
func WriteObj2File(obj interface{},filename string) error {
//打开文件
file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil{
return err
}
defer file.Close()
//获得实例信息
oType := reflect.TypeOf(obj)
oValue := reflect.ValueOf(obj)
//获取obj的所有属性名值
for i:=0;i<oType.NumField();i++{
//属性名
fName := oType.Field(i).Name
//获得属性值的字符串形式
fValue := oValue.FieldByName(fName).Interface()
fValueStr := fmt.Sprint(fValue)
//写入文件
_, err = file.WriteString(fName + ":" + fValueStr + "\n")
if err != nil{
return err
}
}
return nil
}
总结
使用常规“正射”对未知类型进行操作难于登天,有了反射,EASY JOB!