关于市面上go的aop方式

2,611 阅读3分钟

反思概述

Golang中没有原生的AOP(面向切面编程)支持,但可以使用一些技术来实现类似的效果。

以下是一些可能的方法:

1. 自定义 middleware

Middleware是一个常用的技术,可以实现切面的效果。可以通过复用中间件函数定义,将这些函数用作AOP钩子来告诉程序在何时进行拦截。例如,可以编写HTTP中间件来拦截请求并记录日志,或者编写数据库中间件来拦截查询并自动打印执行时间。这里有一个使用Http方式的例子:


func  YourHandler(w  http.ResponseWriter,  r  *http.Request)  {

    //  your  code

}

func  AuthMiddleware(next  http.Handler)  http.Handler  {

    return  http.HandlerFunc(func(w  http.ResponseWriter,  r  *http.Request)  {

        //  Perform  authentication  logic  here

        next.ServeHTTP(w,  r)

    })

}

func  LogMiddleware(next  http.Handler)  http.Handler  {

    return  http.HandlerFunc(func(w  http.ResponseWriter,  r  *http.Request)  {

        log.Println(r.Method,  r.URL.Path)

        next.ServeHTTP(w,  r)

    })

}

func  main()  {

    handler  :=  http.HandlerFunc(YourHandler)

    http.Handle("/",

        LogMiddleware(

            AuthMiddleware(

                handler,

            ),

        ),

    )

    http.ListenAndServe(":8080",  nil)

}

2. 利用函数指针传递方法

在 Go 中,将一个函数名作为参数传递给另一个函数时,实际上就是将函数指针传递给它。因此,您可以使用这个功能来实现 AOP。例如,我们可以定义一个函数,该函数接受一个函数指针作为参数,然后在调用实际函数之前或之后执行另一个函数(切面),以达到AOP的目的。下面是一个简单的例子:


func  before()  {

    //  logic  before  actual  function  call

}

func  after()  {

    //  logic  after  actual  function  call

}

func  actualFunc()  {

    //  real  function  logic

}

func  executeWithAOP(f  func())  {

    before()

    f()

    after()

}

func  main()  {

    executeWithAOP(actualFunc)

}

3. 利用反射和 Struct Tag 实现 AOP

Go 语言中使用 Struct Tag 实现 AOP 也是一种常见的方法。将 Struct Tag 添加到函数或结构体上,在运行时使用反射扫描该 Struct Tag,并根据标记中的信息执行切面操作。下面是一个简单的例子:


type  ActualStruct  struct  {

}

func  (a  ActualStruct)  DoSomething(name  string)  {

    fmt.Printf("Doing  %s\n",  name)

}

func  BeforeAdvice(name  string)  {

    fmt.Printf("Starting  %s\n",  name)

}

func  AfterAdvice(name  string)  {

    fmt.Printf("Completed  %s\n",  name)

}

func  ApplyBefore(funcName  string)  bool  {

    //  logic  to  check  if  before  advice  should  be  applied

    return  true

}

func  ApplyAfter(funcName  string)  bool  {

    //  logic  to  check  if  after  advice  should  be  applied

    return  true

}

func  main()  {

    actualStruct  :=  ActualStruct{}

    value  :=  reflect.ValueOf(actualStruct)

    method  :=  value.MethodByName("DoSomething")

    //  Check  if  before  advice  needs  to  be  applied

    if  ApplyBefore(method.Type().Name())  {

        BeforeAdvice("DoSomething")

    }

    //  Invoke  the  real  function

    args  :=  []reflect.Value{reflect.ValueOf("Something")}

    method.Call(args)

    //  Check  if  after  advice  needs  to  be  applied

    if  ApplyAfter(method.Type().Name())  {

        AfterAdvice("DoSomething")

    }

}

这是三种实现 AOP 的常见技术,但不局限于以上所示方法,Golang可以用不同的库来扩展AOP的方式。

4. 利用第三方库实现 AOP

除了上述方法,还可以使用第三方库来实现 AOP。下面是一些适用于 Golang 的流行库:

  • GoAOP:一个完全兼容 Spring AOP 框架的 Golang 实现,非常强大,但是需要添加 Java 样式的注解。但是,这个库已经很长时间没有更新了,可能需要注意。

  • AOP:一个非常简单的 AOP 框架,不需要注解,操作简单。

  • gotcha:另一个非常简单的 AOP 实现,支持 Java 样式的注解和 Struct 标签,但是需要使用额外的包管理器,可能对项目造成一些麻烦。

这些第三方库中的每一个都提供了一些内置的方法和示例,以帮助您更好地理解和使用 AOP。选择最适合您项目需求的库,并根据需要进行自定义配置。

希望这些信息可以帮助您实现 AOP 在 Golang 中的实现。