委托机制
package main import ( "errors" "fmt" "sort" "strings" ) type InSet struct { data map[int]bool undo Undo } type UndoableInSet struct { InSet functions []func() } func NewUndoableInSet() UndoableInSet { return UndoableInSet{NewInSet(), nil} } func (set *UndoableInSet) Delete(x int) { if set.Contains(x) { delete(set.data, x) set.functions = append(set.functions, func() { set.Add(x) }) } } func (set *UndoableInSet) Add(x int) { if !set.Contains(x) { set.data[x] = true set.functions = append(set.functions, func() { set.Delete(x) }) } } func (set *UndoableInSet) Undo() error { if len(set.functions) == 0 { return errors.New("No functions to undo") } index := len(set.functions) - 1 if function := set.functions[index]; function != nil { function() set.functions[index] = nil } set.functions = set.functions[:index] return nil } func NewInSet() InSet { return InSet{data:make(map[int]bool)} } func (set *InSet) Add(x int) { if set.Contains(x) { set.data[x] = true set.undo.Add(func() { set.Delete(x) }) } else { set.undo.Add(nil) } } func (set *InSet) Delete(x int) { if set.Contains(x) { delete(set.data, x) set.undo.Add(func() { set.Add(x) }) } else { set.undo.Add(nil) } } func (set *InSet) Contains(x int) bool { return set.data[x] } func (set *InSet) Undo() error { return set.undo.Undo() } func (set *InSet) String() string { if len(set.data) == 0 { return "{}" } ints := make([]int, 0, len(set.data)) for i := range set.data { ints = append(ints, i) } sort.Ints(ints) parts := make([]string, 0, len(ints)) for _, i := range ints { parts = append(parts, fmt.Sprint(i)) } return "{" + strings.Join(parts, ",") + "}" } func main() { ints := NewUndoableInSet() for _, i := range []int{1, 2, 3, 4} { ints.Add(i) fmt.Println(ints) } fmt.Println() for { if err := ints.Undo(); err != nil { break } fmt.Println(ints) } } type Undo []func() func (undo *Undo) Add(function func()) { *undo = append(*undo, function) } func (undo *Undo) Undo() error { functions := *undo if len(functions) == 0 { return errors.New("No functions to undo") } index := len(functions) - 1 if function := functions[index]; function != nil { function() functions[index] = nil } *undo = functions[:index] return nil }
参考自陈皓的极客时间 https://time.geekbang.org/column/article/2748
end