github.com/kaydxh/golang@v0.0.131/tutorial/programming_paradigm/visitor_test.go (about) 1 package tutorial 2 3 import ( 4 "fmt" 5 "testing" 6 ) 7 8 //kubectl 使用了build模式和visitor模式 9 //https://github.com/kubernetes/kubernetes/blob/cea1d4e20b4a7886d8ff65f34c6d4f95efcb4742/staging/src/k8s.io/cli-runtime/pkg/resource/visitor.go 10 type VisitorFunc func(*Info, error) error 11 12 type Visitor interface { 13 Visit(VisitorFunc) error 14 } 15 16 type Info struct { 17 Namespace string 18 Name string 19 OtherThings string 20 } 21 22 func (info *Info) Visit(fn VisitorFunc) error { 23 return fn(info, nil) 24 } 25 26 type NameVisitor struct { 27 visitor Visitor 28 } 29 30 func (v NameVisitor) Visit(fn VisitorFunc) error { 31 return v.visitor.Visit(func(info *Info, err error) error { 32 fmt.Println("NameVisitor() before call function") 33 err = fn(info, err) 34 if err == nil { 35 fmt.Printf("==> Name=%s, NameSpace=%s\n", info.Name, info.Namespace) 36 } 37 fmt.Println("NameVisitor() after call function") 38 return err 39 }) 40 } 41 42 func WithNameVisitor() VisitorFunc { 43 return func(info *Info, err error) error { 44 fmt.Println("NameVisitor() before call function") 45 info.Name = "kay.name" 46 return nil 47 } 48 } 49 50 type OtherVisitor struct { 51 visitor Visitor 52 } 53 54 func (v OtherVisitor) Visit(fn VisitorFunc) error { 55 return v.visitor.Visit(func(info *Info, err error) error { 56 fmt.Println("OtherThingsVisitor() before call function") 57 err = fn(info, err) 58 if err == nil { 59 fmt.Printf("==> OtherThings=%s\n", info.OtherThings) 60 } 61 fmt.Println("OtherThingsVisitor() after call function") 62 return err 63 }) 64 } 65 66 func WithOtherVisitor() VisitorFunc { 67 return func(info *Info, err error) error { 68 fmt.Println("WithOtherVisitor() before call function") 69 info.Namespace = "nanjing" 70 return nil 71 } 72 } 73 74 type DecoratedVisitor struct { 75 visitor Visitor 76 decorators []VisitorFunc 77 } 78 79 func NewDecoratedVisitor(v Visitor, fn ...VisitorFunc) Visitor { 80 if len(fn) == 0 { 81 return v 82 } 83 return DecoratedVisitor{v, fn} 84 } 85 86 // Visit implements Visitor 87 func (v DecoratedVisitor) Visit(fn VisitorFunc) error { 88 return v.visitor.Visit(func(info *Info, err error) error { 89 if err != nil { 90 return err 91 } 92 for i := range v.decorators { 93 if err := v.decorators[i](info, nil); err != nil { 94 return err 95 } 96 } 97 if err := fn(info, nil); err != nil { 98 return err 99 } 100 return nil 101 }) 102 } 103 104 func TestDecoratedVisitor(t *testing.T) { 105 106 info := Info{} 107 var v Visitor = &info 108 109 v = NewDecoratedVisitor(v, WithNameVisitor(), WithOtherVisitor()) 110 loadFile := func(info *Info, err error) error { 111 fmt.Println("process loadFile") 112 info.OtherThings = "We are running as remote team." 113 fmt.Printf("info: %v", info) 114 return nil 115 } 116 v.Visit(loadFile) 117 }