...
1
2
3
4
5
6
7 package typeutil
8
9 import (
10 "go/types"
11 "sync"
12 )
13
14
15
16
17 type MethodSetCache struct {
18 mu sync.Mutex
19 named map[*types.Named]struct{ value, pointer *types.MethodSet }
20 others map[types.Type]*types.MethodSet
21 }
22
23
24
25
26
27
28 func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
29 if cache == nil {
30 return types.NewMethodSet(T)
31 }
32 cache.mu.Lock()
33 defer cache.mu.Unlock()
34
35 switch T := T.(type) {
36 case *types.Named:
37 return cache.lookupNamed(T).value
38
39 case *types.Pointer:
40 if N, ok := T.Elem().(*types.Named); ok {
41 return cache.lookupNamed(N).pointer
42 }
43 }
44
45
46
47 mset := cache.others[T]
48 if mset == nil {
49 mset = types.NewMethodSet(T)
50 if cache.others == nil {
51 cache.others = make(map[types.Type]*types.MethodSet)
52 }
53 cache.others[T] = mset
54 }
55 return mset
56 }
57
58 func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {
59 if cache.named == nil {
60 cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })
61 }
62
63
64 msets, ok := cache.named[named]
65 if !ok {
66 msets.value = types.NewMethodSet(named)
67 msets.pointer = types.NewMethodSet(types.NewPointer(named))
68 cache.named[named] = msets
69 }
70 return msets
71 }
72
View as plain text