gone

package module
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2024 License: MIT Imports: 17 Imported by: 14

README

English  |  中文

license GoDoc Go Report Card codecov Build and Test Release Mentioned in Awesome Go

logo

Gone

What Is Gone?

Gone is a lightweight golang dependency injection framework; a series of Goners components are built in for rapid development of micro services.

plan

Features

  • Define the Goner interface to abstract dependencies.
  • Dependency Injection:
    • Inject Goners.
    • Inject function arguments.
  • Modular, detachable design.
  • Startup process control.
  • Testing support.
  • Built-in components:
    • goner/config, supports dependency injection of configuration parameters.
    • goner/tracer, adds TraceId to call chains, supports link tracing.
    • goner/logrus, goner/zap, supports log recording.
    • goner/gin, integrates with the gin framework to provide HTTP request parameter dependency injection.
    • goner/viper, used to parse various configuration files.
    • ...

Dependency Injection and Startup

Here's an example:

package main

import (
	"fmt"
	"github.com/gone-io/gone"
)

type Worker struct {
	gone.Flag // Anonymously embedding gone.Flag structure makes it a Goner, it can be injected as a dependency into other Goners or receive injections from other Goners.
	Name      string
}

func (w *Worker) Work() {
	fmt.Printf("I am %s, and I am working\n", w.Name)
}

type Manager struct {
	gone.Flag                         // Anonymously embedding gone.Flag structure makes it a Goner, it can be injected as a dependency into other Goners or receive injections from other Goners.
	*Worker   `gone:"manager-worker"` // Named injection GonerId="manager-worker" for Worker instance.
	workers   []*Worker               `gone:"*"` // Inject all Workers into an array.
}

func (m *Manager) Manage() {
	fmt.Printf("I am %s, and I am managing\n", m.Name)
	for _, worker := range m.workers {
		worker.Work()
	}
}

func main() {
	managerRole := &Manager{}

	managerWorker := &Worker{Name: "Scott"}
	ordinaryWorker1 := &Worker{Name: "Alice"}
	ordinaryWorker2 := &Worker{Name: "Bob"}

	gone.
		Prepare(func(cemetery gone.Cemetery) error {
			cemetery.
				Bury(managerRole).
				Bury(managerWorker, gone.GonerId("manager-worker")).
				Bury(ordinaryWorker1).
				Bury(ordinary, ordinaryWorker2)
			return nil
		}).
		// Run method supports dependency injection of parameters in its function.
		Run(func(manager *Manager) {
			manager.Manage()
		})
}

Summary:

  1. In the Gone framework, dependencies are abstracted as Goners, which can be injected into each other.
  2. By anonymously embedding the gone.Flag, the structure implements the Goner interface.
  3. Before starting, load all Goners into the framework using the Bury function.
  4. Use the Run method to start, where the function supports dependency injection of parameters.

Full Documentation

Let's use Gone to write a web service below!

🌐Web Service

package main

import (
	"fmt"
	"github.com/gone-io/gone"
	"github.com/gone-io/gone/goner"
)

// Implement a Goner. What is a Goner? => https://goner.fun/guide/core-concept.html#goner-%E9%80%9D%E8%80%85
type controller struct {
	gone.Flag // Goner tag, when anonymously embedded, a structure implements Goner
	gone.RouteGroup `gone:"gone-gin-router"` // Inject root routes
}

// Implement the Mount method to mount routes; the framework will automatically execute this method
func (ctr *controller) Mount() gone.GinMountError {

	// Define request structure
	type Req struct {
		Msg string `json:"msg"`
	}

	// Register the handler for `POST /hello`
	ctr.POST("/hello", func(in struct {
		to  string `gone:"http,query"` // Inject http request Query parameter To
		req *Req   `gone:"http,body"`  // Inject http request Body
	}) any {
		return fmt.Sprintf("to %s msg is: %s", in.to, in.req.Msg)
	})

	return nil
}

func main() {
	// Start the service
	gone.Serve(func(cemetery gone.Cemetery) error {
		// Call the framework's built-in component, load the gin framework
		_ = goner.GinPriest(cemetery)

		// Bury a controller-type Goner in the cemetery
		// What does bury mean? => https://goner.fun/guide/core-concept.html#burying
		// What is a cemetery? => https://goner.fun/guide/core-concept.html#cemetery
		cemetery.Bury(&controller{})
		return nil
	})
}

