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 BeeApp is created in init().
  • Key types: HttpServer (struct), MiddleWare (func type func(http.Handler) http.Handler), LifeCycleCallback (interface with AfterStart/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 a sync.Pool for request context reuse.
  • Key types: ControllerRegister (struct), FilterRouter (linked list node), FilterChain (func type func(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 from conf/app.conf at startup and exposed as the global BConfig.
  • 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 custom Response writer, BeegoInput (typed request parameter access, binding, session) and BeegoOutput (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 Configer interface 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: Logger interface, BeeLogger struct
  • 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.Pool

For 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:

  1. registerMime — adds MIME type mappings
  2. registerDefaultErrorHandler — registers 401/403/404/500/… handlers
  3. registerSession — initializes GlobalSessions manager if SessionOn
  4. registerTemplate — parses and caches templates from ViewsPath
  5. registerAdmin — starts the in-process admin/monitor HTTP server
  6. registerGzip — 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 into AppConfig (a Configer), then walks all fields of BConfig via reflection and applies values.
  • Global access: Two globals: BConfig *Config (typed struct) and AppConfig Configer (raw interface). BConfig is the primary access path for web settings; AppConfig is 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 Configer interface is the same.
  • Environment override: The core/config/env driver 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#

  1. Global singleton + optional multi-server: BeeApp is a package-level singleton for the common case of a single server per process. Multi-server use is explicitly documented as requiring NewHttpServerWithCfg(cfg) directly. This trades safety for the ergonomics that defined beego v1’s API.

  2. 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. The FilterChain type adds a middleware-chain composition pattern on top of this.

  3. Reflection-based controller routing: When a ControllerInterface is registered, the router uses reflect.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.

  4. 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.

  5. 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.