go, 随机实例化xml (2)

  • Post author:
  • Post category:其他




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>



版权声明:本文为weixin_44129801原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。