Undo,利用闭包捕获外部变量,将带有变量值的函数压
谨以此文,缅怀传奇技术大佬——陈皓先生
package main
import (
"errors"
"fmt"
)
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 // Free closure for garbage collection
}
*undo = functions[:index]
return nil
}
type IntSet struct {
data map[int]bool
undo Undo
}
func (this IntSet)String()string{
fmt.Print("{")
for k,v:= range this.data {
fmt.Print(k,":",v,"\t")
}
fmt.Print("}")
fmt.Println()
return ""
}
func NewIntSet() IntSet {
return IntSet{data: make(map[int]bool)}
}
/*
Add 操作时加入 Delete 操作的 Undo。
Delete 操作时加入 Add 操作的 Undo。
*/
func (set *IntSet) 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 *IntSet) 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 *IntSet) Undo() error {
return set.undo.Undo()
}
func (set *IntSet) Contains(x int) bool {
return set.data[x]
}
func main() {
ints := NewIntSet()
for _, i := range []int{1, 3, 5, 7} {
ints.Add(i)
fmt.Println(ints)
}
for _, i := range []int{1, 2, 3, 4, 5, 6, 7} {
fmt.Println("contains:",i,":", ints.Contains(i))
ints.Delete(i)
fmt.Println(ints)
}
fmt.Println()
for {
fmt.Println("---------------------------------")
if err := ints.Undo(); err != nil {
break
}
fmt.Println(ints)
}
}
Reference
https://coolshell.cn/articles/21214.html