Beego — Interfaces#
Interface catalog#
ControllerInterface#
- Package:
github.com/beego/beego/v2/server/web - File:
server/web/controller.go:137 - Methods:
Init(ct *context.Context, controllerName, actionName string, app interface{}) Prepare() Get() Post() Delete() Put() Head() Patch() Options() Trace() Finish() Render() error XSRFToken() string CheckXSRFCookie() bool HandlerFunc(fn string) bool URLMapping() - Purpose: Defines the contract for all HTTP controller handlers. The router stores registered controllers as
ControllerInterfacevalues, resolved at dispatch time via reflection. - Implementations: The base
Controllerstruct implements all 16 methods. User controllers embedControllerand override individual HTTP verb methods. - Design quality: Broad — 16 methods is a lot for an interface. The HTTP verb methods (Get/Post/Delete/Put/Head/Patch/Options/Trace) return nothing and write to
c.Ctxdirectly, which limits testability. The interface is defined by the provider (Controller) rather than the consumer, making it hard to swap. Violates ISP: a GET-only controller must satisfy the entire interface. The architecture compensates by providing default 405 implementations inController.
Configer#
- Package:
github.com/beego/beego/v2/core/config - File:
core/config/config.go:56 - Methods:
Set(key, val string) error String(key string) (string, error) Strings(key string) ([]string, error) Int(key string) (int, error) Int64(key string) (int64, error) Bool(key string) (bool, error) Float(key string) (float64, error) DefaultString(key string, defaultVal string) string DefaultStrings(key string, defaultVal []string) []string DefaultInt(key string, defaultVal int) int DefaultInt64(key string, defaultVal int64) int64 DefaultBool(key string, defaultVal bool) bool DefaultFloat(key string, defaultVal float64) float64 DIY(key string) (interface{}, error) GetSection(section string) (map[string]string, error) Unmarshaler(prefix string, obj interface{}, opt ...DecodeOption) error Sub(key string) (Configer, error) OnChange(key string, fn func(value string)) SaveConfigFile(filename string) error - Purpose: Uniform typed key-value access over any configuration backend. The
BaseConfigerstruct provides default implementations of all numeric/bool methods in terms of a singlereader func(ctx, key) (string, error), so driver authors only need to implement the reader. - Implementations: ini, json, yaml, toml, xml, env, etcd — seven drivers registered via the companion
Configadapter interface’sParsemethod. - Design quality: Wide but internally structured: paired
Foo/DefaultFoomethods for every type create an API suitable for both strict error-checking and defensive fallback access.Sub(returns a namespaced sub-configer) andOnChange(live-reload callback) are modern additions.BaseConfigerreduces driver boilerplate significantly.
Config (factory interface)#
- Package:
github.com/beego/beego/v2/core/config - File:
core/config/config.go:200 - Methods:
Parse(key string) (Configer, error) ParseData(data []byte) (Configer, error) - Purpose: Factory interface for parsing raw config files or bytes into a
Configer. Separates file-format parsing from value access — a two-level abstract factory. - Implementations:
IniConfig,JSONConfig,YAMLConfig,TOMLConfig,XMLConfig,ENVConfig,EtcdConfig— each registered viaRegister(name, Config). - Design quality: Exemplary ISP — only 2 methods, tightly focused. The naming is confusing (
Configinterface vsConfigstruct elsewhere inserver/web) but the design itself is clean.
Ormer / TxOrmer (ORM interface family)#
- Package:
github.com/beego/beego/v2/client/orm - File:
client/orm/types.go:258,263 - Interface hierarchy:
DQL (read operations: Read, ReadOrCreate, LoadRelated, QueryTable, QueryM2M, …) DML (write operations: Insert, Update, Delete, Raw, …) DriverGetter └─ ormer (private: DQL + DML + DriverGetter) └─ QueryExecutor (public alias) ├─ Ormer = QueryExecutor + TxBeginner └─ TxOrmer = QueryExecutor + TxCommitter - Methods (Ormer top-level additions):
// Via TxBeginner: Begin() (TxOrmer, error) BeginWithCtx(ctx context.Context) (TxOrmer, error) BeginWithOpts(opts *sql.TxOptions) (TxOrmer, error) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error DoTxWithCtx/WithOpts/WithCtxAndOpts variants… - Purpose:
Ormeris the main entry point for all database operations.TxOrmerscopes those same operations within a transaction and addsCommit/Rollback/RollbackUnlessCommit. - Implementations:
ormBase(internal struct). The mock package providesMockOrmviaclient/orm/mock. - Design quality: The DML/DQL decomposition is thoughtful — both carry identical
WithCtxvariants for every method, making context propagation consistent but verbose (nearly doubling method count). TheDoTxclosure pattern is a standout: it handlesBegin/Commit/Rollbackautomatically, reducing transaction boilerplate. The privateormer/ publicQueryExecutorindirection adds unnecessary complexity for little gain.
QuerySeter#
- Package:
github.com/beego/beego/v2/client/orm - File:
client/orm/types.go:276 - Methods (selected):
Filter(string, ...interface{}) QuerySeter FilterRaw(string, string) QuerySeter Exclude(string, ...interface{}) QuerySeter SetCond(*Condition) QuerySeter Limit(limit interface{}, args ...interface{}) QuerySeter Offset(offset interface{}) QuerySeter GroupBy(exprs ...string) QuerySeter OrderBy(exprs ...string) QuerySeter ForceIndex/UseIndex/IgnoreIndex(indexes ...string) QuerySeter RelatedSel(params ...interface{}) QuerySeter Distinct() QuerySeter ForUpdate() QuerySeter Count() (int64, error) Exist() bool Update(values Params) (int64, error) Delete() (int64, error) PrepareInsert() (Inserter, error) All(container interface{}, cols ...string) (int64, error) One(container interface{}, cols ...string) error Values/ValuesList/ValuesFlat variants… Aggregate(s string) QuerySeter // plus WithCtx variants for all terminal operations - Purpose: Fluent query builder. Returns
self(QuerySeter) for chaining; terminal methods (Count,All,One,Delete,Update) execute the query. Uses Django-style ORM lookups (profile__age__gt). - Implementations:
querySet(internal struct). Also mocked viaclient/orm/mock. - Design quality: Very large interface (~40+ methods including
WithCtxvariants). The fluent return ofQuerySeterfrom filter/sort methods is idiomatic and expressive. The Django-style double-underscore field traversal is unusual in Go but powerful for related model lookups. The massive size makes it hard to mock or implement from scratch.
Cache#
- Package:
github.com/beego/beego/v2/client/cache - File:
client/cache/cache.go:52 - Methods:
Get(ctx context.Context, key string) (interface{}, error) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error Delete(ctx context.Context, key string) error Incr(ctx context.Context, key string) error Decr(ctx context.Context, key string) error IsExist(ctx context.Context, key string) (bool, error) ClearAll(ctx context.Context) error StartAndGC(config string) error - Purpose: Universal cache backend contract. The
Instance func() Cachetype andRegister(name, Instance)+NewCache(name, config)idiom follows beego’s universal driver-registry pattern. - Implementations: memory, file, redis (go-redis), memcache, ssdb — each in a sub-package registered via
func init()import side-effect. - Design quality: Well-sized (9 methods). All operations take
context.Context.StartAndGCis the only lifecycle method. Theinterface{}return type predates generics; a future version could useanyor parameterize on value type.
session.Store#
- Package:
github.com/beego/beego/v2/server/web/session - File:
server/web/session/session.go:46 - Methods:
Set(ctx context.Context, key, value interface{}) error Get(ctx context.Context, key interface{}) interface{} Delete(ctx context.Context, key interface{}) error SessionID(ctx context.Context) string SessionReleaseIfPresent(ctx context.Context, w http.ResponseWriter) SessionRelease(ctx context.Context, w http.ResponseWriter) Flush(ctx context.Context) error - Purpose: Per-request session data access.
SessionReleaseserializes and persists the session back to the provider at the end of a request;SessionReleaseIfPresentis a conditional variant for lazy-start sessions. - Implementations: cookie, file, memory, redis, mysql — registered via
Register(name, Provider). - Design quality: Focused, context-aware. The
http.ResponseWriterparameter inSessionReleaseis a leaky abstraction — the store must write the cookie header directly, coupling the storage layer to the HTTP layer.
session.Provider#
- Package:
github.com/beego/beego/v2/server/web/session - File:
server/web/session/session.go:58 - Methods:
SessionInit(ctx context.Context, gclifetime int64, config string) error SessionRead(ctx context.Context, sid string) (Store, error) SessionExist(ctx context.Context, sid string) (bool, error) SessionRegenerate(ctx context.Context, oldsid, sid string) (Store, error) SessionDestroy(ctx context.Context, sid string) error SessionAll(ctx context.Context) int SessionGC(ctx context.Context) - Purpose: Global session storage management. The
Managerstruct holds aProviderand delegates all store-level operations through it.Provideris a backend (redis, file, mysql, memory);Storeis a per-request handle. - Design quality: Good two-level separation (provider ↔ per-session store). The
SessionAllmethod returning anintcount is a hint that active-session monitoring is built in. JSON config string inSessionInitis a weak spot — opaque to static analysis.
Logger#
- Package:
github.com/beego/beego/v2/core/logs - File:
core/logs/log.go:83 - Methods:
Init(config string) error WriteMsg(lm *LogMsg) error Destroy() Flush() SetFormatter(f LogFormatter) - Purpose: Log backend adapter. The
BeeLoggerstruct fans out log messages to multiple registeredLoggeradapters concurrently via goroutines and channels. - Implementations: console, file, multifile, smtp, elasticsearch, alils (Alibaba Cloud Log Service).
- Design quality: Minimal and stable.
Inittakes a JSON config string (same weakness as session).SetFormatterallows runtime log-line customization. Nocontext.ContextonWriteMsg— consistent with the pre-context era of beego’s logging layer.
LifeCycleCallback#
- Package:
github.com/beego/beego/v2/server/web - File:
server/web/server.go:81 - Methods:
AfterStart(app *HttpServer) BeforeShutdown(app *HttpServer) - Purpose: Hook for external code to react to server start and stop events. Registered via
HttpServer.AddLifeCycleCallback(cb). - Design quality: Simple and targeted. Passing
*HttpServergives callbacks access to the full server, which is both powerful and a potential source of misuse (e.g., callingRun()recursively). A narrower interface exposing justConfigor a read-only view would be safer.
FilterHandler#
- Package:
github.com/beego/beego/v2/server/web - File:
server/web/router.go:82 - Methods:
Filter(*beecontext.Context) bool - Purpose: Predicate for the access log filter: if
Filterreturnstrue, the request is excluded from the access log. Also used internally byDefaultAccessLogFilter. - Design quality: Textbook single-method interface, easily satisfiable. Named like a handler but acts as a predicate — the naming is slightly misleading.
Tasker#
- Package:
github.com/beego/beego/v2/task - File:
task/task.go:105 - Methods (key):
GetSpec(ctx context.Context) string GetStatus(ctx context.Context) string Run(ctx context.Context) error SetNext(ctx context.Context, t time.Time) GetNext(ctx context.Context) time.Time SetPrev(ctx context.Context, t time.Time) GetPrev(ctx context.Context) time.Time GetTimeout(ctx context.Context) time.Duration - Purpose: Scheduled task abstraction. The
TaskManagerstoresTaskervalues and drives them in a goroutine timer loop. - Implementations:
Taskstruct. TheOptioninterface (also in task.go) provides a functional-options extension point for task configuration. - Design quality: Context-aware throughout. 8 methods covering both state inspection and lifecycle. The paired
Set/Getmethods forNext/Prevtime are clear. Wider than strictly necessary — a simplerRun(ctx) errorwould suffice for the executor, with state queries separated.
Interface patterns#
Size distribution: Wide variation. Single-method interfaces (
FilterHandler,Configfactory) sit alongside 16-method monsters (ControllerInterface) and 40+-method query builders (QuerySeter). The ORM layer is the outlier; core infrastructure interfaces (Cache,Logger,Store) are well-sized (5–9 methods).Embedding: The ORM uses deep composition:
OrmerembedsQueryExecutorwhich embeds the privateormerwhich embedsDQL+DML+DriverGetter. This creates a clean public surface while hiding internal layering. No other subsystem uses interface embedding to the same degree.Implicit satisfaction: Beego follows Go convention — interfaces are defined at the point of use (
ControllerInterfacein the router package,FilterHandlerin the routing package) or at the boundary package (allcore/interfaces). Implementations in driver sub-packages satisfy them implicitly, with no explicitvar _ Cache = (*MemoryCache)(nil)guards visible in the main packages (though they may appear in tests).stdlib interfaces used:
http.Handler—ControllerRegisterimplements it;MiddleWarewraps ithttp.ResponseWriter—session.Storetakes it directly (leaky abstraction)fmt.Stringer— not pervasive; beego prefers explicitString()methodsio.ReadCloser,io.Writer— used internally in context/response handling
Registry pattern: Universally applied across all plugin subsystems. Each domain uses the same idiom:
Register(name string, impl DriverInterface) NewXxx(name, jsonConfig string) (Interface, error)This pattern appears in
core/config,core/logs,client/cache,server/web/session, andclient/orm.
Key abstractions#
Configer— The backbone of beego’s multi-format configuration system. ItsBaseConfigeradapter base is a textbook use of a partial implementation struct to reduce boilerplate across 7+ driver implementations. TheSubandOnChangemethods enable namespaced and reactive config, setting it apart from simpler key-value stores.Ormer+TxOrmer— The cleanest interface decomposition in the project. The DML/DQL split provides a principled separation of read vs. write concerns; theOrmer/TxOrmersplit makes transaction scope visible in the type system — you cannot accidentally begin a transaction on aTxOrmeror commit without one on anOrmer. TheDoTxclosure is the most idiomatic addition.ControllerInterface— The architectural linchpin of the MVC system. Reflection-based dispatch through this interface allows the auto-router to work (URL → controller type → HTTP-method method by name convention). Its breadth is a deliberate trade-off: users extendControllerrather than implementControllerInterfacefrom scratch, so the 16-method size is rarely felt directly.Cache— The clearest example of beego’s driver-registry pattern applied well. 9 focused methods, full context propagation, and a cleanRegister/NewCachefactory. Serves as the template for understanding how every other pluggable subsystem works.session.Store+session.Provider— The two-level session abstraction (global lifecycle vs. per-request handle) is architecturally sound. The pattern recurs conceptually in ORM (Ormervs.QuerySeter) and config (Configfactory vs.Configerreader).
Interface-driven extensibility#
Beego’s entire plugin ecosystem is driven by the register-then-retrieve interface pattern:
init() import side-effect → Register(name, factory)
user code → NewXxx(name, jsonConfig) → InterfaceThis means adding a new cache backend, log adapter, session store, or config format requires:
- Implementing the relevant interface
- Registering it via
Registerin aninit()function - Users import the driver package for its side effect
The pattern is consistent enough to be considered beego’s primary extension mechanism. It predates Go modules and the explicit dependency era, using blank imports (_ "github.com/beego/beego/v2/client/cache/redis") as the activation mechanism — a design that remains valid but is opaque compared to explicit dependency injection.
The core/bean package adds an optional reflection-based IoC container (AutoWireBeanFactory interface) for struct-level dependency injection via inject: tags, but it is not used by the framework internals and represents a separate, less-integrated extension point.