Beego — Architecture#
Architectural style#
Layered + Plugin-based Monolith
Beego v2 is a classic full-stack web framework structured as a layered library monolith with a pervasive plugin pattern for swappable backends. The four-domain layer stack (core → client → server → task) enforces a strict dependency direction: inner layers know nothing of outer ones. Within each layer, the plugin pattern is applied consistently — every subsystem that touches I/O (config formats, log adapters, cache backends, session stores) is hidden behind an interface and delivered by a driver package that the user opts into at import time.
Evidence: core/ imports nothing from client/ or server/; server/web/config.go imports core/config but not client/orm; client/orm/ imports core/logs and core/berror but has no knowledge of server/web.
Component diagram (textual)#
┌──────────────────────────────────────────────────────┐
│ User Application │
│ import "github.com/beego/beego/v2/server/web" │
└──────────────┬───────────────────────────────────────┘
│ web.Run() / web.BeeApp
┌──────────────▼───────────────────────────────────────┐
│ server/web (HttpServer) │
│ ┌──────────────────┐ ┌──────────────────────────┐ │
│ │ ControllerRegister│ │ Config │ │
│ │ routers (Trees) │ │ (BConfig global struct) │ │
│ │ filters[5] │ └──────────────────────────┘ │
│ │ filterChains │ ┌──────────────────────────┐ │
│ │ sync.Pool(ctx) │ │ LifeCycleCallbacks [] │ │
│ └──────┬───────────┘ └──────────────────────────┘ │
│ │ ServeHTTP │
│ ┌──────▼───────────────┐ ┌──────────────────────┐ │
│ │ context.Context │ │ session / template │ │
│ │ (BeegoInput/Output) │ │ (registered hooks) │ │
│ └──────┬───────────────┘ └──────────────────────┘ │
│ │ │
│ ┌──────▼───────────────────────────────────────┐ │
│ │ Controller (user-embedded base type) │ │
│ │ Prepare → Get/Post/… → Finish → Render │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
│ │
┌──────────────▼──┐ ┌────────────▼──────────────┐
│ client/orm │ │ client/cache / httplib │
│ (Ormer iface) │ │ (Cache / HttpClient iface)│
└──────────────┬──┘ └────────────┬──────────────┘
│ │
┌──────────────▼───────────────────▼──────────────────┐
│ core/ │
│ config (Configer) │ logs (Logger) │ berror │ bean │
└─────────────────────────────────────────────────────┘Core components#
HttpServer#
- Package:
github.com/beego/beego/v2/server/web - File:
server/web/server.go - Responsibility: Top-level application container. Owns the net/http server, the routing engine, the config, and lifecycle callback hooks. The global singleton
BeeAppis created ininit(). - Key types:
HttpServer(struct),MiddleWare(func typefunc(http.Handler) http.Handler),LifeCycleCallback(interface withAfterStart/BeforeShutdown) - Dependencies:
ControllerRegister,Config,core/logs,server/web/grace
ControllerRegister#
- Package:
github.com/beego/beego/v2/server/web - File:
server/web/router.go - Responsibility: Central request dispatcher. Implements
http.Handler. Holds per-method radix-tree routers, five filter execution arrays, an onion-style filter chain root, and async.Poolfor request context reuse. - Key types:
ControllerRegister(struct),FilterRouter(linked list node),FilterChain(func typefunc(next FilterFunc) FilterFunc) - Dependencies:
server/web/context,core/logs,core/utils
Controller#
- Package:
github.com/beego/beego/v2/server/web - File:
server/web/controller.go - Responsibility: Base struct embedded by user-defined controllers. Provides HTTP method handlers (Get/Post/Delete/Put/…), lifecycle hooks (Prepare/Finish), template rendering, XSRF protection, and session access.
- Key types:
Controller(struct),ControllerInterface(interface — 14 methods),ControllerComments(Swagger metadata carrier) - Dependencies:
server/web/context,server/web/session
Config#
- Package:
github.com/beego/beego/v2/server/web - File:
server/web/config.go - Responsibility: Runtime configuration for the web server. A single large struct (
Config) holding sub-structs for listen settings, web/template settings, session settings, and log settings. Loaded fromconf/app.confat startup and exposed as the globalBConfig. - Key types:
Config,SessionConfig,ListenConfig,WebConfig - Dependencies:
core/config(Configer),core/logs,server/web/session
context.Context#
- Package:
github.com/beego/beego/v2/server/web/context - File:
server/web/context/context.go - Responsibility: Per-request state carrier. Wraps
http.Request, a customResponsewriter,BeegoInput(typed request parameter access, binding, session) andBeegoOutput(typed response helpers for JSON/XML/YAML/Protobuf/HTML). - Key types:
Context,BeegoInput,BeegoOutput,Response - Dependencies:
core/utils,server/web/session
core/config (Configer)#
- Package:
github.com/beego/beego/v2/core/config - File:
core/config/config.go - Responsibility: Defines the
Configerinterface for typed config access. Seven driver implementations: ini (default), json, yaml, toml, xml, env, etcd. - Key types:
Configer(interface — 16 methods),BaseConfiger(adapter base) - Dependencies: stdlib only (drivers add third-party parsers)
core/logs#
- Package:
github.com/beego/beego/v2/core/logs - Responsibility: Structured logger with level filtering. Drivers for console, file, multi-file, SMTP, ElasticSearch, Alibaba Cloud Log Service.
- Key types:
Loggerinterface,BeeLoggerstruct - Dependencies: stdlib + optional driver deps
client/orm#
- Package:
github.com/beego/beego/v2/client/orm - Responsibility: Full-featured ORM supporting MySQL, PostgreSQL, SQLite, TiDB. Reflection-based model registration, query building via
QuerySeter, migration engine, mock layer. - Key types:
Ormer(interface),QuerySeter(interface),RawSeter(interface),TxOrmer(interface) - Dependencies:
database/sql,core/logs,core/berror,core/utils
task#
- Package:
github.com/beego/beego/v2/task - Responsibility: Cron-style scheduled task engine. Tasks registered by name, run on a timer, managed via the admin interface.
- Key types:
Tasker(interface),Task(struct) - Dependencies:
core/logs
Data flow#
A typical HTTP request flows as follows:
net/http listener
→ ControllerRegister.ServeHTTP(w, r)
→ context acquired from sync.Pool
→ filterChain root traversal (onion pattern, outermost first)
→ filters[BeforeStatic] — e.g., serve static files
→ filters[BeforeRouter] — e.g., rate limiting, CORS
→ route tree match (ControllerRegister.routers[METHOD])
→ ControllerInterface resolved (reflect-based or direct handler)
→ filters[BeforeExec] — e.g., auth, session validation
→ controller.Init(ctx, name, action, app)
→ controller.Prepare() ← user override hook
→ controller.Get() / Post() / … ← user business logic
→ controller.Finish() ← user override hook
→ controller.Render() ← template rendering (MVC) or JSON/XML (API)
→ filters[AfterExec]
→ filters[FinishRouter]
→ context returned to sync.PoolFor a RESTful API (no template rendering), the controller calls c.Ctx.Output.JSON(data, ...) directly inside Get()/Post()/etc., and EnableRender is set to false to skip template execution.
Initialization / Bootstrap#
Beego uses a three-phase init:
Phase 1 — Package init (automatic):
// server/web/server.go
func init() {
BeeApp = NewHttpSever() // creates ControllerRegister, http.Server, BConfig
}Phase 2 — web.Run() called by user:
func Run(params ...string) {
BeeApp.Run(...)
}
func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
initBeforeHTTPRun() // sync.Once guarded
app.Handlers.Init() // builds filter chain from registered FilterChains
// ... net.Listen, TLS setup, graceful server start
}Phase 3 — initBeforeHTTPRun() (sync.Once):
Runs a sequence of registered hooks:
registerMime— adds MIME type mappingsregisterDefaultErrorHandler— registers 401/403/404/500/… handlersregisterSession— initializes GlobalSessions manager if SessionOnregisterTemplate— parses and caches templates from ViewsPathregisterAdmin— starts the in-process admin/monitor HTTP serverregisterGzip— configures response compression
Dependency injection: Beego uses core/bean — a reflection-based IoC container with struct tag wiring (inject:"name"). It is an optional facility; the web framework itself uses global singletons rather than DI.
Configuration#
- Primary source:
conf/app.conf(ini format by default) - Loading:
config.LoadAppConfig(provider, path)reads the file intoAppConfig(aConfiger), then walks all fields ofBConfigvia reflection and applies values. - Global access: Two globals:
BConfig *Config(typed struct) andAppConfig Configer(raw interface).BConfigis the primary access path for web settings;AppConfigis used for arbitrary key lookups including section-scoped ini keys. - Alternative formats: Switching to json/yaml/toml/xml/env/etcd requires only changing the provider string — the
Configerinterface is the same. - Environment override: The
core/config/envdriver allows env-var-backed configuration; ini files can also reference${ENV_VAR}substitutions. - Runtime updates:
AppConfig.Set(key, val)is available but not used by the framework core — config is read once at startup.
Key design decisions#
Global singleton + optional multi-server:
BeeAppis a package-level singleton for the common case of a single server per process. Multi-server use is explicitly documented as requiringNewHttpServerWithCfg(cfg)directly. This trades safety for the ergonomics that defined beego v1’s API.Five-point filter pipeline: Filters are registered at one of five execution points (
BeforeStatic,BeforeRouter,BeforeExec,AfterExec,FinishRouter). This gives middleware authors precise control over when they run relative to routing and controller execution — more expressive than a simple pre/post split. TheFilterChaintype adds a middleware-chain composition pattern on top of this.Reflection-based controller routing: When a
ControllerInterfaceis registered, the router usesreflect.ValueOf(c).MethodByName(actionName)at dispatch time to call the right HTTP method handler. This enables auto-router (URL path → controller method by naming convention) but adds reflection cost per request and couples the routing model to Go’s type system.Hook-based startup extensibility:
AddAPPStartHook(fns...)lets any package register initialization logic that runs exactly once before the HTTP server opens its port. The framework’s own subsystems (session, template, gzip, admin) use this same mechanism, making internal and external initialization first-class citizens.Interface-everywhere for pluggable backends: Every I/O subsystem exposes an interface (
Configer,Cache,Store/session,Ormer,Logger) and ships multiple implementations as separate packages. Users import only the driver they need. This is the most consistent design pattern across the entire codebase and is what makes beego usable as a menu of components rather than an all-or-nothing framework import.