Run the above code: go run main.go, the program will listen on port 8080. Test it using curl:

curl -X POST 'http://localhost:8080/hello' \
    -H 'Content-Type: application/json' \
	--data-raw '{"msg": "你好呀?"}'

The result is as follows:

{"code":0,"data":"to  msg is: 你好呀?"}

Quick Start

💡Concepts

The code we write is ultimately lifeless unless it is run. In Gone, components are abstracted as Goners, whose properties can inject other Goners. Before Gone starts, all Goners need to be buried in the cemetery; after Gone starts, all Goners will be resurrected to establish a Heaven, "everyone in Heaven is no longer incomplete, and what they want will be satisfied."

Core Concepts

🌰 More Examples:

Detailed examples can be found in the example directory, and more will be completed in the future.

🪜🧰🛠️ Component Library (👉🏻 More components are under development... 💪🏻 ヾ(◍°∇°◍)ノ゙ 🖖🏻)

  • goner/cumx, a wrapper for github.com/soheilhy/cmux, used to reuse the same port to implement multiple protocols;
  • goner/config, used to implement configuration for Gone-App
  • goner/gin, a wrapper for github.com/gin-gonic/gin, providing web services
  • goner/logrus, a wrapper for github.com/sirupsen/logrus, providing logging services
  • goner/tracer, providing log tracing, providing a unified tracer```markdown Id for the same request chain
  • goner/xorm, a wrapper for xorm.io/xorm, used for database access; when using it, import the database driver as needed;
  • goner/redis, a wrapper for github.com/gomodule/redigo, used for interacting with redis
  • goner/schedule, a wrapper for github.com/robfig/cron/v3, used for setting timers
  • emitter, encapsulates event handling, which can be used for DDD's Event Storm
  • goner/urllib, encapsulates github.com/imroc/req/v3, used for sending HTTP requests, and connects the traceId between server and client

📚Full Documentation

Contributing

If you have a bug report or feature request, you can open an issue, and pull requests are also welcome.

Contact

If you have questions, feel free to reach out to us in the following ways:

License

gone released under MIT license, refer LICENSE file.

Documentation

Index

Constants

View Source
const (
	// GonerIdIsExisted Goner for the GonerId is existed.
	GonerIdIsExisted = 1001 + iota

	// CannotFoundGonerById cannot find the Goner by the GonerId.
	CannotFoundGonerById

	// CannotFoundGonerByType cannot find the Goner by the Type.
	CannotFoundGonerByType

	//NotCompatible Goner is not compatible with the Type.
	NotCompatible

	//ReplaceBuryIdParamEmpty Cemetery.ReplaceBury error for the GonerId is empty.
	ReplaceBuryIdParamEmpty

	//StartError Gone Start flow error.
	StartError

	//StopError Gone Stop flow error.
	StopError

	//DbRollForPanic error in rollback of DB transaction  for panic.
	DbRollForPanic

	//MustHaveGonerId error for the GonerId is empty.
	MustHaveGonerId

	//InjectError error for dependence injection error
	InjectError
)

Error Code:1001~1999 used for gone framework.

View Source
const (
	RequestIdHeaderKey = "X-Request-Id"
	TraceIdHeaderKey   = "X-Trace-Id"
)

Variables

View Source
var AfterStopSignalWaitSecond = 5

AfterStopSignalWaitSecond , The variable is used to set the time to wait after the stop signal is received.

Functions

func BlackMagic added in v1.0.0

func BlackMagic(v reflect.Value) reflect.Value

func GetFuncName added in v0.0.20

func GetFuncName(f any) string

GetFuncName get function name

func GetInterfaceType added in v0.0.17

func GetInterfaceType[T any](t *T) reflect.Type

GetInterfaceType get interface type

func IsCompatible added in v1.0.0

func IsCompatible(t reflect.Type, goner any) bool

IsCompatible t Type can put in goner

func NewSimpleLogger added in v0.0.8

func NewSimpleLogger() (Goner, GonerId, GonerOption)

func PanicTrace

func PanicTrace(kb int, skip int) []byte

PanicTrace used for getting panic stack

func Run

func Run(priests ...Priest)

Run A Gone Program;

gone.Run vs gone.Serve:

- gone.Run, The main goroutine never hangs, and the program is terminated when the main goroutine exits.

- gone.Serve, The main goroutine calls Heaven.WaitEnd and hangs, and the program waiting for the stop signal for exiting.

func Serve added in v0.0.6

func Serve(priests ...Priest)

Serve Start for A Gone Server Program.

func Test added in v0.0.6

func Test[T Goner](fn func(goner T), priests ...Priest)

Test Use for writing test cases, refer to [example](https://github.com/gone-io/gone/blob/main/example/test/goner_test.go)

func TestAt added in v0.0.6

func TestAt[T Goner](id GonerId, fn func(goner T), priests ...Priest)

TestAt Use for writing test cases, test a specific ID of Goner

func TimeStat added in v1.0.0

func TimeStat(name string, start time.Time, logs ...func(format string, args ...any))

TimeStat record the time of function and avg time

Types

type AfterReviveError added in v0.0.6

type AfterReviveError error

type Angel

type Angel interface {
	Goner
	Start(Cemetery) error
	Stop(Cemetery) error
}

type BError added in v0.3.0

type BError struct {
	// contains filtered or unexported fields
}

BError Business error implementation

func (*BError) Code added in v0.3.0

func (e *BError) Code() int

func (*BError) Data added in v0.3.0

func (e *BError) Data() any

func (*BError) Error added in v0.3.0

func (e *BError) Error() string

func (*BError) GetStatusCode added in v1.0.4

func (e *BError) GetStatusCode() int

func (*BError) Msg added in v0.3.0

func (e *BError) Msg() string

type BusinessError added in v0.3.0

type BusinessError interface {
	Error
	Data() any
}

BusinessError which has data, and which is used for Business error

func NewBusinessError added in v0.3.0

func NewBusinessError(msg string, ext ...any) BusinessError

NewBusinessError create a business error

type CMuxServer added in v1.0.0

type CMuxServer interface {
	Match(matcher ...cmux.Matcher) net.Listener
	MatchWithWriters(matcher ...cmux.MatchWriter) net.Listener
	GetAddress() string
}

CMuxServer cMux service,Used to multiplex the same port to listen for multiple protocols,ref:https://pkg.go.dev/github.com/soheilhy/cmux

type Cemetery

type Cemetery interface {
	Goner

	// Bury a Goner to the Cemetery
	Bury(Goner, ...GonerOption) Cemetery

	// BuryOnce a Goner to the Cemetery, if the Goner is already in the Cemetery, it will be ignored
	BuryOnce(goner Goner, options ...GonerOption) Cemetery

	// ReplaceBury replace the Goner in the Cemetery with a new Goner
	ReplaceBury(goner Goner, options ...GonerOption) error

	// ReviveOne Revive a Goner from the Cemetery
	ReviveOne(goner any) (deps []Tomb, err error)

	// ReviveAllFromTombs Revive all Goner from the Cemetery
	ReviveAllFromTombs() error

	// GetTomById return the Tomb by the GonerId
	GetTomById(GonerId) Tomb

	// GetTomByType return the Tombs by the GonerType
	GetTomByType(reflect.Type) []Tomb

	// InjectFuncParameters used for inject func parameters,which will construct parameters for a func;return constructed parameters reflect.Value Slice;
	// InjectFuncParameters accept two hook functions:  injectBefore and injectAfter,and hook function can be nil.
	// The ith parameter will be ignored by injecting process if injectBefore(x, i) returned is not nil, and the result of injectBefore(x, i) will be added to args.
	InjectFuncParameters(
		fn any,
		injectBefore func(pt reflect.Type, i int) any,
		injectAfter func(pt reflect.Type, i int),
	) (args []reflect.Value, err error)
}

Cemetery which is for burying and reviving Goner

func NewBuryMockCemeteryForTest added in v1.0.0

func NewBuryMockCemeteryForTest() Cemetery

NewBuryMockCemeteryForTest make a new Cemetery for test

type Configure added in v1.0.0

type Configure interface {

	//Get the value from config system
	Get(key string, v any, defaultVal string) error
}

Configure use for get value of struct attribute tag by `gone:"config,${key}"`

type Context added in v0.3.0

type Context struct {
	*gin.Context
}

Context is a wrapper of gin.Context

type Error

type Error interface {
	error
	Msg() string
	Code() int

	GetStatusCode() int
}

Error normal error

func CannotFoundGonerByIdError

func CannotFoundGonerByIdError(id GonerId) Error

func CannotFoundGonerByTypeError

func CannotFoundGonerByTypeError(t reflect.Type) Error

func GonerIdIsExistedError

func GonerIdIsExistedError(id GonerId) Error

func NewError

func NewError(code int, msg string, statusCode int) Error

NewError create a error

func NewInnerError added in v0.0.6

func NewInnerError(msg string, code int) Error

func NewInnerErrorSkip added in v1.0.0

func NewInnerErrorSkip(msg string, code int, skip int) Error

func NewParameterError added in v0.3.0

func NewParameterError(msg string, ext ...int) Error

NewParameterError create a Parameter error

func NotCompatibleError

func NotCompatibleError(a reflect.Type, b reflect.Type) Error

func ReplaceBuryIdParamEmptyError

func ReplaceBuryIdParamEmptyError() Error

func ToError added in v0.3.0

func ToError(input any) Error

ToError translate any type to An Error

type Flag

type Flag struct{}

type GinMiddleware added in v1.0.0

type GinMiddleware interface {
	Process(ctx *Context) error
}

type GinMountError added in v0.3.0

type GinMountError error

type Goner

type Goner interface {
	// contains filtered or unexported methods
}

Goner which is an abstraction of injectable objects: can inject other Goner, can be injected by other Goner.

type GonerId

type GonerId string

GonerId Goner's id

const (
	// IdGoneHeaven , The GonerId of Heaven Goner, which represents the program itself, and which is injected by default when it starts.
	IdGoneHeaven GonerId = "gone-heaven"

	// IdGoneCemetery , The GonerId of Cemetery Goner, which is Dependence Injection Key Goner, and which is injected by default.
	IdGoneCemetery GonerId = "gone-cemetery"

	// IdGoneTestKit , The GonerId of TestKit Goner, which is injected by default when using gone.Test or gone.TestAt to run test code.
	IdGoneTestKit GonerId = "gone-test-kit"

	//IdConfig , The GonerId of Config Goner, which can be used for Injecting Configs from files or envs.
	IdConfig GonerId = "config"

	//IdGoneConfigure , The GonerId of Configure Goner, which is used to read configs from devices.
	IdGoneConfigure GonerId = "gone-configure"

	// IdGoneTracer ,The GonerId of Tracer
	IdGoneTracer GonerId = "gone-tracer"

	// IdGoneLogger , The GonerId of Logger
	IdGoneLogger GonerId = "gone-logger"

	// IdGoneCMux , The GonerId of CMuxServer
	IdGoneCMux GonerId = "gone-cmux"

	// IdGoneGin , IdGoneGinRouter , IdGoneGinProcessor, IdGoneGinProxy, IdGoneGinResponser, IdHttpInjector;
	// The GonerIds of Goners in goner/gin, which integrates gin framework for web request.
	IdGoneGin              GonerId = "gone-gin"
	IdGoneGinRouter        GonerId = "gone-gin-router"
	IdGoneGinSysMiddleware GonerId = "gone-gin-sys-middleware"
	IdGoneGinProxy         GonerId = "gone-gin-proxy"
	IdGoneGinResponser     GonerId = "gone-gin-responser"
	IdHttpInjector         GonerId = "http"

	// IdGoneXorm , The GonerId of XormEngine Goner, which is for xorm engine.
	IdGoneXorm GonerId = "gone-xorm"

	// IdGoneRedisPool ,IdGoneRedisCache, IdGoneRedisKey, IdGoneRedisLocker, IdGoneRedisProvider
	// The GonerIds of Goners in goner/redis, which integrates redis framework for cache and locker.
	IdGoneRedisPool     GonerId = "gone-redis-pool"
	IdGoneRedisCache    GonerId = "gone-redis-cache"
	IdGoneRedisKey      GonerId = "gone-redis-key"
	IdGoneRedisLocker   GonerId = "gone-redis-locker"
	IdGoneRedisProvider GonerId = "gone-redis-provider"

	// IdGoneSchedule , The GonerId of Schedule Goner, which is for schedule in goner/schedule.
	IdGoneSchedule GonerId = "gone-schedule"

	// IdGoneReq , The GonerId of urllib.Client Goner, which is for request in goner/urllib.
	IdGoneReq GonerId = "gone-urllib"
)

GonerIds for Gone framework inner Goners

func GetGoneDefaultId

func GetGoneDefaultId(goner Goner) GonerId

type GonerOption added in v1.0.0

type GonerOption interface {
	// contains filtered or unexported methods
}

func IsDefault added in v1.0.0

func IsDefault[T any](t *T) GonerOption

type HandlerFunc added in v0.3.0

type HandlerFunc any

type Heaven

type Heaven interface {

	//Install do some prepare before start
	Install() Heaven

	//WaitEnd make program block until heaven stop
	WaitEnd() Heaven

	//End send a signal to heaven to stop
	End() Heaven

	//Start make heaven start
	Start() Heaven
	Stop() Heaven

	//GetHeavenStopSignal return a channel to listen the signal of heaven stop
	GetHeavenStopSignal() <-chan struct{}

	//BeforeStart add a hook function which will execute before start;
	BeforeStart(Process) Heaven

	//AfterStart add a hook function which will execute after start
	AfterStart(Process) Heaven

	//BeforeStop add a hook function which will execute before stop
	BeforeStop(Process) Heaven

	//AfterStop add a hook function which will execute after stop
	AfterStop(Process) Heaven

	SetAfterStopSignalWaitSecond(sec int)
}

func New

func New(priests ...Priest) Heaven

New build new Heaven

type IRouter added in v0.3.0

type IRouter interface {
	IRoutes

	GetGinRouter() gin.IRouter

	Group(string, ...HandlerFunc) RouteGroup

	LoadHTMLGlob(pattern string)
}

type IRoutes added in v0.3.0

type IRoutes interface {
	Use(...HandlerFunc) IRoutes

	Handle(string, string, ...HandlerFunc) IRoutes
	Any(string, ...HandlerFunc) IRoutes
	GET(string, ...HandlerFunc) IRoutes
	POST(string, ...HandlerFunc) IRoutes
	DELETE(string, ...HandlerFunc) IRoutes
	PATCH(string, ...HandlerFunc) IRoutes
	PUT(string, ...HandlerFunc) IRoutes
	OPTIONS(string, ...HandlerFunc) IRoutes
	HEAD(string, ...HandlerFunc) IRoutes
}

type InnerError added in v0.0.6

type InnerError interface {
	Error
	Stack() []byte
}

InnerError which has stack, and which is used for Internal error

type Logger

type Logger interface {
	Tracef(format string, args ...any)
	Debugf(format string, args ...any)
	Infof(format string, args ...any)
	Printf(format string, args ...any)
	Warnf(format string, args ...any)
	Errorf(format string, args ...any)
	Fatalf(format string, args ...any)
	Panicf(format string, args ...any)

	Trace(args ...any)
	Debug(args ...any)
	Info(args ...any)
	Print(args ...any)
	Warn(args ...any)
	Error(args ...any)
	Fatal(args ...any)
	Panic(args ...any)

	Traceln(args ...any)
	Debugln(args ...any)
	Infoln(args ...any)
	Println(args ...any)
	Warnln(args ...any)
	Errorln(args ...any)
	Fatalln(args ...any)
	Panicln(args ...any)
}

Logger log interface

func GetSimpleLogger added in v1.0.0

func GetSimpleLogger() Logger

type Order added in v1.0.0

type Order int
const Order0 Order = 0
const Order1 Order = 10
const Order2 Order = 100
const Order3 Order = 1000
const Order4 Order = 10000

type Preparer added in v0.2.1

type Preparer struct {
	// contains filtered or unexported fields
}

func Prepare added in v0.2.1

func Prepare(priests ...Priest) *Preparer

func (*Preparer) AfterStart added in v0.2.1

func (p *Preparer) AfterStart(fn any) *Preparer

func (*Preparer) AfterStop added in v0.2.1

func (p *Preparer) AfterStop(fn any) *Preparer

func (*Preparer) BeforeStart added in v0.2.1

func (p *Preparer) BeforeStart(fn any) *Preparer

func (*Preparer) BeforeStop added in v0.2.1

func (p *Preparer) BeforeStop(fn any) *Preparer

func (*Preparer) Run added in v0.2.1

func (p *Preparer) Run(fns ...any)

func (*Preparer) Serve added in v0.2.1

func (p *Preparer) Serve(fns ...any)

func (*Preparer) SetAfterStopSignalWaitSecond added in v1.0.0

func (p *Preparer) SetAfterStopSignalWaitSecond(sec int)

func (*Preparer) Test added in v1.0.0

func (p *Preparer) Test(fn any)

Test Use for writing test cases example: ```go

