zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", in) //[]reflect.Value             []reflect.Value
                fmt.Println(in) //[<int Value> <int Value> <int Value>]     [<[]int Value>]
                fmt.Printf("%T
    ", 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)
    }
  • 相关阅读:
    Android
    mysql监视器MONyog的使用
    网络架构、云平台和微信公众平台开发接入
    Protocol buffer序列化及其在微信蓝牙协议中的应用
    基于微信硬件公众平台的智能控制开发流程
    物联网架构演进和微信智能设备平台开发
    Android设置虚线、圆角、渐变
    android shape的使用详解以及常用效果(渐变色、分割线、边框、半透明阴影效果等)
    android bitmap的 一些简单操作
    Android Bitmap开发之旅--基本操作
  • 原文地址:https://www.cnblogs.com/xyz2b/p/10654135.html
Copyright © 2011-2022 走看看