首页 > 其他分享 >记一次golang并发map json encode 问题

记一次golang并发map json encode 问题

时间:2025-02-07 10:43:00浏览次数:4  
标签:map return nil err sv golang json reflect

package main

import (
	"encoding"
	"fmt"
	"reflect"
	"strconv"
)

type reflectWithString struct {
	k  reflect.Value
	v  reflect.Value
	ks string
}

func main() {
	m := map[string]interface{}{"1": 1}
	v := reflect.ValueOf(m)
	sv := make([]reflectWithString, v.Len())
	m["2"] = 2
	mi := v.MapRange()

	for i := 0; mi.Next(); i++ {
		sv[i].k = mi.Key()
		sv[i].v = mi.Value()
		if err := sv[i].resolve(); err != nil {
			fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error())
		}
	}

}

func (w *reflectWithString) resolve() error {
	if w.k.Kind() == reflect.String {
		w.ks = w.k.String()
		return nil
	}
	if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok {
		if w.k.Kind() == reflect.Pointer && w.k.IsNil() {
			return nil
		}
		buf, err := tm.MarshalText()
		w.ks = string(buf)
		return err
	}
	switch w.k.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		w.ks = strconv.FormatInt(w.k.Int(), 10)
		return nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		w.ks = strconv.FormatUint(w.k.Uint(), 10)
		return nil
	}
	panic("unexpected map key type")
}

在官方包中,通过反射获取先获取了map的len长度得到sv的长度。
如果在v.MapRange() 前,将map的长度扩大,
就会出现sv的下标越界问题触发painc;
如果内容改变,就会出现 序列化 后的数据不是之前的数据,
因此在操作map时,一点要确认 不能并发操作读写。

标签:map,return,nil,err,sv,golang,json,reflect
From: https://www.cnblogs.com/pengb/p/18702193

相关文章