1. 问题
xml字段除了int, string, float等基本类型, 还有可能是slice, struct等复合类型
那么对于基本类型外的字段, 如何随机初始化呢
2. 分析
复合类型本质还是由基本类型构成的, 只要将其拆解成基本类型, 就能顺利完成
3. 实例
3.1. 模板
package element
import "encoding/xml"
type CommonXmlStruct struct {
XMLName xml.Name `xml:"person"`
Name string `xml:"name"`
Age int `xml:"age"`
IsAdult bool `xml:"isAdult"`
Emails []Email `xml:"email,omitempty"`
}
type Email struct {
Where string `xml:"where,attr"`
Addr string `xml:"addr"`
}
3.2. 解析
package main
import (
"encoding/xml"
"fmt"
"idc/element"
"math/rand"
"reflect"
"time"
)
const SLICE_MAX_LENGTH = 5
// 随机种子
func init() {
rand.Seed(time.Now().UnixMicro())
}
// 根据字段类型, 自动随机赋值
func RandInitXmlField(v reflect.Value, name string) {
if !v.CanSet() {
return
}
switch v.Kind() {
case reflect.Int:
v.SetInt(int64(rand.Intn(100)))
case reflect.Bool:
v.SetBool(rand.Intn(10) < 5)
case reflect.String:
v.SetString(fmt.Sprintf("%s-%04d", name, rand.Intn(1000)))
case reflect.Struct:
v.Set(RandInitStruct(v))
case reflect.Slice:
v.Set(RandInitSliceField(v, SLICE_MAX_LENGTH, name))
default:
panic("unsupported field type: " + v.Kind().String())
}
}
// 自动初始化slice
func RandInitSliceField(v reflect.Value, size int, name string) reflect.Value {
if size < 0 {
panic("slice length must >= 0")
}
length := rand.Intn(size)
dst := reflect.MakeSlice(v.Type(), length, length)
for i := 0; i < dst.Len(); i++ {
indexVal := dst.Index(i)
RandInitXmlField(indexVal, name)
}
return dst
}
// 自动初始化struct
func RandInitStruct(v reflect.Value) reflect.Value {
dst := reflect.New(v.Type()).Elem()
for i := 0; i < dst.NumField(); i++ {
tmpField := dst.Field(i)
tmpFieldName := dst.Type().Field(i).Name
RandInitXmlField(tmpField, tmpFieldName)
}
return dst
}
// 获取自动初始化后的struct实例
func NewRandXML(st any) any {
v := reflect.ValueOf(st)
if v.Kind() != reflect.Struct {
panic("xml must be struct")
}
dst := RandInitStruct(v)
return dst.Interface()
}
func main() {
commonXML := element.CommonXmlStruct{}
v := NewRandXML(commonXML)
xmlBytes, err := xml.MarshalIndent(v, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(xmlBytes))
}
3.3. 效果
<person>
<name>Name-0224</name>
<age>71</age>
<isAdult>true</isAdult>
<email where="Where-0841">
<addr>Addr-0036</addr>
</email>
<email where="Where-0195">
<addr>Addr-0598</addr>
</email>
<email where="Where-0425">
<addr>Addr-0220</addr>
</email>
<email where="Where-0128">
<addr>Addr-0241</addr>
</email>
</person>