# go_aop **Repository Path**: fenquen/go_aop ## Basic Information - **Project Name**: go_aop - **Description**: 通过源码生成实现go的aop - **Primary Language**: Go - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-10-17 - **Last Updated**: 2024-06-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # go_aop 以源码生成为蓝本的golang的aop解决方案 ### 实现原理 秉承了java的aop的基本思想,对项目中满足要求的函数(满足切入点表达式)按需添加前置通知、环绕通知和后置通知 ### 实现效果 会对项目中的全部函数添加添加前置通知、环绕通知和后置通知,它们需要满足如下的样式 ```go // variadic 原函数入参的最后1个是不是可变参数 func Before(variadic bool, params ...any) { } // variadic 原函数入参的最后1个是不是可变参数 func Around(function any, variadic bool, params ...any) []any { // 根据实际的情况自由发挥 以下是样例 functionValue := reflect.ValueOf(function) paramValues := utils.ConvertSlice(params, func(param any) reflect.Value { return reflect.ValueOf(param) }) var returnedValues []reflect.Value if variadic { returnedValues = functionValue.CallSlice(paramValues) } else { returnedValues = functionValue.Call(paramValues) } return utils.ConvertSlice(returnedValues, func(returnedValue reflect.Value) any { return returnedValue.Interface() }) } func After(returnedValues... any) { } ``` 如果原来函数是这样的 ```go package util func (car *Car) operate(a int) (b int) { b = a + 1 return } ``` 那么修改后的是这样的 ```go package util import "go_aop/processor" func (car *Car) operate_original(a int) (b int) { b = a + 1 return } func (car *Car) operate(a int) (b int) { processor.Before(false, a) returnedValues := processor.Around(car.operate, false, a) b, _ = returnedValues[0].(int) processor.After(b) return } ``` ### 如何使用 ```shell go install gitee.com/fenquen/go_aop@latest go_aop ${项目根目录} ${配置文件的path} ``` #### 配置文件 使用配置文件来明确你需要对哪些函数使用什么样的通知 ```json { "before": { "pointcutExprs": [ "*" ], "aspectPath": "go_aop/processor.Before" }, "around": { "pointcutExprs": [ "*" ], "aspectPath": "go_aop/processor.Around" }, "after": { "pointcutExprs": [ "*" ], "aspectPath": "go_aop/processor.After" } } ```