gone.Prepare(priests...).Test(func(in struct{
    cemetery Cemetery `gone:"*"`
}) {

  // test code
})

```

type Priest

type Priest func(cemetery Cemetery) error

Priest A function which has A Cemetery parameter, and return an error. use for Burying Goner

type Process

type Process func(cemetery Cemetery) error

Process a function which has a Cemetery parameter, and return an error. use for hooks

func WrapNormalFnToProcess added in v0.2.1

func WrapNormalFnToProcess(fn any) Process

WrapNormalFnToProcess warp a func to Process

type Prophet added in v0.0.6

type Prophet interface {
	Goner

	//AfterRevive A method which will execute after revive
	// Deprecate: use `AfterRevive() error` instead
	AfterRevive() AfterReviveError
}

Prophet A interface which has a AfterRevive method

type Prophet2 added in v0.2.1

type Prophet2 interface {
	Goner

	//AfterRevive A method which will execute after revive
	AfterRevive() error
}

type ResponseWriter added in v0.3.0

type ResponseWriter = gin.ResponseWriter

type RouteGroup added in v0.3.0

type RouteGroup interface {
	IRouter
}

RouteGroup route group, which is a wrapper of gin.RouterGroup, and can be injected for mount router.

type SuckError

type SuckError error

type Tomb

type Tomb interface {
	SetId(GonerId) Tomb
	GetId() GonerId
	GetGoner() Goner
	GonerIsRevive(flags ...bool) bool

	SetDefault(reflect.Type) Tomb
	IsDefault(reflect.Type) bool

	GetOrder() Order
	SetOrder(order Order) Tomb
}

Tomb container of Goner

func NewTomb

func NewTomb(goner Goner) Tomb

type Tombs

type Tombs []Tomb

func (Tombs) GetTomByType

func (tombs Tombs) GetTomByType(t reflect.Type) (filterTombs []Tomb)

func (Tombs) Len added in v1.0.0

func (tombs Tombs) Len() int

func (Tombs) Less added in v1.0.0

func (tombs Tombs) Less(i, j int) bool

func (Tombs) Swap added in v1.0.0

func (tombs Tombs) Swap(i, j int)

type Tracer added in v0.3.0

type Tracer interface {

	//SetTraceId to set `traceId` to the calling function. If traceId is an empty string, an automatic one will
	//be generated. TraceId can be obtained by using the GetTraceId () method in the calling function.
	SetTraceId(traceId string, fn func())

	//GetTraceId Get the traceId of the current goroutine
	GetTraceId() string

	//Go Start a new goroutine instead of `go func`, which can pass the traceid to the new goroutine.
	Go(fn func())

	//Recover use for catch panic in goroutine
	Recover()

	//RecoverSetTraceId SetTraceId and Recover
	RecoverSetTraceId(traceId string, fn func())
}

Tracer Log tracking, which is used to assign a unified traceId to the same call link to facilitate log tracking.

type Vampire

type Vampire interface {
	Goner
	Suck(conf string, v reflect.Value) SuckError
}

type Vampire2 added in v0.3.0

type Vampire2 interface {
	Goner
	Suck(conf string, v reflect.Value, field reflect.StructField) error
}

type XormEngine added in v0.3.0

type XormEngine interface {
	xorm.EngineInterface
	Transaction(fn func(session xorm.Interface) error) error
	Sqlx(sql string, args ...any) *xorm.Session
	GetOriginEngine() xorm.EngineInterface
}

Directories

Path Synopsis
example
app Module
http-server Module
gin
zap
internal
tools

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL