conversion负责转换两个obj,挨个遍历其中一个obj的属性,找到key或者tag一样的另一边的属性并进行赋值。若有用户注册的转换函数,则调用用户注册的转换函数。

1、ConversionFuncs

  1. type ConversionFuncs struct {
  2. untyped map[typePair]ConversionFunc
  3. }
  4. // 注册一个转换函数
  5. // typePair里面的src和dest为指针
  6. func (c ConversionFuncs) AddUntyped(a, b interface{}, fn ConversionFunc) error {
  7. tA, tB := reflect.TypeOf(a), reflect.TypeOf(b)
  8. if tA.Kind() != reflect.Ptr {
  9. return fmt.Errorf("the type %T must be a pointer to register as an untyped conversion", a)
  10. }
  11. if tB.Kind() != reflect.Ptr {
  12. return fmt.Errorf("the type %T must be a pointer to register as an untyped conversion", b)
  13. }
  14. c.untyped[typePair{tA, tB}] = fn
  15. return nil
  16. }
  17. // 合并
  18. func (c ConversionFuncs) Merge(other ConversionFuncs) ConversionFuncs {
  19. merged := NewConversionFuncs()
  20. for k, v := range c.untyped {
  21. merged.untyped[k] = v
  22. }
  23. for k, v := range other.untyped {
  24. merged.untyped[k] = v
  25. }
  26. return merged
  27. }

2、Scope

  1. type Scope interface {
  2. Convert(src, dest interface{}, flags FieldMatchingFlags) error
  3. // SrcTag和DestTag返回的是当前正在比较的两个属性
  4. // 供转换函数进行更进一步的转换
  5. SrcTag() reflect.StructTag
  6. DestTag() reflect.StructTag
  7. Flags() FieldMatchingFlags
  8. Meta() *Meta
  9. }
  10. // 用来给转换函数传递额外的信息,被封装在scope里面
  11. type Meta struct {
  12. KeyNameMapping FieldMappingFunc
  13. Context interface{}
  14. }
  15. type scope struct {
  16. converter *Converter
  17. meta *Meta
  18. flags FieldMatchingFlags
  19. srcStack scopeStack
  20. destStack scopeStack
  21. }
  22. func (s *scope) Convert(src, dest interface{}, flags FieldMatchingFlags) error {
  23. return s.converter.Convert(src, dest, flags, s.meta)
  24. }
  25. // 返回最新找到的属性的tag
  26. func (s *scope) SrcTag() reflect.StructTag {
  27. return s.srcStack.top().tag
  28. }
  29. // 返回最新找到的属性的tag
  30. func (s *scope) DestTag() reflect.StructTag {
  31. return s.destStack.top().tag
  32. }
  33. func (s *scope) Flags() FieldMatchingFlags {
  34. return s.flags
  35. }
  36. // Meta returns the meta object that was originally passed to Convert.
  37. func (s *scope) Meta() *Meta {
  38. return s.meta
  39. }
  40. func (s *scope) setIndices(src, dest int) {
  41. s.srcStack.top().key = fmt.Sprintf("[%v]", src)
  42. s.destStack.top().key = fmt.Sprintf("[%v]", dest)
  43. }
  44. func (s *scope) setKeys(src, dest interface{}) {
  45. s.srcStack.top().key = fmt.Sprintf(`["%v"]`, src)
  46. s.destStack.top().key = fmt.Sprintf(`["%v"]`, dest)
  47. }
  48. func (s *scope) describe() (src, dest string) {
  49. return s.srcStack.describe(), s.destStack.describe()
  50. }
  51. func (s *scope) errorf(message string, args ...interface{}) error {
  52. srcPath, destPath := s.describe()
  53. where := fmt.Sprintf("converting %v to %v: ", srcPath, destPath)
  54. return fmt.Errorf(where+message, args...)
  55. }
  56. type scopeStackElem struct {
  57. tag reflect.StructTag
  58. value reflect.Value
  59. key string
  60. }
  61. type scopeStack []scopeStackElem
  62. func (s *scopeStack) pop() {
  63. n := len(*s)
  64. *s = (*s)[:n-1]
  65. }
  66. func (s *scopeStack) push(e scopeStackElem) {
  67. *s = append(*s, e)
  68. }
  69. func (s *scopeStack) top() *scopeStackElem {
  70. return &(*s)[len(*s)-1]
  71. }
  72. func (s scopeStack) describe() string {
  73. desc := ""
  74. if len(s) > 1 {
  75. desc = "(" + s[1].value.Type().String() + ")"
  76. }
  77. for i, v := range s {
  78. if i < 2 {
  79. // First layer on stack is not real; second is handled specially above.
  80. continue
  81. }
  82. if v.key == "" {
  83. desc += fmt.Sprintf(".%v", v.value.Type())
  84. } else {
  85. desc += fmt.Sprintf(".%v", v.key)
  86. }
  87. }
  88. return desc
  89. }

