github.com/kaydxh/golang@v0.0.131/tutorial/programming_paradigm/control.inverse_test.go (about) 1 package tutorial 2 3 import ( 4 "errors" 5 "testing" 6 ) 7 8 // Undo 是控制逻辑,与业务逻辑分开,业务逻辑依赖控制逻辑Undo,而不是控制 9 // 逻辑依赖业务逻辑 10 type Undo []func() 11 12 func (undo *Undo) Add(function func()) { 13 *undo = append(*undo, function) 14 } 15 16 func (undo *Undo) Undo() error { 17 functions := *undo 18 if len(functions) == 0 { 19 return errors.New("No functions to undo") 20 } 21 index := len(functions) - 1 22 if function := functions[index]; function != nil { 23 function() 24 functions[index] = nil // For garbage collection 25 } 26 *undo = functions[:index] 27 return nil 28 } 29 30 type IntSet struct { 31 data map[int]bool 32 undo Undo 33 } 34 35 func NewIntSet() IntSet { 36 return IntSet{data: make(map[int]bool)} 37 } 38 39 func (set *IntSet) Undo() error { 40 return set.undo.Undo() 41 } 42 43 func (set *IntSet) Contains(x int) bool { 44 return set.data[x] 45 } 46 47 func (set *IntSet) Add(x int) { 48 if !set.Contains(x) { 49 set.data[x] = true 50 set.undo.Add(func() { set.Delete(x) }) 51 } else { 52 set.undo.Add(nil) 53 } 54 } 55 56 func (set *IntSet) Delete(x int) { 57 if set.Contains(x) { 58 delete(set.data, x) 59 set.undo.Add(func() { set.Add(x) }) 60 } else { 61 set.undo.Add(nil) 62 } 63 } 64 65 func TestUndo(t *testing.T) { 66 s := NewIntSet() 67 s.Add(10) 68 s.Add(5) 69 t.Logf("s: %v", s) 70 s.Undo() 71 t.Logf("s: %v", s) 72 }