func sizeof()

in pkg/util/reflect.go [133:194]


func sizeof(v reflect.Value, selfRecurseMap map[uintptr]struct{}) (s uint64) {
	if !v.IsValid() {
		return
	}

	if v.CanAddr() {
		selfRecurseMap[v.Addr().Pointer()] = struct{}{}
	}

	t := v.Type()
	s += uint64(t.Size())
	switch v.Kind() {
	case reflect.Ptr:
		if v.IsNil() {
			break
		}
		if _, ok := selfRecurseMap[v.Pointer()]; ok {
			break
		}
		fallthrough
	case reflect.Interface:
		s += sizeof(v.Elem(), selfRecurseMap)
	case reflect.Struct:
		s -= uint64(t.Size())
		for i := 0; i < v.NumField(); i++ {
			s += sizeof(v.Field(i), selfRecurseMap)
		}
	case reflect.Array:
		if isValueType(t.Elem().Kind()) {
			break
		}
		s -= uint64(t.Size())
		for i := 0; i < v.Len(); i++ {
			s += sizeof(v.Index(i), selfRecurseMap)
		}
	case reflect.Slice:
		et := t.Elem()
		if isValueType(et.Kind()) {
			s += uint64(v.Len()) * uint64(et.Size())
			break
		}
		for i := 0; i < v.Len(); i++ {
			s += sizeof(v.Index(i), selfRecurseMap)
		}
	case reflect.Map:
		if v.IsNil() {
			break
		}
		kt, vt := t.Key(), t.Elem()
		if isValueType(kt.Kind()) && isValueType(vt.Kind()) {
			s += uint64(kt.Size()+vt.Size()) * uint64(v.Len())
			break
		}
		for _, k := range v.MapKeys() {
			s += sizeof(k, selfRecurseMap)
			s += sizeof(v.MapIndex(k), selfRecurseMap)
		}
	case reflect.String:
		s += uint64(v.Len())
	}
	return
}