3、Converter

  1. type Converter struct {
  2. // 注册的转换函数
  3. // generatedConversionFuncs一般为脚手架生成的转换函数
  4. // 用户自定义注入到conversionFuncs
  5. // 且conversionFuncs的优先级比generatedConversionFuncs高
  6. conversionFuncs ConversionFuncs
  7. generatedConversionFuncs ConversionFuncs
  8. // 忽略掉一些类型的转换
  9. ignoredConversions map[typePair]struct{}
  10. ignoredUntypedConversions map[typePair]struct{}
  11. // 实际代码里面两个变量没有作用
  12. // src -> dest
  13. structFieldDests map[typeNamePair][]typeNamePair
  14. // dest -> src
  15. structFieldSources map[typeNamePair][]typeNamePair
  16. // field mapping函数
  17. // 默认注册了map[string][]string{}/url.Values{}
  18. // 对应的field mapping函数为JSONKeyMapper
  19. // 根据结构体tag匹配map的key
  20. inputFieldMappingFuncs map[reflect.Type]FieldMappingFunc
  21. // obj默认匹配flag,包含以下四种
  22. // DestFromSource、SourceToDest、IgnoreMissingFields、AllowDifferentFieldTypeNames
  23. inputDefaultFlags map[reflect.Type]FieldMatchingFlags
  24. // 日志
  25. Debug DebugLogger
  26. // 类型名称函数
  27. nameFunc func(t reflect.Type) string
  28. }
  29. // 初始化函数并注册切片转换函数
  30. func NewConverter(nameFn NameFunc) *Converter {
  31. c := &Converter{
  32. conversionFuncs: NewConversionFuncs(),
  33. generatedConversionFuncs: NewConversionFuncs(),
  34. ignoredConversions: make(map[typePair]struct{}),
  35. ignoredUntypedConversions: make(map[typePair]struct{}),
  36. nameFunc: nameFn,
  37. structFieldDests: make(map[typeNamePair][]typeNamePair),
  38. structFieldSources: make(map[typeNamePair][]typeNamePair),
  39. inputFieldMappingFuncs: make(map[reflect.Type]FieldMappingFunc),
  40. inputDefaultFlags: make(map[reflect.Type]FieldMatchingFlags),
  41. }
  42. c.RegisterUntypedConversionFunc(
  43. (*[]byte)(nil), (*[]byte)(nil),
  44. func(a, b interface{}, s Scope) error {
  45. return Convert_Slice_byte_To_Slice_byte(a.(*[]byte), b.(*[]byte), s)
  46. },
  47. )
  48. return c
  49. }
  50. // src/dest必须为指针
  51. // meta是用来给转换函数传递信息的,被用来封装在scope中
  52. // Scheme调用Scheme.Convert之前会调用DefaultMeta获取flags和meta并传入Converter.Convert
  53. func (c *Converter) Convert(src, dest interface{}, flags FieldMatchingFlags, meta *Meta) error {
  54. return c.doConversion(src, dest, flags, meta, c.convert)
  55. }
  56. // 开启转换
  57. // 首先检查是否注册了转换函数
  58. // 否则用默认的转换函数进行转换
  59. func (c *Converter) doConversion(src, dest interface{}, flags FieldMatchingFlags, meta *Meta, f conversionFunc) error {
  60. pair := typePair{reflect.TypeOf(src), reflect.TypeOf(dest)}
  61. scope := &scope{
  62. converter: c,
  63. flags: flags,
  64. meta: meta,
  65. }
  66. // 是否被忽略
  67. if _, ok := c.ignoredUntypedConversions[pair]; ok {
  68. return nil
  69. }
  70. // 优先检查用户自定义转换函数
  71. if fn, ok := c.conversionFuncs.untyped[pair]; ok {
  72. return fn(src, dest, scope)
  73. }
  74. // 检查是否有用脚手架生成的转换函数
  75. if fn, ok := c.generatedConversionFuncs.untyped[pair]; ok {
  76. return fn(src, dest, scope)
  77. }
  78. // 确保obj为ptr且不为nil并返回obj的Value对象
  79. dv, err := EnforcePtr(dest)
  80. if err != nil {
  81. return err
  82. }
  83. // 对于dest对象,必须可以取址和设置(要给dest赋值,必须满足这两个条件,src则不需要)
  84. if !dv.CanAddr() && !dv.CanSet() {
  85. return fmt.Errorf("can't write to dest")
  86. }
  87. sv, err := EnforcePtr(src)
  88. if err != nil {
  89. return err
  90. }
  91. // 保留空的scopeStackElem,包装struct tag getters不会失败
  92. // Leave something on the stack, so that calls to struct tag getters never fail.
  93. scope.srcStack.push(scopeStackElem{})
  94. scope.destStack.push(scopeStackElem{})
  95. return f(sv, dv, scope)
  96. }
  97. // 未匹配到注册函数,则进入默认转换函数
  98. // 此处的value已经是struct本身了,不需要处理Ptr
  99. func (c *Converter) convert(sv, dv reflect.Value, scope *scope) error {
  100. dt, st := dv.Type(), sv.Type()
  101. pair := typePair{st, dt}
  102. // 是否被忽略
  103. if _, ok := c.ignoredConversions[pair]; ok {
  104. return nil
  105. }
  106. // 开始转换
  107. // 由于convert可能被递归调用,因此需要先判断是否有符合条件的转换函数
  108. // 这里需要转换为指针的type
  109. pair = typePair{reflect.PtrTo(sv.Type()), reflect.PtrTo(dv.Type())}
  110. if f, ok := c.conversionFuncs.untyped[pair]; ok {
  111. return c.callUntyped(sv, dv, f, scope)
  112. }
  113. if f, ok := c.generatedConversionFuncs.untyped[pair]; ok {
  114. return c.callUntyped(sv, dv, f, scope)
  115. }
  116. // 检查dv是否可以被设置
  117. if !dv.CanSet() {
  118. return scope.errorf("Cannot set dest. (Tried to deep copy something with unexported fields?)")
  119. }
  120. // 若未设置AllowDifferentFieldTypeNames,但是field名称不一样,则直接抛异常
  121. if !scope.flags.IsSet(AllowDifferentFieldTypeNames) && c.nameFunc(dt) != c.nameFunc(st) {
  122. return scope.errorf(
  123. "type names don't match (%v, %v), and no conversion 'func (%v, %v) error' registered.",
  124. c.nameFunc(st), c.nameFunc(dt), st, dt)
  125. }
  126. // 检查src对象是否为简单类型
  127. switch st.Kind() {
  128. case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct:
  129. default:
  130. // 若为简单类型直接,则
  131. // 若二者类型一样,直接赋值返回
  132. // 否则检查是否可以st -> dt,可以直接赋值返回
  133. if st.AssignableTo(dt) {
  134. dv.Set(sv)
  135. return nil
  136. }
  137. if st.ConvertibleTo(dt) {
  138. dv.Set(sv.Convert(dt))
  139. return nil
  140. }
  141. }
  142. scope.srcStack.push(scopeStackElem{value: sv})
  143. scope.destStack.push(scopeStackElem{value: dv})
  144. defer scope.srcStack.pop()
  145. defer scope.destStack.pop()
  146. // 检查目标对象的类型
  147. switch dv.Kind() {
  148. // 若为结构体类型,直接调用convertKV进行比较
  149. // 此处支持struct -> struct, map -> struct
  150. case reflect.Struct:
  151. return c.convertKV(toKVValue(sv), toKVValue(dv), scope)
  152. case reflect.Slice:
  153. // 若为切片,则
  154. // 若sv为空,则赋值返回
  155. // 此处支持map/chan/slice/string/array -> slice
  156. if sv.IsNil() {
  157. dv.Set(reflect.Zero(dt))
  158. return nil
  159. }
  160. // 否则对dv进行挨个赋值
  161. dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap()))
  162. for i := 0; i < sv.Len(); i++ {
  163. scope.setIndices(i, i)
  164. if err := c.convert(sv.Index(i), dv.Index(i), scope); err != nil {
  165. return err
  166. }
  167. }
  168. case reflect.Ptr:
  169. if sv.IsNil() {
  170. dv.Set(reflect.Zero(dt))
  171. return nil
  172. }
  173. dv.Set(reflect.New(dt.Elem()))
  174. switch st.Kind() {
  175. case reflect.Ptr, reflect.Interface:
  176. return c.convert(sv.Elem(), dv.Elem(), scope)
  177. default:
  178. return c.convert(sv, dv.Elem(), scope)
  179. }
  180. case reflect.Map:
  181. if sv.IsNil() {
  182. dv.Set(reflect.Zero(dt))
  183. return nil
  184. }
  185. // 此处支持map -> map
  186. dv.Set(reflect.MakeMap(dt))
  187. for _, sk := range sv.MapKeys() {
  188. dk := reflect.New(dt.Key()).Elem()
  189. if err := c.convert(sk, dk, scope); err != nil {
  190. return err
  191. }
  192. dkv := reflect.New(dt.Elem()).Elem()
  193. scope.setKeys(sk.Interface(), dk.Interface())
  194. if err := c.convert(sv.MapIndex(sk), dkv, scope); err != nil {
  195. return err
  196. }
  197. dv.SetMapIndex(dk, dkv)
  198. }
  199. case reflect.Interface:
  200. if sv.IsNil() {
  201. dv.Set(reflect.Zero(dt))
  202. return nil
  203. }
  204. tmpdv := reflect.New(sv.Elem().Type()).Elem()
  205. if err := c.convert(sv.Elem(), tmpdv, scope); err != nil {
  206. return err
  207. }
  208. dv.Set(reflect.ValueOf(tmpdv.Interface()))
  209. return nil
  210. default:
  211. return scope.errorf("couldn't copy '%v' into '%v'; didn't understand types", st, dt)
  212. }
  213. return nil
  214. }
  215. func (c *Converter) convertKV(skv, dkv kvValue, scope *scope) error {
  216. if skv == nil || dkv == nil {
  217. return fmt.Errorf("unable to convert %#v to %#v", skv, dkv)
  218. }
  219. // 默认遍历dest,若设置了SourceToDest则遍历src
  220. lister := dkv
  221. if scope.flags.IsSet(SourceToDest) {
  222. lister = skv
  223. }
  224. // 检查是否设置了mapping函数
  225. var mapping FieldMappingFunc
  226. if scope.meta != nil && scope.meta.KeyNameMapping != nil {
  227. mapping = scope.meta.KeyNameMapping
  228. }
  229. // eg.
  230. // type TestA struct {
  231. // A string `test:"a"`
  232. // B string `test:"b"`
  233. // }
  234. // type TestB struct {
  235. // A string `test:"b"`
  236. // B string `test:"a"`
  237. // }
  238. // 假设此处遍历TestA
  239. // key为A
  240. for _, key := range lister.keys() {
  241. // found均为false,忽略即可
  242. if found, err := c.checkField(key, skv, dkv, scope); found {
  243. if err != nil {
  244. return err
  245. }
  246. continue
  247. }
  248. // 获取key对应的tag
  249. // stag/dtag分别为a,b
  250. stag := skv.tagOf(key)
  251. dtag := dkv.tagOf(key)
  252. // skey为A
  253. // dkey为B
  254. skey := key
  255. dkey := key
  256. if mapping != nil {
  257. // 若配置了mapping函数,一般是针对map -> struct,map -> map,struct -> struct的映射
  258. // x := map[string][]string{
  259. // "Foo": {"bar"},
  260. // "test": {"baz"},
  261. // }
  262. // type A struct {
  263. // Foo string `json:"test"`
  264. // }
  265. // func JSONKeyMapper(key string, sourceTag, destTag reflect.StructTag) (string, string) {
  266. // if s := destTag.Get("json"); len(s) > 0 {
  267. // return strings.SplitN(s, ",", 2)[0], key
  268. // }
  269. // if s := sourceTag.Get("json"); len(s) > 0 {
  270. // return key, strings.SplitN(s, ",", 2)[0]
  271. // }
  272. // return key, key
  273. // }
  274. // 1、遍历dest。则key为Foo。stag/dtag分别为""/test。因此mapping之后
  275. // skey/dkey分别为test/Foo,后续用x的test的值去赋值A的Foo
  276. // 2、遍历src。
  277. // 第一次遍历:key为Foo。stag/dtag分别为""/test。因此mapping之后
  278. // skey/dkey分别为test/Foo,后续用x的test的值去赋值A的Foo
  279. // 第二次遍历:key为test。stag/dtag分别为""/""。因此mapping之后
  280. // skey/dkey分别为test/test,后续用x的test的值去赋值A的Foo
  281. skey, dkey = scope.meta.KeyNameMapping(key, stag, dtag)
  282. }
  283. // df/sf分别为typeOf(A)/typeOf(A)
  284. df := dkv.value(dkey)
  285. sf := skv.value(skey)
  286. if !df.IsValid() || !sf.IsValid() {
  287. switch {
  288. case scope.flags.IsSet(IgnoreMissingFields):
  289. case scope.flags.IsSet(SourceToDest):
  290. return scope.errorf("%v not present in dest", dkey)
  291. default:
  292. return scope.errorf("%v not present in src", skey)
  293. }
  294. continue
  295. }
  296. scope.srcStack.top().key = skey
  297. scope.srcStack.top().tag = stag
  298. scope.destStack.top().key = dkey
  299. scope.destStack.top().tag = dtag
  300. // 转换后为TestB A的值等于TestB A的值
  301. if err := c.convert(sf, df, scope); err != nil {
  302. return err
  303. }
  304. }
  305. return nil
  306. }
  307. // 基本没有用
  308. // 因为structFieldSources都是空的
  309. func (c *Converter) checkField(fieldName string, skv, dkv kvValue, scope *scope) (bool, error) {
  310. replacementMade := false
  311. if scope.flags.IsSet(DestFromSource) {
  312. df := dkv.value(fieldName)
  313. if !df.IsValid() {
  314. return false, nil
  315. }
  316. destKey := typeNamePair{df.Type(), fieldName}
  317. // Check each of the potential source (type, name) pairs to see if they're
  318. // present in sv.
  319. for _, potentialSourceKey := range c.structFieldSources[destKey] {
  320. sf := skv.value(potentialSourceKey.fieldName)
  321. if !sf.IsValid() {
  322. continue
  323. }
  324. if sf.Type() == potentialSourceKey.fieldType {
  325. // Both the source's name and type matched, so copy.
  326. scope.srcStack.top().key = potentialSourceKey.fieldName
  327. scope.destStack.top().key = fieldName
  328. if err := c.convert(sf, df, scope); err != nil {
  329. return true, err
  330. }
  331. dkv.confirmSet(fieldName, df)
  332. replacementMade = true
  333. }
  334. }
  335. return replacementMade, nil
  336. }
  337. sf := skv.value(fieldName)
  338. if !sf.IsValid() {
  339. return false, nil
  340. }
  341. srcKey := typeNamePair{sf.Type(), fieldName}
  342. // Check each of the potential dest (type, name) pairs to see if they're
  343. // present in dv.
  344. for _, potentialDestKey := range c.structFieldDests[srcKey] {
  345. df := dkv.value(potentialDestKey.fieldName)
  346. if !df.IsValid() {
  347. continue
  348. }
  349. if df.Type() == potentialDestKey.fieldType {
  350. // Both the dest's name and type matched, so copy.
  351. scope.srcStack.top().key = fieldName
  352. scope.destStack.top().key = potentialDestKey.fieldName
  353. if err := c.convert(sf, df, scope); err != nil {
  354. return true, err
  355. }
  356. dkv.confirmSet(potentialDestKey.fieldName, df)
  357. replacementMade = true
  358. }
  359. }
  360. return replacementMade, nil
  361. }
  362. func (c *Converter) callUntyped(sv, dv reflect.Value, f ConversionFunc, scope *scope) error {
  363. if !dv.CanAddr() {
  364. return scope.errorf("cant addr dest")
  365. }
  366. var svPointer reflect.Value
  367. if sv.CanAddr() {
  368. svPointer = sv.Addr()
  369. } else {
  370. svPointer = reflect.New(sv.Type())
  371. svPointer.Elem().Set(sv)
  372. }
  373. dvPointer := dv.Addr()
  374. return f(svPointer.Interface(), dvPointer.Interface(), scope)
  375. }

