1. Основные характеристики
- файл с
.proto
В качестве суффикса файла операторы, отличные от определений структуры, заканчиваются точкой с запятой. - Определения структуры могут содержать: сообщение, сервис, перечисление.
- сообщение определяет структуру, сервис определяет метод
- Точка с запятой в конце определения метода rpc необязательна.
- Сообщение названо в верблюжьем регистре, а имена полей разделены строчными буквами и символами подчеркивания.
- Имена типов перечислений написаны в верблюжьем регистре, а имена полей разделены прописными буквами и символами подчеркивания.
- Имена сервисов и методов rpc едины в имени верблюжьего регистра.
enum GenderType {
SECRET = 0;
FEMALE = 1;
MALE = 2;
}
// 人
message Person {
int64 id = 1;
string name = 2;
GenderType gender = 3;
string number = 4;
}
2. Правила поля
Формат поля
Формат поля: модификатор уточнения | тип данных | имя поля | = | значение кодировки поля | [значение поля по умолчанию]
модификатор квалификации
К модификаторам квалификации относятся: обязательные, необязательные, повторяющиеся.
- Обязательное: указывает, что это обязательное поле
- Необязательно: представляет необязательное поле. Для получателя, если необязательное поле может быть распознано, оно будет обработано соответствующим образом, если оно не может быть распознано, поле будет проигнорировано.
- Повторяется: указывает, что поле может содержать от 0 до N элементов. Свойства такие же, как и необязательные, но каждое из них может содержать несколько значений. Это можно рассматривать как передачу массива значений
тип данных
Protobuf определяет набор основных типов данных:
Тип данных Protobuf | описывать | Пакет |
---|---|---|
bool | логический тип | 1 байт |
double | 64-битная с плавающей запятой | N |
float | 32-битное число с плавающей запятой | N |
int32 | 32-битное целое число | N |
uint32 | беззнаковое 32-битное целое | N |
int64 | 64-битное целое число | N |
uint64 | 64-битное целое число без знака | N |
$int32 | 32-битное целое, более эффективное для обработки отрицательных чисел | N |
$int64 | 64-битное целое, более эффективное для обработки отрицательных чисел | N |
fixed32 | 32-битное целое число без знака | 4 |
fixed64 | 64-битное целое число без знака | 8 |
$fixed32 | 32-битное целое число, может более эффективно обрабатывать отрицательные числа | 4 |
$fixed64 | 64-битные целые числа, которые могут более эффективно обрабатывать отрицательные числа. | 8 |
string | Может обрабатывать только символы ASCII | N |
bytes | Используется для обработки многобайтовых языковых символов, таких как китайский. | N |
enum | Может содержать определяемый пользователем тип перечисления uint32. | N(uiint32) |
message | Может содержать определяемый пользователем тип сообщения | N |
- N означает, что упакованные байты не фиксированы, а в соответствии с размером или длиной данных
- Что касается разницы между fiex32 и int32: эффективность упаковки fixed32 выше, чем у int32, но обычно он использует больше места, чем int32.
Имя поля
- Именование имен полей почти такое же, как именование переменных в таких языках, как C и Java.
- protobuf рекомендует, чтобы поля назывались в верблюжьем регистре и разделялись символами подчеркивания.
значение кодировки поля
- С помощью этого значения две взаимодействующие стороны могут идентифицировать поля друг друга. Для одного и того же значения кодировки модификатор квалификации и тип данных должны быть одинаковыми. Диапазон значений значения кодирования: 1 ~ 2^32 (4294967296)
- Среди них самыми высокими являются время кодирования и пространственная эффективность от 1 до 15. Чем больше значение кодирования, тем ниже время кодирования и пространственная эффективность.
- 1900 ~ 2000 Значение кодирования - это зарезервированное значение в системе Google Protobuf, и рекомендуется не использовать его в проекте.
Значение поля по умолчанию
- При передаче данных для требуемого типа данных, если пользователь не устанавливает значение, значение по умолчанию используется для передачи партнеру.
3. Как определить услугу
- Если вы хотите использовать тип сообщения в системе RPC, вы можете
.proto
Интерфейс службы RPC определен в файле, и компилятор буфера протокола сгенерирует код интерфейса службы в соответствии с выбранными языками. - Сгенерированный код интерфейса используется как соглашение между клиентом и сервером.Сервер должен реализовать все определенные методы интерфейса, и клиент напрямую вызывает одноименный метод, чтобы инициировать запрос к серверу (даже если никакие параметры не указаны). требуется в бизнесе, должно быть указано сообщение запроса, которое обычно определяется как пустое сообщение)
Например, если вы хотите определить службу RPC и иметь метод, который получает SearchRequest и возвращает SearchResponse, вы можете.proto
В файле сделаны следующие определения:
service SearchService {
rpc Search(SearchRequest) returns (SearchResponse) {}
}
4. Как определить сообщение
- Определение типа сообщения описывает формат сообщения запроса или ответа и может содержать несколько типов полей.
- Имя поля написано строчными буквами и автоматически становится прописными после преобразования в файл go, а сообщение эквивалентно структуре
5. Добавьте больше типов сообщений
Файл .proto может определять несколько типов сообщений, которые обычно используются для одновременного определения нескольких связанных сообщений, например, для определения поискового запроса и ответных сообщений в одном и том же файле .proto:
syntax = "proto3" // 声明使用的 protobuf 版本
message SearchRequest {
string query = 1; // 查询字符串
int32 page_number = 2;
int32 result_per_page = 3;
}
message SearchResponse {
}
6. Как использовать другие сообщения
сообщение поддерживает вложенное использование в качестве типа поля в другом сообщении
message SearchResponse {
repeated Result results = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
7. Использование вложенности сообщений
Поддерживаются вложенные сообщения, сообщение может содержать другое сообщение в качестве поля. Также возможно определить новое сообщение внутри сообщения.
Внутренне объявленные имена типов сообщений могут использоваться только непосредственно внутри:
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result results = 1;
}
Кроме того, возможно несколько уровней вложенности:
message Outer {
message A {
message Inner {
int64 ival = 1;
bool booly = 2;
}
}
message B {
message Inner {
int64 ival = 1;
bool booly = 2;
}
}
}
8. Тип карты PROTO3
-
proto3 поддерживает объявление типа карты
-
Типы ключей и значений могут быть встроенными типами или пользовательскими типами сообщений.
-
Поле не поддерживает повторяющийся атрибут
map<key_type, value_type>map_field = N; message Project {...} map<string, Project>projects = 1;
9. Компиляция файла .proto
- Чтобы сгенерировать Java, Python, Go, Ruby и другой код через определенный файл .proto, вам необходимо установить протокол компилятора.
- Формат кода, генерируемый разными языками с помощью компилятора protobuf, отличается:
- Go: Создайте файл .pb.go, каждый тип сообщения соответствует структуре
- Java: создание файла Java, каждое сообщение соответствует классу, а специальный класс Builder используется для создания интерфейса сообщений.
- ......
10. Определение импорта импорта
-
Типы, объявленные в других файлах описаний, можно импортировать с помощью оператора import.
-
Файл интерфейса protobuf может импортировать нужные файлы через импорт, например:
import "example.proto"
-
Компилятор protobuf будет искать импортированные файлы в каталоге, указанном параметром -I/ --proto_path Если этот параметр не указан, по умолчанию он будет искать в текущем каталоге.
11. Использование пакетов
Используйте package, чтобы объявить имя пакета в прото-файле, чтобы избежать конфликтов имен:
syntax = "proto3"
package foo.bar
message Open {...}
В других определениях формата сообщения вы можете использовать имя пакета + имя сообщения для использования типа, например:
message Foo {
...
foo.bar.Open open = 1;
...
}
В разных языках определения имен пакетов по-разному влияют на код, сгенерированный после компиляции:
- Go: использовать имя пакета в качестве имени пакета по умолчанию, если не указана опция go_package.
- Java: используйте имя пакета в качестве имени пакета по умолчанию, если не указана опция go_package.
- Python: пакет игнорируется