Fiberhouse Framework
-
https://github.com/lamxy/fiberhouse
🏠 關於 Fiberhouse
Fiberhouse 是基於 Fiber 的高性能、可裝配的 Go Web 框架,內置全局管理器、配置器、統一日誌器、驗證包裝器以及數據庫、緩存、中間件、統一異常處理等框架組件,開箱即用。
- 提供了強大的全局管理容器,支持自定義組件一次註冊到處使用的能力,方便開發者按需替換和功能擴展,
- 在框架層面約定了應用啓動器、全局上下文、業務分層等接口以及內置默認實現,支持自定義實現和模塊化開發,
- 使得 FiberHouse 像裝配"傢俱"的"房子"一樣可以按需構建靈活的、完整的 Go Web 應用。
🏆 開發方向
提供高性能、可擴展、可定製,開箱即用的 Go Web 框架
✨ 功能
- 高性能: 基於 Fiber 框架,提供極速的 HTTP 性能,支持對象池、goroutine池、緩存、異步等性能優化措施
- 模塊化設計: 清晰的分層架構設計,定義了標準的接口契約和實現,支持團隊協作、擴展和模塊化開發
- 全局管理器: 全局對象管理容器,無鎖設計、即時註冊、延遲初始化、單例特性,支持可替代第三方依賴注入工具的依賴解決方案、以及生命週期的統一管理
- 全局配置管理: 統一配置文件加載、解析和管理,支持多格式配置、環境變量覆蓋,適應不同的應用場景
- 統一日誌管理: 高性能日誌系統,支持結構化日誌、同步異步寫入器,以及各種日誌源標識管理
- 統一異常處理: 統一異常定義和處理機制,支持錯誤碼模塊化管理、集成參數驗證器、錯誤追蹤,以及友好的調試體驗
- 參數驗證: 集成開源驗證包裝器,支持註冊自定義語言驗證器、tag標籤規則和多語言翻譯器
- 數據庫支持: 集成 MySQL、MongoDB 驅動組件以及對數據庫模型基類的支持
- 緩存組件: 內置高性能的本地、遠程和二級緩存組件的組合使用和管理,以及對緩存模型基類的支持
- 任務隊列: 集成基於 Redis 的高性能 C/S 架構異步任務隊列,支持任務調度、延時執行和失敗重試等功能
- API 文檔: 集成 swag 文檔工具,支持自動生成 API 文檔
- 命令行應用: 完整的命令行應用框架支持,遵循統一的模塊化設計,支持團隊協作、功能擴展和模塊化開發
- 樣例模板: 提供完整的Web應用和CMD應用樣例模板結構,涵蓋了常見場景和最佳實踐,開發者稍作修改即可直接套用
- 更多: 持續優化和更新中...
🏗️ 架構説明
frame/ # FiberHouse 框架核心
├── 接口定義層
│ ├── application_interface.go # 應用啓動器接口定義
│ ├── command_interface.go # 命令行應用接口定義
│ ├── context_interface.go # 全局上下文接口定義
│ ├── json_wraper_interface.go # JSON 包裝器接口定義
│ ├── locator_interface.go # 服務定位器接口定義
│ └── model_interface.go # 數據模型接口定義
├── 應用啓動層
│ ├── applicationstarter/ # Web 應用啓動器實現
│ │ └── web_starter.go # 基於 Fiber 的應用啓動器
│ ├── commandstarter/ # 命令行應用啓動器實現
│ │ └── cmdline_starter.go # 命令行應用啓動器
│ └── bootstrap/ # 應用引導程序
│ └── bootstrap.go # 統一引導入口
├── 配置管理層
│ └── appconfig/ # 應用配置管理
│ └── config.go # 多格式配置文件加載和管理
├── 全局管理層
│ ├── globalmanager/ # 全局對象容器管理
│ │ ├── interface.go # 全局管理器接口
│ │ ├── manager.go # 全局管理器實現
│ │ └── types.go # 全局管理器類型定義
│ └── global_utility.go # 全局工具函數
├── 數據訪問層
│ └── database/ # 數據庫驅動支持
│ ├── dbmysql/ # MySQL 數據庫組件
│ │ ├── interface.go # MySQL 接口定義
│ │ ├── mysql.go # MySQL 連接實現
│ │ └── mysql_model.go # MySQL 模型基類
│ └── dbmongo/ # MongoDB 數據庫組件
│ ├── interface.go # MongoDB 接口定義
│ ├── mongo.go # MongoDB 連接實現
│ └── mongo_model.go # MongoDB 模型基類
├── 緩存系統層
│ └── cache/ # 高性能緩存組件
│ ├── cache_interface.go # 緩存接口定義
│ ├── cache_option.go # 緩存配置選項
│ ├── cache_utility.go # 緩存工具函數
│ ├── cache_errors.go # 緩存錯誤定義
│ ├── helper.go # 緩存助手函數
│ ├── cache2/ # 二級緩存實現
│ │ └── level2_cache.go # 本地+遠程二級緩存
│ ├── cachelocal/ # 本地緩存實現
│ │ ├── local_cache.go # 內存緩存實現
│ │ └── type.go # 本地緩存類型
│ └── cacheremote/ # 遠程緩存實現
│ ├── cache_model.go # 遠程緩存模型基類
│ └── redis_cache.go # Redis 緩存實現
├── 組件庫層
│ └── component/ # 框架核心組件
│ ├── dig_container.go # 基於dig依賴注入容器包裝
│ ├── jsoncodec/ # JSON 編解碼器
│ │ └── sonicjson.go # 基於 Sonic 的高性能 JSON編解碼器
│ ├── jsonconvert/ # JSON 轉換工具
│ │ └── convert.go # 轉換核心實現
│ ├── mongodecimal/ # MongoDB 十進制處理
│ │ └── mongo_decimal.go # MongoDB Decimal128 支持
│ ├── validate/ # 參數驗證組件
│ │ ├── type_interface.go # 驗證器接口定義
│ │ ├── validate_wrapper.go # 驗證器包裝實現
│ │ ├── en.go # 英文驗證器實現
│ │ ├── zh_cn.go # 簡體中文驗證器實現
│ │ ├── zh_tw.go # 繁體中文驗證器實現
│ │ └── example/ # 註冊示例
│ ├── tasklog/ # 任務日誌組件
│ │ └── logger_adapter.go # 日誌適配器
│ └── writer/ # 日誌寫入器
│ ├── async_channel_writer.go # 異步通道寫入器
│ ├── async_diode_writer.go # 異步二極管寫入器
│ ├── async_diode_writer_test.go # 異步寫入器測試
│ └── sync_lumberjack_writer.go # 同步滾動日誌寫入器
├── 中間件層
│ └── middleware/ # HTTP 中間件
│ └── recover/ # 異常恢復中間件
│ ├── config.go # 恢復中間件配置
│ └── recover.go # 恢復中間件實現
├── 響應處理層
│ └── response/ # 統一響應處理
│ └── response.go # 響應對象池和序列化
├── 異常處理層
│ └── exception/ # 統一異常處理
│ ├── types.go # 異常類型定義
│ └── exception_error.go # 異常錯誤實現
├── 工具層
│ ├── utils/ # 通用工具函數
│ │ └── common.go # 通用工具實現
│ └── constant/ # 框架常量
│ ├── constant.go # 全局常量定義
│ └── exception.go # 異常常量定義
├── 業務分層
│ ├── api.go # API 層接口定義
│ ├── service.go # 服務層接口定義
│ ├── repository.go # 倉儲層接口定義
│ └── task.go # 任務層接口定義
└── 佔位模塊
├── mq/ # 消息隊列(待實現)
├── plugins/ # 插件支持(待實現)
└── component/
├── i18n/ # 國際化(待實現)
└── rpc/ # RPC 支持(待實現)
🚀 快速開始
環境要求
- Go 1.24 或更高版本,推薦升級到1.25+
- MySQL 5.7+ 或 MongoDB 4.0+
- Redis 5.0+
docker 啓動數據庫、緩存容器用於框架調式
- docker compose文件,見: docker-compose.yml
- 啓動命令:
docker compose up -d
cd frame/docs/docker_compose_db_redis_yaml/
docker compose up -d
安裝
FiberHouse 運行需要 Go 1.24 或更高版本。如果您需要安裝或升級 Go,請訪問 Go 官方下載頁面。
要開始創建項目,請創建一個新的項目目錄並進入該目錄。然後,在終端中執行以下命令,使用 Go Modules 初始化您的項目:
go mod init github.com/your/repo
項目設置完成後,您可以使用go get命令安裝FiberHouse框架:
go get github.com/lamxy/fiberhouse
main文件示例
參考樣例: example_main/main.go
package main
import (
"github.com/lamxy/fiberhouse/example_application"
"github.com/lamxy/fiberhouse/example_application/module"
"github.com/lamxy/fiberhouse/frame"
"github.com/lamxy/fiberhouse/frame/applicationstarter"
"github.com/lamxy/fiberhouse/frame/bootstrap"
)
func main() {
// bootstrap 初始化啓動配置(全局配置、全局日誌器),配置目錄默認為當前工作目錄"."下的`example_config/`
// 可以指定絕對路徑或基於工作目錄的相對路徑
cfg := bootstrap.NewConfigOnce("./example_config")
// 日誌目錄默認為當前工作目錄"."下的`example_main/logs`
// 可以指定絕對路徑或基於工作目錄的相對路徑
logger := bootstrap.NewLoggerOnce(cfg, "./example_main/logs")
// 初始化全局應用上下文
appContext := frame.NewAppContextOnce(cfg, logger)
// 初始化應用註冊器、模塊/子系統註冊器和任務註冊器對象,注入到應用啓動器
appRegister := example_application.NewApplication(appContext) // 需實現應用註冊器接口,見frame.ApplicationRegisterer接口定義,參考example_application/application.go樣例實現
moduleRegister := module.NewModule(appContext) // 需實現模塊註冊器接口,見樣例模塊module/module.go的實現
taskRegister := module.NewTaskAsync(appContext) // 需實現任務註冊器接口,見樣例任務module/task.go的實現
// 實例化 Web 應用啓動器
webStarter := &applicationstarter.WebApplication{
// 實例化框架啓動器 // 公共框架實現
FrameStarter: applicationstarter.NewFrameApplication(appContext,
option.WithAppRegister(appRegister),
option.WithModuleRegister(moduleRegister),
option.WithTaskRegister(taskRegister),
),
// 實例化核心應用啓動器 // 核心支持可替代,只要實現CoreStarter接口,默認基於fiber實現
CoreStarter: applicationstarter.NewCoreFiber(appContext),
}
// 運行框架應用啓動器
applicationstarter.RunApplicationStarter(webStarter)
}
快速體驗
- web應用快速體驗
# 克隆框架
git clone https://github.com/lamxy/fiberhouse.git
# 進入框架目錄
cd fiberhouse
# 安裝依賴
go mod tidy
# 進入example_main/
cd example_main/
# 查看README
cat README_go_build.md
# 構建應用: windows環境為例,其他環境請參考交叉編譯
# 退回到應用根目錄(默認工作目錄),在工作目錄下執行以下命令,構建應用
# 當前工作目錄為 fiberhouse/,構建產物輸出到 example_main/target/ 目錄
cd ..
# windows環境構建產物保留.exe後綴,linux環境無需保留後綴
go build "-ldflags=-X 'main.Version=v0.0.1'" -o ./example_main/target/examplewebserver.exe ./example_main/main.go
# 運行應用
# 退回到應用根目錄(默認工作目錄),在工作目錄下執行以下命令,啓動應用
./example_main/target/examplewebserver.exe
# or Linux、 MacOS
./example_main/target/examplewebserver
訪問hello world接口: http://127.0.0.1:8080/example/hello/world
您將收到響應: {"code":0,"msg":"ok","data":"Hello World!"}
curl -sL "http://127.0.0.1:8080/example/hello/world"
# 響應:
{
"code": 0,
"msg": "ok",
"data": "Hello World!"
}
- Cmd應用快速體驗
# mysql數據庫準備
mysqlsh root:root@localhost:3306
# 創建一個test庫
CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
# 克隆框架
git clone https://github.com/lamxy/fiberhouse.git
# 進入框架目錄
cd fiberhouse
# 安裝依賴
go mod tidy
# 進入example_application/command/
cd example_application/command/
# 查看README
cat README_go_build.md
# 當前工作目錄: command/
# windows環境構建產物保留.exe後綴,Linux or MacOS環境無需保留後綴
go build -o ./target/cmdstarter.exe ./main.go
# 設置cmd應用的環境變量,windows環境,將讀取application_cmd_dev.yml配置文件
set APP_ENV_application_appType=cmd
set APP_ENV_application_env=dev
# Linux or MacOS 環境
# export APP_ENV_application_appType=cmd
# export APP_ENV_application_env=dev
# 執行cmd命令腳本,查看幫助
./target/cmdstarter.exe -h
# or
./target/cmdstarter -h
# 執行子命令,查看控制枱日誌輸出
./target/cmdstarter.exe test-orm -m ok
# or
./target/cmdstarter test-orm -m ok
# 控制枱輸出 ok
# result: ExampleMysqlService.TestOK: OK --from: ok
📖 使用指南
- examples樣例模板項目結構
- 依賴注入工具説明和使用
- 通過框架的全局管理器實現無需依賴注入工具來解決依賴關係
- 樣例 curd API實現
- 如何添加新的模塊和新的api
- task異步任務的使用樣例
- 緩存組件使用樣例
- cmd命令行應用的使用樣例
examples樣例應用模板目錄結構
- 架構概覽與説明
example_application/ # 樣例應用根目錄
├── 應用配置層
│ ├── application.go # 應用註冊器實現
│ ├── constant.go # 應用級常量定義
│ └── customizer_interface.go # 應用定製器接口
├── API 接口層
│ └── api-vo/ # API 值對象定義
│ ├── commonvo/ # 通用 VO
│ │ └── vo.go # 通用值對象
│ └── example/ # 示例模塊 VO
│ ├── api_interface.go # API 接口定義
│ ├── requestvo/ # 請求 VO
│ │ └── example_reqvo.go # 示例請求對象
│ └── responsevo/ # 響應 VO
│ └── example_respvo.go # 示例響應對象
├── 命令行框架應用層
│ └── command/ # 命令行程序
│ ├── main.go # 命令行main入口
│ ├── README_go_build.md # 構建説明
│ ├── application/
│ │ ├── application.go # 命令應用配置和邏輯
│ │ ├── constants.go # 命令常量
│ │ ├── functions.go # 命令工具函數
│ │ └── commands/ # 具體命令腳本實現
│ │ ├── test_orm_command.go # ORM 測試命令
│ │ └── test_other_command.go # 其他更多開發的命令腳本...
│ ├── component/ # 命令行組件
│ │ ├── cron.go # 定時任務組件
│ │ └── readme.md # 組件説明
│ └── target/ # 構建產物
│ └── cmdstarter.exe # 命令行可執行文件
├── 異常處理層
│ ├── get_exceptions.go # 異常獲取器
│ └── example-module/ # 示例模塊異常,其他模塊異常,每個模塊獨立目錄
│ └── exceptions.go # 模塊異常彙總
├── 中間件層
│ └── middleware/ # 應用級中間件
│ └── register_app_middleware.go # 應用中間件註冊器
├── 模塊(子系統)層
│ └── module/ # 業務模塊
│ ├── module.go # 模塊註冊器
│ ├── route_register.go # 路由註冊器
│ ├── swagger.go # Swagger 文檔配置
│ ├── task.go # 異步任務註冊器
│ ├── api/ # 模塊級 API 中間件
│ │ └── register_module_middleware.go
│ ├── command-module/ # 命令行腳本專用的業務模塊
│ │ ├── entity/ # 實體定義
│ │ │ └── mysql_types.go # MySQL 類型定義
│ │ ├── model/ # 數據模型
│ │ │ ├── mongodb_model.go # MongoDB 模型
│ │ │ └── mysql_model.go # MySQL 模型
│ │ └── service/ # 業務服務
│ │ ├── example_mysql_service.go # MySQL 服務示例
│ │ └── mongodb_service.go # MongoDB 服務示例
│ ├── common-module/ # 通用模塊
│ │ ├── attrs/ # 屬性定義
│ │ │ └── attr1.go # 屬性示例
│ │ ├── command/ # 通用命令
│ │ ├── fields/ # 通用字段
│ │ │ └── timestamps.go # 時間戳字段
│ │ ├── model/ # 通用模型
│ │ ├── repository/ # 通用倉儲
│ │ ├── service/ # 通用服務
│ │ └── vars/ # 通用變量
│ │ └── vars.go # 變量定義
│ ├── constant/ # 常量定義
│ │ └── constants.go # 模塊常量
│ └── example-module/ # 用於展示的核心樣例模塊
│ ├── api/ # API 控制器層
│ │ ├── api_provider_wire_gen.go # Wire 依賴注入生成文件
│ │ ├── api_provider.go # API 提供者,提供依賴關係
│ │ ├── common_api.go # 通用 API 控制器
│ │ ├── example_api.go # 示例 API 控制器
│ │ ├── health_api.go # 健康檢查 API 控制器
│ │ ├── README_wire_gen.md # Wire 生成説明
│ │ └── register_api_router.go # API 路由註冊
│ ├── dto/ # 數據傳輸對象
│ ├── entity/ # 實體層
│ │ └── types.go # 類型定義
│ ├── model/ # 模型層
│ │ ├── example_model.go # 示例模型
│ │ ├── example_mysql_model.go # MySQL 示例模型
│ │ └── model_wireset.go # 模型 Wire 集合
│ ├── repository/ # 倉儲層
│ │ ├── example_repository.go # 示例倉儲
│ │ ├── health_repository.go # 健康檢查倉儲
│ │ └── repository_wireset.go # 倉儲 Wire 集合
│ ├── service/ # 服務層
│ │ ├── example_service.go # 示例服務
│ │ ├── health_service.go # 健康檢查服務
│ │ ├── service_wireset.go # 服務 Wire 集合
│ │ └── test_service.go # 測試服務
│ └── task/ # 任務層
│ ├── names.go # 任務名稱定義
│ ├── task.go # 任務註冊器
│ └── handler/ # 任務處理器
│ ├── handle.go # 任務處理邏輯
│ └── mount.go # 任務掛載器
├── 工具層
│ └── utils/ # 應用工具
│ └── common.go # 通用工具函數
└── 自定義驗證器層
└── validatecustom/ # 自定義驗證器
├── tag_register.go # 標籤註冊器
├── validate_initializer.go # 驗證器初始化
├── tags/ # 自定義標籤
│ ├── new_tag_hascourses.go # 課程驗證標籤
│ └── tag_startswith.go # 前綴驗證標籤
└── validators/ # 多語言驗證器
├── ja.go # 日語驗證器
├── ko.go # 韓語驗證器
└── langs_const.go # 語言常量
依賴注入工具説明和使用
-
依賴注入工具和庫
- google wire: 依賴注入代碼生成工具,官方地址 https://github.com/google/wire
- uber dig: 依賴注入容器,推薦僅在應用啓動階段使用,官方地址 https://github.com/uber-go/dig
-
google wire使用説明和示例,參考:
- example_application/module/example-module/api/api_provider.go
- example_application/module/example-module/api/README_wire_gen.md
-
uber dig使用説明和示例,參考:
- frame/component/dig_container.go
通過框架的全局管理器實現無需依賴注入工具來解決依賴關係
- 見註冊路由示例: example_application/module/example-module/api/register_api_router.go
func RegisterRouteHandlers(ctx frame.ContextFramer, app fiber.Router) {
// 獲取exampleApi處理器
exampleApi, _ := InjectExampleApi(ctx) // 由wire編譯依賴注入生成注入函數獲取ExampleApi
// 獲取CommonApi處理器,直接NewCommonHandler
// 直接New,無需依賴注入(Wire注入),內部依賴走全局管理器延遲獲取依賴組件,
// 見 common_api.go: api.CommonHandler
commonApi := NewCommonHandler(ctx)
// 獲取註冊更多api處理器並註冊相應路由...
// 註冊Example模塊的路由
exampleGroup := app.Group("/example")
// hello world
exampleGroup.Get("/hello/world", exampleApi.HelloWorld).Name("ex_get_example_test")
}
- 見CommonHandler通過全局管理器實現無需事先依賴注入服務組件: example_application/module/example-module/api/common_api.go
// CommonHandler 示例公共處理器,繼承自 frame.ApiLocator,具備獲取上下文、配置、日誌、註冊實例等功能
type CommonHandler struct {
frame.ApiLocator
KeyTestService string // 定義依賴組件的全局管理器的實例key。通過key即可由 h.GetInstance(key) 方法獲取實例,或由 frame.GetMustInstance[T](key) 泛型方法獲取實例,
// 無需wire或其他依賴注入工具
}
// NewCommonHandler 直接New,無需依賴注入(Wire) TestService對象,內部走全局管理器獲取依賴組件
func NewCommonHandler(ctx frame.ContextFramer) *CommonHandler {
return &CommonHandler{
ApiLocator: frame.NewApi(ctx).SetName(GetKeyCommonHandler()),
// 註冊依賴的TestService實例初始化器並返回註冊實例key,通過 h.GetInstance(key) 方法獲取TestService實例
KeyTestService: service.RegisterKeyTestService(ctx),
}
}
// TestGetInstance 測試獲取註冊實例,通過 h.GetInstance(key) 方法獲取TestService註冊實例,無需編譯階段的wire依賴注入
func (h *CommonHandler) TestGetInstance(c *fiber.Ctx) error {
t := c.Query("t", "test")
// 通過 h.GetInstance(h.KeyTestService) 方法獲取註冊實例
testService, err := h.GetInstance(h.KeyTestService)
if err != nil {
return err
}
if ts, ok := testService.(*service.TestService); ok {
return response.RespSuccess(t + ":" + ts.HelloWorld()).JsonWithCtx(c)
}
return fmt.Errorf("類型斷言失敗")
}
樣例 curd API實現
- 定義實體類型: 見example_application/module/example-module/entity/types.go
// Example
type Example struct {
ID bson.ObjectID `json:"id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Age int `json:"age" bson:"age,minsize"` // minsize 取int32存儲數據
Courses []string `json:"courses" bson:"courses,omitempty"`
Profile map[string]interface{} `json:"profile" bson:"profile,omitempty"`
fields.Timestamps `json:"-" bson:",inline"` // inline: bson文檔序列化自動提升嵌入字段即自動展開繼承的公共字段
}
- 路由註冊:見 example_application/module/example-module/api/register_api_router.go
func RegisterRouteHandlers(ctx frame.ContextFramer, app fiber.Router) {
// 獲取exampleApi處理器
exampleApi, _ := InjectExampleApi(ctx) // 由wire編譯依賴注入獲取
// 註冊Example模塊的路由
// Example 路由組
exampleGroup := app.Group("/example")
// hello world 路由
exampleGroup.Get("/hello/world", exampleApi.HelloWorld).Name("ex_get_example_test")
// CURD 路由
exampleGroup.Get("/get/:id", exampleApi.GetExample).Name("ex_get_example")
exampleGroup.Get("/on-async-task/get/:id", exampleApi.GetExampleWithTaskDispatcher).Name("ex_get_example_on_task")
exampleGroup.Post("/create", exampleApi.CreateExample).Name("ex_create_example")
exampleGroup.Get("/list", exampleApi.GetExamples).Name("ex_get_examples")
}
- 定義樣例Api處理器: 見 example_application/module/example-module/api/example_api.go
// ExampleHandler 示例處理器,繼承自 frame.ApiLocator,具備獲取上下文、配置、日誌、註冊實例等功能
type ExampleHandler struct {
frame.ApiLocator
Service *service.ExampleService
KeyTestService string
}
func NewExampleHandler(ctx frame.ContextFramer, es *service.ExampleService) *ExampleHandler {
return &ExampleHandler{
ApiLocator: frame.NewApi(ctx).SetName(GetKeyExampleHandler()),
Service: es,
KeyTestService: service.RegisterKeyTestService(ctx),
}
}
// GetKeyExampleHandler 定義和獲取 ExampleHandler 註冊到全局管理器的實例key
func GetKeyExampleHandler(ns ...string) string {
return frame.RegisterKeyName("ExampleHandler", frame.GetNamespace([]string{constant.NameModuleExample}, ns...)...)
}
// GetExample 獲取樣例數據
func (h *ExampleHandler) GetExample(c *fiber.Ctx) error {
// 獲取語言
var lang = c.Get(constant.XLanguageFlag, "en")
id := c.Params("id")
// 構造需要驗證的結構體
var objId = &requestvo.ObjId{
ID: id,
}
// 獲取驗證包裝器對象
vw := h.GetContext().GetValidateWrap()
// 獲取指定語言的驗證器,並對結構體進行驗證
if errVw := vw.GetValidate(lang).Struct(objId); errVw != nil {
var errs validator.ValidationErrors
if errors.As(errVw, &errs) {
return vw.Errors(errs, lang, true)
}
}
// 從服務層獲取數據
resp, err := h.Service.GetExample(id)
if err != nil {
return err
}
// 返回成功響應
return response.RespSuccess(resp).JsonWithCtx(c)
}
- 定義樣例服務: 見 example_application/module/example-module/service/example_service.go
// ExampleService 樣例服務,繼承 frame.ServiceLocator 服務定位器接口,具備獲取上下文、配置、日誌、註冊實例等功能
type ExampleService struct {
frame.ServiceLocator // 繼承服務定位器接口
Repo *repository.ExampleRepository // 依賴的組件: 樣例倉庫,構造參數注入。由wire工具依賴注入
}
func NewExampleService(ctx frame.ContextFramer, repo *repository.ExampleRepository) *ExampleService {
name := GetKeyExampleService()
return &ExampleService{
ServiceLocator: frame.NewService(ctx).SetName(name),
Repo: repo,
}
}
// GetKeyExampleService 獲取 ExampleService 註冊鍵名
func GetKeyExampleService(ns ...string) string {
return frame.RegisterKeyName("ExampleService", frame.GetNamespace([]string{constant.NameModuleExample}, ns...)...)
}
// GetExample 根據ID獲取樣例數據
func (s *ExampleService) GetExample(id string) (*responsevo.ExampleRespVo, error) {
resp := responsevo.ExampleRespVo{}
// 調用倉儲層獲取數據
example, err := s.Repo.GetExampleById(id)
if err != nil {
return nil, err
}
// 處理數據
resp.ExamName = example.Name
resp.ExamAge = example.Age
resp.Courses = example.Courses
resp.Profile = example.Profile
resp.CreatedAt = example.CreatedAt
resp.UpdatedAt = example.UpdatedAt
// 返回數據
return &resp, nil
}
- 定義樣例倉儲: 見 example_application/module/example-module/repository/example_repository.go
// ExampleRepository Example倉庫,負責Example業務的數據持久化操作,繼承frame.RepositoryLocator倉庫定位器接口,具備獲取上下文、配置、日誌、註冊實例等功能
type ExampleRepository struct {
frame.RepositoryLocator
Model *model.ExampleModel
}
func NewExampleRepository(ctx frame.ContextFramer, m *model.ExampleModel) *ExampleRepository {
return &ExampleRepository{
RepositoryLocator: frame.NewRepository(ctx).SetName(GetKeyExampleRepository()),
Model: m,
}
}
// GetKeyExampleRepository 獲取 ExampleRepository 註冊鍵名
func GetKeyExampleRepository(ns ...string) string {
return frame.RegisterKeyName("ExampleRepository", frame.GetNamespace([]string{constant.NameModuleExample}, ns...)...)
}
// RegisterKeyExampleRepository 註冊 ExampleRepository 到容器(延遲初始化)並返回註冊key
func RegisterKeyExampleRepository(ctx frame.ContextFramer, ns ...string) string {
return frame.RegisterKeyInitializerFunc(GetKeyExampleRepository(ns...), func() (interface{}, error) {
m := model.NewExampleModel(ctx)
return NewExampleRepository(ctx, m), nil
})
}
// GetExampleById 根據ID獲取Example示例數據
func (r *ExampleRepository) GetExampleById(id string) (*entity.Example, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
result, err := r.Model.GetExampleByID(ctx, id)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, exception.GetNotFoundDocument() // 返回error
}
exception.GetInternalError().RespError(err.Error()).Panic() // 直接panic
}
return result, nil
}
- 定義樣例模型: 見 example_application/module/example-module/model/example_model.go
// ExampleModel Example模型,繼承MongoLocator定位器接口,具備獲取上下文、配置、日誌、註冊實例等功能 以及基本的mongodb操作能力
type ExampleModel struct {
dbmongo.MongoLocator
ctx context.Context // 可選屬性
}
func NewExampleModel(ctx frame.ContextFramer) *ExampleModel {
return &ExampleModel{
MongoLocator: dbmongo.NewMongoModel(ctx, constant.MongoInstanceKey).SetDbName(constant.DbNameMongo).SetTable(constant.CollExample).
SetName(GetKeyExampleModel()).(dbmongo.MongoLocator), // 設置當前模型的配置項名(mongodb)和庫名(test)
ctx: context.Background(),
}
}
// GetKeyExampleModel 獲取模型註冊key
func GetKeyExampleModel(ns ...string) string {
return frame.RegisterKeyName("ExampleModel", frame.GetNamespace([]string{constant.NameModuleExample}, ns...)...)
}
// RegisterKeyExampleModel 註冊模型到容器(延遲初始化)並返回註冊key
func RegisterKeyExampleModel(ctx frame.ContextFramer, ns ...string) string {
return frame.RegisterKeyInitializerFunc(GetKeyExampleModel(ns...), func() (interface{}, error) {
return NewExampleModel(ctx), nil
})
}
// GetExampleByID 根據ID獲取樣例文檔
func (m *ExampleModel) GetExampleByID(ctx context.Context, oid string) (*entity.Example, error) {
_id, err := bson.ObjectIDFromHex(oid)
if err != nil {
exception.GetInputError().RespError(err.Error()).Panic()
}
filter := bson.D{{"_id", _id}}
opts := options.FindOne().SetProjection(bson.M{
"_id": 0,
"profile": 0,
})
var example entity.Example
err = m.GetCollection(m.GetColl()).FindOne(ctx, filter, opts).Decode(&example)
if err != nil {
return nil, err
}
return &example, nil
}
-
調用鏈路總結: 如 獲取樣例數據接口 GET /example/get/:id
- 路由註冊: RegisterRouteHandlers -> exampleGroup.Get("/get/:id", exampleApi.GetExample)
- Api處理器: ExampleHandler.GetExample -> h.Service.GetExample
- 服務層: ExampleService.GetExample -> s.Repo.GetExampleById
- 倉儲層: ExampleRepository.GetExampleById -> r.Model.GetExampleByID
- 模型層: ExampleModel.GetExampleByID -> m.GetCollection(m.GetColl()).FindOne(...)
- 實體層: entity.Example
- 響應層: e.g. response.RespSuccess(resp).JsonWithCtx(c) -> response.RespInfo
如何添加新的模塊和新的api
- 參考樣例: example_application/module/example-module
- 複製樣例模塊目錄:從
example-module目錄複製一份作為新模塊的起始模板
cp -r example_application/module/example-module example_application/module/mymodule
-
修改模塊相關文件:
- 常量定義:修改
constant/constants.go中的模塊名稱常量 - 實體類型:修改
entity/types.go中的實體結構體定義 - 模型層:修改
model/目錄下的模型文件,更新模型名稱和數據庫表名 - 倉儲層:修改
repository/目錄下的倉儲文件,更新倉儲接口和實現 - 服務層:修改
service/目錄下的服務文件,更新業務邏輯 - API層:修改
api/目錄下的API控制器文件,更新接口定義
- 常量定義:修改
- 註冊新模塊API路由:在
module/route_register.go中添加新模塊路由註冊
// 在 RegisterApiRouters 函數中添加
mymodule.RegisterRouteHandlers(ctx, app)
-
更新Wire依賴注入:運行
wire命令重新生成依賴注入代碼# 進入新模塊的api目錄 cd example_application/module/mymodule/api # 運行wire命令生成依賴注入代碼,指定生成代碼文件的前綴 wire gen -output_file_prefix api_provider_
task異步任務的使用樣例
- 定義唯一任務名稱: 見 example_application/module/example-module/task/names.go
package task
// A list of task types. 任務名稱的列表
const (
// TypeExampleCreate 定義任務名稱,異步創建一個樣例數據
TypeExampleCreate = "ex:example:create:create-an-example"
)
- 新建任務: 見 example_application/module/example-module/task/task.go
/*
Task payload list 任務負載列表
*/
// PayloadExampleCreate 樣例創建負載的數據
type PayloadExampleCreate struct {
frame.PayloadBase // 繼承基礎負載結構體,自動具備獲取json編解碼器的方法
/**
負載的數據
*/
Age int8
}
// NewExampleCreateTask 生成一個 ExampleCreate 任務,從調用處獲取相關參數,並返回任務
func NewExampleCreateTask(ctx frame.IContext, age int8) (*asynq.Task, error) {
vo := PayloadExampleCreate{
Age: age,
}
// 獲取json編解碼器,將負載數據編碼為json格式的字節切片
payload, err := vo.GetMustJsonHandler(ctx).Marshal(&vo)
if err != nil {
return nil, err
}
return asynq.NewTask(TypeExampleCreate, payload, asynq.Retention(24*time.Hour), asynq.MaxRetry(3), asynq.ProcessIn(1*time.Minute)), nil
}
- 定義任務處理器: 見 example_application/module/example-module/task/handler/handle.go
// HandleExampleCreateTask 樣例任務創建的處理器
func HandleExampleCreateTask(ctx context.Context, t *asynq.Task) error {
// 從 context 中獲取 appCtx 全局應用上下文,獲取包括配置、日誌、註冊實例等組件
appCtx, _ := ctx.Value(frame.ContextKeyAppCtx).(frame.ContextFramer)
// 聲明任務負載對象
var p task.PayloadExampleCreate
// 解析任務負載
if err := p.GetMustJsonHandler(appCtx).Unmarshal(t.Payload(), &p); err != nil {
appCtx.GetLogger().Error(appCtx.GetConfig().LogOriginWeb()).Str("From", "HandleExampleCreateTask").Err(err).Msg("[Asynq]: Unmarshal error")
return err
}
// 獲取處理任務的實例,注意service.TestService需在任務掛載階段註冊到全局管理器
// 見 task/handler/mount.go: service.RegisterKeyTestService(ctx)
instance, err := frame.GetInstance[*service.TestService](service.GetKeyTestService())
if err != nil {
return err
}
// 將負參數傳入實例的處理函數
result, err := instance.DoAgeDoubleCreateForTaskHandle(p.Age)
if err != nil {
return err
}
// 記錄結果
appCtx.GetLogger().InfoWith(appCtx.GetConfig().LogOriginTask()).Msgf("HandleExampleCreateTask 執行成功,結果 Age double: %d", result)
return nil
}
- 任務掛載器: 見 example_application/module/example-module/task/handler/mount.go
package handler
import (
"github.com/lamxy/fiberhouse/example_application/module/example-module/service"
"github.com/lamxy/fiberhouse/example_application/module/example-module/task"
"github.com/lamxy/fiberhouse/frame"
)
// RegisterTaskHandlers 統一註冊任務處理函數和依賴的組件實例初始化器
func RegisterTaskHandlers(tk frame.TaskRegister) {
// append task handler to global taskHandlerMap
// 通過RegisterKeyXXX註冊任務處理的實例初始化器,並獲取註冊實例的keyName
// 統一註冊全局管理實例初始化器,該實例可在任務處理函數中通過tk.GetContext().GetContainer().GetXXXService()獲取,用來執行具體的任務處理邏輯
service.RegisterKeyTestService(tk.GetContext())
// 統一追加任務處理函數到Task註冊器對象的任務名稱映射的屬性中
tk.AddTaskHandlerToMap(task.TypeExampleCreate, HandleExampleCreateTask)
}
- 將任務推送到隊列: 見 example_application/module/example-module/api/example_api.go
調用了 example_application/module/example-module/service/example_service.go 的 GetExampleWithTaskDispatcher 方法
// GetExampleWithTaskDispatcher 示例方法,演示如何在服務方法中使用任務調度器異步執行任務
func (s *ExampleService) GetExampleWithTaskDispatcher(id string) (*responsevo.ExampleRespVo, error) {
resp := responsevo.ExampleRespVo{}
example, err := s.Repo.GetExampleById(id)
if err != nil {
return nil, err
}
// 獲取帶任務標記的日誌器,從全局管理器獲取已附加了日誌源標記的日誌器
log := s.GetContext().GetMustLoggerWithOrigin(s.GetContext().GetConfig().LogOriginTask())
// 獲取樣例數據成功,推送延遲任務異步執行
dispatcher, err := s.GetContext().(frame.ContextFramer).GetStarterApp().GetTask().GetTaskDispatcher()
if err != nil {
log.Warn().Err(err).Str("Category", "asynq").Msg("GetExampleWithTaskDispatcher GetTaskDispatcher failed")
}
// 創建任務對象
task1, err := task.NewExampleCreateTask(s.GetContext(), int8(example.Age))
if err != nil {
log.Warn().Err(err).Str("Category", "asynq").Msg("GetExampleWithTaskDispatcher NewExampleCountTask failed")
}
// 將任務對象入隊
tInfo, err := dispatcher.Enqueue(task1, asynq.MaxRetry(constant.TaskMaxRetryDefault), asynq.ProcessIn(1*time.Minute)) // 任務入隊,並將在1分鐘後執行
if err != nil {
log.Warn().Err(err).Msg("GetExampleWithTaskDispatcher Enqueue failed")
} else if tInfo != nil {
log.Warn().Msgf("GetExampleWithTaskDispatcher Enqueue task info: %v", tInfo)
}
// 正常的業務邏輯
resp.ExamName = example.Name
resp.ExamAge = example.Age
resp.Courses = example.Courses
resp.Profile = example.Profile
resp.CreatedAt = example.CreatedAt
resp.UpdatedAt = example.UpdatedAt
return &resp, nil
}
緩存組件使用樣例
- 見獲取樣例列表接口: example_application/module/example-module/api/example_api.go 的 GetExamples 方法
調用樣例服務的 GetExamplesWithCache 方法: example_application/module/example-module/service/example_service.go
func (s *ExampleService) GetExamples(page, size int) ([]responsevo.ExampleRespVo, error) {
// 從緩存選項池獲取緩存選項對象
co := cache.OptionPoolGet(s.GetContext())
// 使用完的緩存選項對象歸還對象池
defer cache.OptionPoolPut(co)
// 設置緩存參數: 二級緩存、啓用本地緩存、設置緩存key、設置本地緩存隨機過期時間(10秒±10%)、設置遠程緩存隨機過期時間(3分鐘±1分鐘)、寫遠程緩存同步策略、設置上下文、啓用緩存全部的保護措施
co.Level2().EnableCache().SetCacheKey("key:example:list:page:"+strconv.Itoa(page)+":size:"+strconv.Itoa(size)).SetLocalTTLRandomPercent(10*time.Second, 0.1).
SetRemoteTTLWithRandom(3*time.Minute, 1*time.Minute).SetSyncStrategyWriteRemoteOnly().SetContextCtx(context.TODO()).EnableProtectionAll()
// 獲取緩存數據,調用緩存包的 GetCached 方法,傳入緩存選項對象和獲取數據的回調函數
return cache.GetCached[[]responsevo.ExampleRespVo](co, func(ctx context.Context) ([]responsevo.ExampleRespVo, error) {
list, err := s.Repo.GetExamples(page, size)
if err != nil {
return nil, err
}
examples := make([]responsevo.ExampleRespVo, 0, len(list))
for i := range list {
example := responsevo.ExampleRespVo{
ID: list[i].ID.Hex(),
ExamName: list[i].Name,
ExamAge: list[i].Age,
Courses: list[i].Courses,
Profile: list[i].Profile,
Timestamps: commonvo.Timestamps{
CreatedAt: list[i].CreatedAt,
UpdatedAt: list[i].UpdatedAt,
},
}
examples = append(examples, example)
}
return examples, nil
})
}
CMD命令行應用使用樣例
- 命令行框架應用main入口 : 見 example_application/command/main.go
package main
import (
"github.com/lamxy/fiberhouse/example_application/command/application"
"github.com/lamxy/fiberhouse/frame"
"github.com/lamxy/fiberhouse/frame/bootstrap"
"github.com/lamxy/fiberhouse/frame/commandstarter"
)
func main() {
// bootstrap 初始化啓動配置(全局配置、全局日誌器),配置路徑為當前工作目錄下的"./../config"
cfg := bootstrap.NewConfigOnce("./../../example_config")
// 全局日誌器,定義日誌目錄為當前工作目錄下的"./logs"
logger := bootstrap.NewLoggerOnce(cfg, "./logs")
// 初始化命令全局上下文
ctx := frame.NewCmdContextOnce(cfg, logger)
// 初始化應用註冊器對象,注入應用啓動器
appRegister := application.NewApplication(ctx) // 需實現框架關於命令行應用的 frame.ApplicationCmdRegister接口
// 實例化命令行應用啓動器
cmdlineStarter := &commandstarter.CMDLineApplication{
// 實例化框架命令啓動器對象
FrameCmdStarter: commandstarter.NewFrameCmdApplication(ctx, option.WithCmdRegister(appRegister)),
// 實例化核心命令啓動器對象
CoreCmdStarter: commandstarter.NewCoreCmdCli(ctx),
}
// 運行命令行啓動器
commandstarter.RunCommandStarter(cmdlineStarter)
}
- 編寫一個命令腳本: 見 example_application/command/application/commands/test_orm_command.go
// TestOrmCMD 測試go-orm庫的CURD操作命令,需實現 frame.CommandGetter 接口,通過 GetCommand 方法返回命令行命令對象
type TestOrmCMD struct {
Ctx frame.ContextCommander
}
func NewTestOrmCMD(ctx frame.ContextCommander) frame.CommandGetter {
return &TestOrmCMD{
Ctx: ctx,
}
}
// GetCommand 獲取命令行命令對象,實現 frame.CommandGetter 接口的 GetCommand方法
func (m *TestOrmCMD) GetCommand() interface{} {
return &cli.Command{
Name: "test-orm",
Aliases: []string{"orm"},
Usage: "測試go-orm庫CURD操作",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "method",
Aliases: []string{"m"},
Usage: "測試類型(ok/orm)",
Required: true,
},
&cli.StringFlag{
Name: "operation",
Aliases: []string{"o"},
Usage: "CURD(c創建|u更新|r讀取|d刪除)",
Required: false,
},
&cli.UintFlag{
Name: "id",
Aliases: []string{"i"},
Usage: "主鍵ID",
Required: true,
},
},
Action: func(cCtx *cli.Context) error {
var (
ems *service.ExampleMysqlService
wrap = component.NewWrap[*service.ExampleMysqlService]()
)
// 使用dig注入所需依賴,通過provide連綴方法連續注入依賴組件
dc := m.Ctx.GetDigContainer().
Provide(func() frame.ContextCommander { return m.Ctx }).
Provide(model.NewExampleMysqlModel).
Provide(service.NewExampleMysqlService)
// 錯誤處理
if dc.GetErrorCount() > 0 {
return fmt.Errorf("dig container init error: %v", dc.GetProvideErrs())
}
/*
// 通過Invoke方法獲取依賴組件,在回調函數中使用依賴組件
err := dc.Invoke(func(ems *service.ExampleMysqlService) error {
err := ems.AutoMigrate()
if err != nil {
return err
}
// 其他操作...
return nil
})
*/
// 另一種方式,使用泛型Invoke方法獲取依賴組件,通過component.Wrap輔助類型來獲取依賴組件
err := component.Invoke[*service.ExampleMysqlService](wrap)
if err != nil {
return err
}
// 獲取依賴組件
ems = wrap.Get()
// 自動創建一次數據表
err = ems.AutoMigrate()
if err != nil {
return err
}
// 獲取命令行參數
method := cCtx.String("method")
// 執行測試
if method == "ok" {
testOk := ems.TestOk()
fmt.Println("result: ", testOk, "--from:", method)
} else if method == "orm" {
// 獲取更多命令行參數
op := cCtx.String("operation")
id := cCtx.Uint("id")
// 執行測試orm
err := ems.TestOrm(m.Ctx, op, id)
if err != nil {
return err
}
fmt.Println("result: testOrm OK", "--from:", method)
} else {
return fmt.Errorf("unknown method: %s", method)
}
return nil
},
}
}
- 命令行構建: 見 example_application/command/README_go_build.md
# 構建
cd command/ # command ROOT Directory
go build -o ./target/cmdstarter.exe ./main.go
# 執行命令幫助
cd command/ ## work dir is ~/command/, configure path base on it
./target/cmdstarter.exe -h
-
命令行應用使用説明
- 編譯命令行應用:
go build -o ./target/cmdstarter.exe ./main.go - 運行命令行應用查看幫助:
./target/cmdstarter.exe -h - 運行測試go-orm庫的CURD操作命令:
./target/cmdstarter.exe test-orm --method ok或./target/cmdstarter.exe test-orm -m ok - 運行測試go-orm庫的CURD操作命令(創建數據):
./target/cmdstarter.exe test-orm --method orm --operation c --id 1或./target/cmdstarter.exe test-orm -m orm -o c -i 1 - 子命令行參數幫助説明:
./target/cmdstarter.exe test-orm -h
- 編譯命令行應用:
🔧 配置説明
應用全局配置
FiberHouse 支持基於環境的多配置文件管理,配置文件位於 example_config/ 目錄。全局配置對象位於框架上下文對象中,可通過 ctx.GetConfig() 方法獲取。
- 配置文件 README: 見 example_config/README.md
- 配置文件命名規則
配置文件格式: application_[應用類型]_[環境].yml
應用類型: web | cmd
環境類型: dev | test | prod
示例文件:
- application_web_dev.yml # Web應用開發環境
- application_web_test.yml # Web應用測試環境
- application_web_prod.yml # Web應用生產環境
- application_cmd_test.yml # 命令行應用測試環境
- 環境變量配置
# 引導環境變量 (APP_ENV_ 前綴):
APP_ENV_application_appType=web # 設置應用類型: web/cmd
APP_ENV_application_env=prod # 設置運行環境: dev/test/prod
# 配置覆蓋環境變量 (APP_CONF_ 前綴):
APP_CONF_application_appName=MyApp # 覆蓋應用名稱
APP_CONF_application_server_port=9090 # 覆蓋服務端口
APP_CONF_application_appLog_level=error # 覆蓋日誌級別
APP_CONF_application_appLog_asyncConf_type=chan # 覆蓋異步日誌類型
核心配置項
-
應用基礎配置:
application: appName: "FiberHouse" # 應用名稱 appType: "web" # 應用類型: web/cmd env: "dev" # 運行環境: dev/test/prod server: host: "127.0.0.1" # 服務主機 port: 8080 # 服務端口 -
日誌系統配置:
application: appLog: level: "info" # 日誌級別: debug/info/warn/error enableConsole: true # 啓用控制枱輸出 consoleJSON: false # 控制枱JSON格式 enableFile: true # 啓用文件輸出 filename: "app.log" # 日誌文件名 # 異步日誌配置 asyncConf: enable: true # 啓用異步日誌 type: "diode" # 異步類型: chan/diode # 日誌輪轉配置 rotateConf: maxSize: 5 # megabytes maxBackups: 5 # 最大備份文件數 maxAge: 7 # days compress: false # disabled by default -
數據庫配置:
# MySQL 配置 mysql: dsn: "root:root@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local&timeout=10s" gorm: maxIdleConns: 10 # 最大空閒連接數 maxOpenConns: 100 # 最大打開連接數 connMaxLifetime: 3600 # 連接最大生命週期,單位秒 connMaxIdleTime: 300 # 連接最大空閒時間,單位秒 logger: level: info # 日誌級別: silent、error、warn、info slowThreshold: 200 * time.Millisecond # 慢SQL閾值,建議 200 * time.Millisecond,根據實際業務調整 colorful: false # 是否彩色輸出 enable: true # 是否啓用日誌記錄 skipDefaultFields: true # 跳過默認字段 pingTry: false -
redis配置:
redis: host: "127.0.0.1" port: 6379 password: "" database: 0 poolSize: 100 # 連接池大小 # 集羣配置 (可選) cluster: addrs: ["127.0.0.1:6379"] poolSize: 100 -
緩存系統配置:
cache: # 本地緩存 local: # 本地緩存配置 numCounters: 1000000 # 100萬個計數器 maxCost: 134217728 # 最大緩存128M bufferItems: 64 # 每個緩存分區的緩衝區大小 metrics: true # 是否啓用緩存指標 IgnoreInternalCost: false # 是否忽略內部開銷 # 遠程緩存 redis: # remote 遠程緩存配置 host: 127.0.0.1 # Redis 服務器地址 port: 6379 # Redis 服務器端口 password: "" # Redis 服務器密碼 # 異步池配置 asyncPool: # 啓用二級緩存時的異步goroutine池配置,用於處理緩存更新和同步策略 ants: # ants異步goroutine池配置 local: size: 248 # 本地緩存異步goroutine池大小 expiryDuration: 5 # 單位秒,空閒goroutine超時時間 preAlloc: false # 不預分配 maxBlockingTasks: 512 # 最大阻塞任務數 nonblocking: false # 允許阻塞 -
任務組件配置
task: enableServer: true # 是否啓用任務調度服務組件支持 - 更多配置按需自定義
-
完整配置示例參考:
- 測試環境配置: example_config/application_web_test.yml
- 命令行測試環境配置: application_cmd_test.yml
🤝 貢獻指南
快速開始
- Fork 倉庫並 Clone
- 創建分支:git checkout -b feature/your-feature
- 開發並保持格式:go fmt ./... && golangci-lint run
- 運行測試:go test ./... -race -cover
- 提交:feat(module): 描述
- 推送併發起 PR
分支策略
- main:穩定發佈
- develop:集成開發
- feature/*:功能
- fix/*:缺陷
- 其它分類
PR 要求
- 標題:與提交信息一致
- 內容:背景 / 方案 / 影響 / 測試 / 關聯 Issue
- CI 通過
安全
安全漏洞請私信:pytho5170@hotmail.com
📄 許可證
本項目基於 MIT 許可證開源 - 查看 LICENSE 文件瞭解詳情。
🙋♂️ 支持與反饋
- 如果您感興趣,或者支持FiberHouse的持續開發,請在GitHub上點個星GitHub Star
- 問題反饋: Issues
- 聯繫郵箱: pytho5170@hotmail.com
🌟 致謝
感謝以下開源項目:
- gofiber/fiber - 高性能 HTTP 內核
- rs/zerolog - 高性能結構化日誌
- knadh/koanf - 靈活的多源配置管理
- bytedance/sonic - 高性能 JSON 編解碼
- dgraph-io/ristretto - 高性能本地緩存
- hibiken/asynq - 基於 Redis 的分佈式任務隊列
- go.mongodb.org/mongo-driver - MongoDB 官方驅動
- gorm.io/gorm - ORM 抽象與 MySQL 支撐
- redis/go-redis - Redis 客户端
- panjf2000/ants - 高性能 goroutine 池
同時感謝:
- swaggo/swag 提供 API 文檔生成
- google/wire、uber-go/dig 支持依賴注入模式
- 以及所有未逐一列出的優秀項目
最後感謝:GitHub Copilot 提供的資料查閲、文檔整理和編碼輔助能力。
github地址:https://github.com/lamxy/fiberhouse