← 返回文章列表

Protobuf

整理 Protocol Buffers 的語法、訊息定義與使用方式。

go

Protobuf(Protocal Buffer),是谷歌開源的一種和語言、平臺無關的,能進行擴充套件的,用於序列化結構化資料的協議

可用於資料的通訊、資料儲存,只需要定義一次資料結構,就可以使用生成的原始碼,從各種資料流或者語言中寫入和讀取結構化資料。

Protobuf用於微服務的通訊協議

基本語法

基本框架

syntax = "proto3";

package xxx.xxx;

option gp_package = "./xxx/xxx/xxx; xxx";

// 一共有三个部分
// 第一行是版本声明
// 第二个是包的声明,防止不同项目同名消息的冲突
// 第三个手生成文件路径和生成的Go的包名

定義服務

說明

  • service表示這是一個服務(介面),關於他的命名規則,考慮到golang中透過首字母的大小寫來進行區別私有和公共,所以必須大寫,讓其他檔案能夠呼叫,同時以字尾Service結尾,表示這是一個服務

  • rpc,必須寫,只能有這一個,表示使用rpc遠端過程呼叫

  • stream,流式,用於大檔案傳輸,聊天場景或者打字機效果等等

    • 一問多答,問完之後,回答按照嚴格順序返回

    • 多問一答,嚴格順序輸入請求,等待一個響應

    • 多問多答,完全非同步的兩根管子,互補阻塞

      • 模式1,一問一答,像打乒乓球一樣

      • 模式2,像你和你曖昧物件聊天一樣,你發10條,ta會一條,或者反過來都有可能,請求和響應走不通的通道

      • 這樣的話,在golang中需要透過goroutine進行實現

service TestService {
        rpc IndexDocument (IndexRequest) returns (IndexResponse)
        rpc Chat (ChatRequest) returns (stream ChatReponse) // 一问多答
        rpc UploadFile (stream FileChunk) returns (UploadStatus) // 多问一答
        rpc LiveChat (stream VoiceData) returns (stream VoiceData) // 变问边答
}

定義訊息

message 相當於 golang中的struct

基本語法格式:型別 欄位名 = 唯一編號;

下面是一個demo

message IndexRequest {
        string library_id = 1; // 字符串
        int32 file_size = 2; // 整数类型int32
        bytes file_content = 3; // 文件内容使用二进制
        bool is_public = 4; // 布尔值
}

注意事項,唯一編號的的問題,它相當於欄位的一個身份認證,在進行RPC的時候為了省流量,不傳輸原本的變數名,直接傳輸編號,為了防止編號混亂,上線之後就不要修改已有的編號,正確做法,如果編號廢棄之後就空著不要用了,用新的欄位值

message和Go型別對比

訊息中比較高階的資料結構

陣列(slice)

使用repeated關鍵字

message ChatResponse {
        repeated string sources = 1;
}
字典(map)

map也就是鍵值對

使用map作為關鍵字

message IndexRequest {
        // Metadata map[string]string
        map<string, string> metasata = 2;
}
列舉(enum)

使用enum作為關鍵字,列舉必須從0開始,通常是預設值或者是未知值

enum只能作為message一部分使用,不能進行單獨傳輸

// 定义枚举 (必须从 0 开始)
enum DocType {
  UNKNOWN = 0; // 规范:第一个必须是 0,通常作为默认/未知值
  PDF = 1;
  IMAGE = 2;
  WORD = 3;
}

message Document {
  string name = 1;
  DocType type = 2; // 使用上面定义的枚举
}
巢狀訊息(nested)
message Author {
        string name = 1;
}

message Book {
        string title = 1;
        Author author = 2;
}

語法規範

  • 訊息名 (Message Name):使用 大駝峰 (ChatRequest)。

  • 欄位名 (Field Name):使用 下劃線蛇形 (library_id, file_name)。

    • 為什麼? 因為生成的 Go 程式碼會自動幫你轉成駝峰 (LibraryId, FileName),但在 Proto 檔案裡看下劃線更清晰。
  • 服務名 (Service Name):使用 大駝峰 (OmniRAGService)。

