go装饰器
普通装饰器(go中没有python的@语法糖)
package main import "fmt" func user_logging(fun func()) func() func() { wrapper := func() func(){ fmt.Println("this func is", fun) fmt.Println("the end of foo") return fun } return wrapper } func foo() { println("i am foo") } func main() { foo := user_logging(foo) fmt.Println(foo()) } //this func is 0x490840 //the end of foo //0x490840
package main
import "fmt"
func user_logging(fun func()) func() { // 装饰器函数
wrapper := func() {
fmt.Println("this func is", fun)
fun()
fmt.Println("the end of foo")
}
return wrapper
}
func foo() {
println("i am foo")
}
func main() {
foo := user_logging(foo)
foo()
}
//this func is 0x490840
//i am foo
//the end of foo
功能函数加参数
package main import ( "fmt" "time" ) func show_time(fun func(...int)) func(...int) { // 装饰器函数 wrapper := func(args ...int) { start := time.Now().Unix() fun(args...) end := time.Now().Unix() fmt.Println(start, end) fmt.Printf("spend %d", end - start) } return wrapper } func add(args ...int) { // 功能函数 sums := 0 for _, v := range args { sums += v } fmt.Println(sums) time.Sleep(3 * time.Second) } func main() { add := show_time(add) add(1, 2, 3, 4, 5) }
装饰器函数加参数
package main import ( "fmt" "time" ) func logger(flag bool) func(fun func(...int)) func(...int) { show_time := func(fun func(...int)) func(...int) { // 装饰器函数 wrapper := func(args ...int) { start := time.Now().Unix() fun(args...) end := time.Now().Unix() fmt.Println(start, end) fmt.Printf("spend %d\n", end - start) if flag == true { fmt.Println("日志记录") } } return wrapper } return show_time } func add(args ...int) { // 功能函数 sums := 0 for _, v := range args { sums += v } fmt.Println(sums) time.Sleep(3 * time.Second) } func test() { show_time := logger(false) add := show_time(add) add(1, 2, 3, 4, 5) } func main() { show_time := logger(true) add := show_time(add) add(1, 2, 3, 4, 5) test() } //15 //1554351453 1554351456 //spend 3 //日志记录 //15 //1554351456 1554351459 //spend 3
通过反射实现的通用型装饰器
package main
import (
"fmt"
"reflect"
)
func Decorator(decoPtr, fn interface{}) (err error) {
var decoratedFunc, targetFunc reflect.Value
decoratedFunc = reflect.ValueOf(decoPtr).Elem()
targetFunc = reflect.ValueOf(fn)
v := reflect.MakeFunc(targetFunc.Type(),
func(in []reflect.Value) (out []reflect.Value) {
fmt.Println("before")
args := []reflect.Value{}
if len(in) == 1 && in[0].Kind() == reflect.Slice {
for i := 0; i < in[0].Len(); i++ {
args = append(args, in[0].Index(i))
}
in = args
}
out = targetFunc.Call(in)
fmt.Println("after")
return
})
decoratedFunc.Set(v)
return
}
func foo(a, b, c int) int {
fmt.Println(a)
return b
}
func main() {
myfoo := foo
Decorator(&myfoo, foo)
myfoo(1, 2, 3)
}
//before
//1
//after
对于以上实现的一个小坑,关于功能函数为定长和可变参数的区别
package main import ( "fmt" "reflect" ) func Decorator(decoPtr, fn interface{}) (err error) { var decoratedFunc, targetFunc reflect.Value decoratedFunc = reflect.ValueOf(decoPtr).Elem() targetFunc = reflect.ValueOf(fn) v := reflect.MakeFunc(targetFunc.Type(), func(in []reflect.Value) (out []reflect.Value) { fmt.Println("before") //args := []reflect.Value{} //if len(in) == 1 && in[0].Kind() == reflect.Slice { // for i := 0; i < in[0].Len(); i++ { // args = append(args, in[0].Index(i)) // } // in = args //} // 定长参数 可变参数 fmt.Printf("%T\n", in) //[]reflect.Value []reflect.Value fmt.Println(in) //[<int Value> <int Value> <int Value>] [<[]int Value>] fmt.Printf("%T\n", in[0]) //reflect.Value reflect.Value fmt.Println(in[0]) // 1 [1 2 3]
// 可变参数的情况下,in是[<[]int Value>]而不是[<int Value> <int Value> <int Value>],[<[]int Value>]是不能直接传入到Call函数中的 // 所以需要将可变参数情况下,in [<[]int Value>]转换成in []reflect.Value // 方法就是把<[]int Value>取出来即in[0],它的类型为reflect.Value,值为[1 2 3],所以使用in[0].Index(i)将其中的值一个个取出来,最后保存到[]reflect.Value中即可 out = targetFunc.Call(in) fmt.Println("after") return }) decoratedFunc.Set(v) return } func foo(args ...int) int { fmt.Println(args) return args[0] } func bar(a,b,c int) int { fmt.Println(a) return c } func main() { //myfoo := foo //Decorator(&myfoo, foo) //myfoo(1, 2, 3)
mybar := bar
Decorator(&mybar, bar)
mybar(1,2,3)
}