| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- package serverproto
- import (
- "encoding/csv"
- "errors"
- "fmt"
- "os"
- "reflect"
- "strconv"
- "strings"
- )
- ////https://github.com/gocarina/gocsv
- //配置表集合
- func loadCsvCfg(fileName string, cfg interface{}) {
- file, err := os.OpenFile(fileName, os.O_RDONLY, os.ModePerm)
- if err != nil {
- panic(err)
- }
- defer file.Close()
- csvReader := csv.NewReader(file)
- if csvReader == nil {
- panic(errors.New(fmt.Sprintf("%v:csv reader nil file", fileName)))
- }
- err = csvUnmarshal(csvReader, cfg)
- if err != nil {
- panic(errors.New(fmt.Sprintf("%v:%v", fileName, err)))
- }
- csvReader = nil
- }
- func csvUnmarshal(r *csv.Reader, cfg interface{}) error {
- cfgValue := reflect.ValueOf(cfg)
- if cfgValue.Kind() == reflect.Ptr {
- cfgValue = cfgValue.Elem()
- }
- cfgValueType := cfgValue.Type()
- //配置文件类型判断
- if cfgValueType.Kind() != reflect.Slice &&
- cfgValueType.Kind() != reflect.Chan &&
- cfgValueType.Kind() != reflect.Array {
- //return fmt.Errorf("cfg type error:%v\n",cfg)
- }
- csvRows, err := r.ReadAll()
- if err != nil {
- return err
- }
- csvRowsNum := len(csvRows)
- if csvRowsNum == 0 {
- return errors.New("empty csv file!")
- }
- //判断容量
- cfgPtr := &cfgValue
- switch cfgPtr.Kind() {
- case reflect.Array:
- if cfgPtr.Len() < csvRowsNum-1 {
- return fmt.Errorf("capacity problem")
- }
- case reflect.Slice:
- if !cfgPtr.CanAddr() && cfgPtr.Len() < csvRowsNum-3 {
- return fmt.Errorf("capacity problem")
- } else if cfgPtr.CanAddr() && cfgPtr.Len() < csvRowsNum-3 {
- cfgPtr.Set(reflect.MakeSlice(cfgPtr.Type(), csvRowsNum-3, csvRowsNum-3))
- }
- }
- stInfo := getStructInfo(cfgValueType.Elem())
- if len(stInfo.Fields) <= 0 {
- return errors.New("fields empty")
- }
- csvHeaders := csvRows[1]
- csvData := csvRows[3:]
- //数据下标对应
- csvHeadersLabels := make(map[int]*fieldInfo, len(stInfo.Fields)) //[pos, fieldInfo]
- headerMap := map[string]int{} // [name,fieldPos]
- for i, csvHeader := range csvHeaders {
- currentHeaderPos := headerMap[csvHeader]
- if info := getFieldPos(csvHeader, stInfo, currentHeaderPos); info != nil {
- info.index = i
- csvHeadersLabels[i] = info
- }
- }
- for i, row := range csvData {
- var cfgTemp reflect.Value
- if cfgValueType.Elem().Kind() == reflect.Ptr {
- cfgTemp = reflect.New(cfgValueType.Elem().Elem())
- } else {
- cfgTemp = reflect.New(cfgValueType.Elem())
- }
- for j, colData := range row {
- if info, ok := csvHeadersLabels[j]; ok {
- elm := cfgTemp.Elem()
- setFieldData(&elm, colData, info)
- }
- }
- cfgValue.Index(i).Set(cfgTemp)
- }
- headerMap = nil
- csvHeadersLabels = nil
- csvHeaders = nil
- csvRows = nil
- return nil
- }
- type structInfo struct {
- Fields []fieldInfo
- }
- type fieldInfo struct {
- keys string
- empty bool
- index int
- }
- func getStructInfo(stType reflect.Type) *structInfo {
- if stType.Kind() == reflect.Ptr {
- stType = stType.Elem()
- }
- fieldList := getFieldInfo(stType, []int{})
- return &structInfo{
- Fields: fieldList,
- }
- }
- func getFieldInfo(stType reflect.Type, index []int) []fieldInfo {
- fieldNum := stType.NumField()
- fieldList := make([]fieldInfo, 0, fieldNum)
- for i := 0; i < fieldNum; i++ {
- field := stType.Field(i)
- if field.PkgPath != "" {
- continue
- }
- info := fieldInfo{}
- info.keys = field.Tag.Get("csv")
- fieldList = append(fieldList, info)
- }
- return fieldList
- }
- func getFieldPos(header string, stInfo *structInfo, currenPos int) *fieldInfo {
- for _, f := range stInfo.Fields {
- if f.keys == header {
- return &f
- }
- }
- return nil
- }
- func setFieldData(value *reflect.Value, data string, field *fieldInfo) {
- v := (*value).FieldByIndex([]int{field.index})
- if v.Kind() == reflect.Ptr {
- if v.IsNil() {
- v.Set(reflect.New(v.Type().Elem()))
- }
- //获取指针指向的变量,后续才能做赋值操作
- v = v.Elem()
- }
- inValue := reflect.ValueOf(data)
- switch v.Interface().(type) {
- case string:
- v.SetString(data)
- case bool:
- if strings.EqualFold(strings.ToLower(data), "true") {
- v.SetBool(true)
- } else if strings.EqualFold(strings.ToLower(data), "false") {
- v.SetBool(false)
- }
- case int, int32, uint32:
- s := strings.TrimSpace(inValue.String())
- if s == "" {
- v.SetInt(0)
- }
- i, err := strconv.ParseInt(s, 0, 64)
- if err == nil {
- v.SetInt(i)
- }
- case float32:
- s := strings.TrimSpace(inValue.String())
- if s == "" {
- v.SetFloat(0)
- }
- i, err := strconv.ParseFloat(s, 64)
- if err == nil {
- v.SetFloat(i)
- }
- case []string:
- dataList := strings.Split(data, ";")
- v.Set(reflect.ValueOf(dataList))
- default:
- panic(errors.New("field type error"))
- }
- }
|