安裝protobuf

Mac安裝

直接透過下面的指令進行安裝即可

brew install protobuf

protoc --version

# 1. 安装生成数据结构的插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

# 2. 安装生成 gRPC 服务的插件
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

Win安裝

在 Windows 上安裝 Protobuf 和 Go 外掛,主要分為 安裝編譯器核心 (protoc) 和 安裝 Go 語言外掛 兩步。

由於 Windows 沒有像 Homebrew 那樣統一的預設包管理器,我們需要手動下載並配置環境變數。請按照以下步驟操作:

第一步:安裝編譯器核心 (protoc)

這是 Google 提供的核心工具,負責讀取 .proto 檔案。

  1. 下載壓縮包:

    • 訪問 GitHub 發布頁:Protocol Buffers Releases

    • 找到最新版本(例如 v25.x 或更高)。

    • 在 “Assets” 列表中,下載 protoc-xx.x-win64.zip (注意選 win64)。

  2. 解壓:

    • 將壓縮包解壓到一個你不會刪除的地方,建議放在 C:\protoc。

    • 解壓後,你應該能看到 bin 資料夾,裡面有一個 protoc.exe。

  3. 配置環境變數 (Path) —— 最關鍵的一步:

    • 按 Win 鍵,搜尋 “編輯系統環境變數” 並開啟。

    • 點選右下角的 “環境變數” 按鈕。

    • 在下方的 “系統變數” 區域,找到 Path​,選中它,點選 “編輯”。

    • 點選右側的 “新建”。

    • 輸入你剛才解壓的 bin 目錄路徑,例如:C:\protoc\bin。

    • 一路點選 “確定” 儲存。

  4. 驗證:

    • 開啟一個新的 CMD 或 PowerShell 視窗。

    • 輸入:protoc —version

    • 如果顯示版本號(如 libprotoc 25.1​),說明核心安裝成功!

第二步:安裝 Go 語言外掛

你需要安裝兩個 Go 外掛,這樣 protoc 才能生成 Go 程式碼。

  1. 開啟 PowerShell 或 CMD,執行以下兩條命令:
# 1. 安装生成数据结构的插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

# 2. 安装生成 gRPC 服务的插件
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
  1. 檢查 Go 的環境變數:

    • go install 會把外掛下載到你的 $GOPATH/bin 目錄下(通常是 C:\Users\你的使用者名稱\go\bin​)。

    • 你需要確保這個路徑也在你的 系統環境變數 Path 裡。

    • 驗證方法:在終端輸入 protoc-gen-go —version。

      • 如果報錯“不是內部或外部命令”,請重複“第一步”中的配置環境變數步驟,把 %USERPROFILE%\go\bin (即你的 go bin 目錄) 加到 Path 裡。

protobuf使用

使用示例

protoc --proto_path=. \
       --go_out=paths=source_relative:. \
       --go-grpc_out=paths=source_relative:. \
       api/omnirag/v1/omnirag.proto

使用說明

  • —proto_path=.: 告訴編譯器,從當前目錄(根目錄)開始尋找 import 的檔案。

  • —go_out=paths=source_relative:.:

    • 生成 .pb.go 檔案(資料結構)。

    • paths=source_relative: 表示生成的檔案路徑與 proto 檔案同級(即生成在 api/omnirag/v1/ 下),而不是按照包名亂跑。

    • :.: 輸出到當前目錄。

  • —go-grpc_out=paths=source_relative:.:

    • 生成 _grpc.pb.go 檔案(服務介面)。

    • 配置同上。

  • api/omnirag/v1/omnirag.proto: 目標檔案的路徑。

關於這篇文章的日期

舊日期 2025-01-16 與文章發布記錄不符,現按舊站可確認的首次發布日 2026-01-23 整理。實際創作日期尚無法確認。

原始日期: 2025-01-16 21:15:06 +0800