go-decorator
![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)
中文 | English
Beta version, use with caution in production environments. Click ⭐Star to follow the project's progress.
go-decorator
, Go 便捷使用装饰器的工具,装饰器能够切面 (AOP)、代理 (Proxy) 任意的函数和方法,提供观察和控制函数的能力。
go-decorator
is a tool that allows Go to easily use decorators. The decorator can slice aspect (AOP) and proxy any function and method, providing the ability to observe and control functions.
Feature
- Add the comment
//go:decor F
to use the decorator (F
is the decorator function) to quickly complete the logic such as "boilerplate code injection, non-intrusive function behavior change, control logic flow"; - You can freely define functions as decorators and apply them to any top-level function or method;
- Support the use of multiple (line)
//go:decor
decorator decorate the functions; - Support comment
type T types
type declaration, decorator will automatically decorate proxy all methods with T
or *T
as the receiver; - The decorator supports optional parameters, which brings more possibilities to development.
- Support compile-time lint verification to ensure the robustness of Go compiled code.
- Provide helpful error hints to detect problems at compile time and give the cause and line number of the error (e.g. undefined decorator or unreferenced package, etc.).
- Enhancing the target function only at compile time does not degrade the performance of the compiled program, nor does it have reflection operations.
Decorator usage can be similar to other languages such as Python, TypeScript. (Ideal for caching, forensics, logging, and other scenarios, as an aid to free up duplicate coding).
go-decorator
is a compile-time decorator injection technique. Using it does not affect your project's source files and does not generate additional .go
files or other redundant files in your project. This injection method is very different from the go:generate
generation method.
Guide
查看: 中文文档 | English Guide
Install
Install via go install
.
$ go install github.com/dengsgo/go-decorator/cmd/decorator@latest
Run decorator
and it will show you the decorator
version.
$ decorator
decorator v0.21.0 beta , https://github.com/dengsgo/go-decorator
Tip: Run the above installation command frequently to install the latest version for bug fixes, enhanced experience, and more new features.
Usage
decorator
relies on the native go
command to call it, just add the -toolexec decorator
parameter to the subcommand of go
.
For example:
Native Command | Use decorator |
---|
go build | go build -toolexec decorator |
go run main.go | go run -toolexec decorator main.go |
go test -v | go test -toolexec decorator -v |
go install | go install -toolexec decorator |
go ... -flags... | go ... -toolexec decorator -flags... |
Code
Introducing decorator dependencies in your project (must be a go.mod
project):
$ go get -u github.com/dengsgo/go-decorator
Write similar code:
package main
import (
"github.com/dengsgo/go-decorator/decor"
"log"
)
func main() {
myFunc()
}
func myFunc() {
log.Println("this is a function: myFunc")
}
func logging(ctx *decor.Context) {
log.Println("decorator function logging in", ctx.TargetIn)
ctx.TargetDo()
log.Println("decorator function logging out", ctx.TargetOut)
}
Decorator usage with parameters:
package main
import (
"github.com/dengsgo/go-decorator/decor"
)
func main() {
optionalParametersFuncDemo()
}
func levelLogging(ctx *decor.Context, level string) {
if level == "debug" {
}
ctx.TargetDo()
}
func optionalParametersFuncDemo() {
}
Add a comment to the' type T types
type declaration //go:decor F
, and the decorator will automatically use the decorator F
to decorate all methods that have T
or *T
as receiver:
package main
import (
"github.com/dengsgo/go-decorator/decor"
)
type structType struct {
name string
}
func (s *structType) Name() string {
return s.name
}
func (s *structType) StrName(name string) {
s.name = name
}
func (s *structType) empty() {}
Example
example/usages This directory demonstrates how to write code correctly to use the decorator
tool.
func main() {
section("inner.go")
useScopeInnerDecor("hello, world", 100)
section("external.go")
useExternalaDecor()
g.PrintfLn("plus(2, 3) = %+v", plus(2, 3))
section("datetime.go")
{
t := 1692450000
s := datetime(t)
g.Printf("datetime(%d)=%s\n", t, s)
}
section("genericfunc.go")
g.PrintfLn("Sum(1, 2, 3, 4, 5, 6, 7, 8, 9) = %+v", Sum(1, 2, 3, 4, 5, 6, 7, 8, 9))
section("method.go")
{
m := &methodTestPointerStruct{}
m.doSomething("main called")
}
{
m := methodTestRawStruct{}
m.doSomething("main called")
}
section("withdecorparams.go")
g.PrintfLn("useArgsDecor() = %+v", useArgsDecor())
g.Printf("useHitUseRequiredLint() = %+v", useHitUseRequiredLint())
g.Printf("useHitUseNonzeroLint() = %+v", useHitUseNonzeroLint())
g.Printf("useHitBothUseLint() = %+v", useHitBothUseLint())
g.Printf("useHitUseMultilineLintDecor() = %+v", useHitUseMultilineLintDecor())
section("types.go")
{
s := &structType{"main say hello"}
g.PrintfLn("s.Name() = %+v", s.Name())
s.StrName("StrName() set")
g.PrintfLn("s.Name() = %+v", s.Name())
s.empty()
}
{
v := varIntType(100)
g.PrintfLn("v.value() = %+v", v.value())
v.zeroSelf()
g.PrintfLn("v.value() = %+v", v.value())
}
{
genInt := &genericType[int]{}
g.PrintfLn("genInt.value() = %+v", genInt.value())
genStruct := &genericType[struct{}]{}
g.PrintfLn("genStruct.value() = %+v", genStruct.value())
}
section("types_multiple.go")
{
m := multipleStructStandType{}
m.sayHello()
}
{
m := multipleStructWrapType{}
m.sayNiHao()
}
}
See more Guide .
Requirement
Issue
If you find any problems, you can provide feedback here. GitHub Issues
Contribute
The project is still under development and due to frequent changes, external contributions are temporarily not accepted. Welcome to submit a Pull Request after stabilization.
TODO
- More documents.
- IDE friendly tool support.
- better performance.
- More testing coverage.
- More clear error reminders.
- More...