4、工具

4.1、adaptor

  1. type kvValue interface {
  2. keys() []string
  3. tagOf(key string) reflect.StructTag
  4. value(key string) reflect.Value
  5. confirmSet(key string, v reflect.Value) bool
  6. }
  7. type stringMapAdaptor reflect.Value
  8. func (a stringMapAdaptor) len() int {
  9. return reflect.Value(a).Len()
  10. }
  11. func (a stringMapAdaptor) keys() []string {
  12. v := reflect.Value(a)
  13. keys := make([]string, v.Len())
  14. for i, v := range v.MapKeys() {
  15. if v.IsNil() {
  16. continue
  17. }
  18. switch t := v.Interface().(type) {
  19. case string:
  20. keys[i] = t
  21. }
  22. }
  23. return keys
  24. }
  25. func (a stringMapAdaptor) tagOf(key string) reflect.StructTag {
  26. return ""
  27. }
  28. func (a stringMapAdaptor) value(key string) reflect.Value {
  29. return reflect.Value(a).MapIndex(reflect.ValueOf(key))
  30. }
  31. func (a stringMapAdaptor) confirmSet(key string, v reflect.Value) bool {
  32. return true
  33. }
  34. type structAdaptor reflect.Value
  35. func (a structAdaptor) len() int {
  36. v := reflect.Value(a)
  37. return v.Type().NumField()
  38. }
  39. func (a structAdaptor) keys() []string {
  40. v := reflect.Value(a)
  41. t := v.Type()
  42. keys := make([]string, t.NumField())
  43. for i := range keys {
  44. keys[i] = t.Field(i).Name
  45. }
  46. return keys
  47. }
  48. func (a structAdaptor) tagOf(key string) reflect.StructTag {
  49. v := reflect.Value(a)
  50. field, ok := v.Type().FieldByName(key)
  51. if ok {
  52. return field.Tag
  53. }
  54. return ""
  55. }
  56. func (a structAdaptor) value(key string) reflect.Value {
  57. v := reflect.Value(a)
  58. return v.FieldByName(key)
  59. }
  60. func (a structAdaptor) confirmSet(key string, v reflect.Value) bool {
  61. return true
  62. }

4.2、通用函数

  1. // 切片转换函数
  2. // out可以不用初始化,声明即可
  3. func Convert_Slice_byte_To_Slice_byte(in *[]byte, out *[]byte, s Scope) error {
  4. if *in == nil {
  5. *out = nil
  6. return nil
  7. }
  8. *out = make([]byte, len(*in))
  9. copy(*out, *in)
  10. return nil
  11. }
  12. // 确保obj为ptr且不为nil并返回obj的Value对象
  13. func EnforcePtr(obj interface{}) (reflect.Value, error) {
  14. v := reflect.ValueOf(obj)
  15. if v.Kind() != reflect.Ptr {
  16. if v.Kind() == reflect.Invalid {
  17. return reflect.Value{}, fmt.Errorf("expected pointer, but got invalid kind")
  18. }
  19. return reflect.Value{}, fmt.Errorf("expected pointer, but got %v type", v.Type())
  20. }
  21. if v.IsNil() {
  22. return reflect.Value{}, fmt.Errorf("expected pointer, but got nil")
  23. }
  24. return v.Elem(), nil
  25. }