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  }