Python cắt ngắn về 0

GHI CHÚ. Trang web này không được dùng nữa. Trang web sẽ ngừng hoạt động sau ngày 31 tháng 1 năm 2023 và lưu lượng truy cập sẽ chuyển hướng đến trang web mới tại https. // protobuf. nhà phát triển. Trong thời gian chờ đợi, các bản cập nhật sẽ chỉ được thực hiện cho protobuf. nhà phát triển

  • Trang chủ
  • Các sản phẩm
  • Bộ đệm giao thức
  • hướng dẫn

Hướng dẫn ngôn ngữ (proto3) Sắp xếp ngăn nắp với các bộ sưu tập Lưu và phân loại nội dung dựa trên sở thích của bạn

Hướng dẫn này mô tả cách sử dụng ngôn ngữ bộ đệm giao thức để cấu trúc dữ liệu bộ đệm giao thức của bạn, bao gồm cú pháp tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 và cách tạo các lớp truy cập dữ liệu từ tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của bạn. Nó bao gồm phiên bản proto3 của ngôn ngữ bộ đệm giao thức. để biết thông tin về cú pháp proto2, xem Hướng dẫn ngôn ngữ Proto2

Đây là hướng dẫn tham khảo – để biết ví dụ từng bước sử dụng nhiều tính năng được mô tả trong tài liệu này, hãy xem hướng dẫn cho ngôn ngữ bạn chọn (hiện chỉ có proto2; sắp có thêm tài liệu proto3)

Xác định loại tin nhắn

Trước tiên hãy xem một ví dụ rất đơn giản. Giả sử bạn muốn xác định định dạng thông báo yêu cầu tìm kiếm, trong đó mỗi yêu cầu tìm kiếm có một chuỗi truy vấn, trang kết quả cụ thể mà bạn quan tâm và một số kết quả trên mỗi trang. Đây là tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 bạn sử dụng để xác định loại thư

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
  • Dòng đầu tiên của tệp xác định rằng bạn đang sử dụng cú pháp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    6. nếu bạn không làm điều này, trình biên dịch bộ đệm giao thức sẽ cho rằng bạn đang sử dụng proto2. Đây phải là dòng không trống, không ghi chú đầu tiên của tệp
  • Định nghĩa thông báo
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    7 chỉ định ba trường (cặp tên/giá trị), một trường cho mỗi phần dữ liệu mà bạn muốn đưa vào loại thông báo này. Mỗi trường có một tên và một loại

Chỉ định loại trường

Trong ví dụ trên, tất cả các trường được. hai số nguyên (

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
8 và
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
9) và một chuỗi (
enum Corpus {
  CORPUS_UNSPECIFIED = 0;
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
  CORPUS_LOCAL = 4;
  CORPUS_NEWS = 5;
  CORPUS_PRODUCTS = 6;
  CORPUS_VIDEO = 7;
}
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Corpus corpus = 4;
}
0). Tuy nhiên, bạn cũng có thể chỉ định các loại kết hợp cho các trường của mình, bao gồm và các loại thông báo khác

Gán số trường

Như bạn có thể thấy, mỗi trường trong định nghĩa thông báo có một số duy nhất. Các số trường này được sử dụng để xác định các trường của bạn ở định dạng nhị phân thông báo và không được thay đổi sau khi loại thông báo của bạn được sử dụng. Lưu ý rằng số trường trong phạm vi từ 1 đến 15 mất một byte để mã hóa, bao gồm số trường và loại trường (bạn có thể tìm hiểu thêm về điều này trong). Số trường trong phạm vi 16 đến 2047 chiếm hai byte. Vì vậy, bạn nên dành các số từ 1 đến 15 cho các phần tử thông báo xuất hiện rất thường xuyên. Hãy nhớ để lại một số chỗ cho các yếu tố thường xuyên xuất hiện có thể được thêm vào trong tương lai

Số trường nhỏ nhất bạn có thể chỉ định là 1 và số lớn nhất là 229 - 1 hoặc 536.870.911. Bạn cũng không thể sử dụng các số từ 19000 đến 19999 (

enum Corpus {
  CORPUS_UNSPECIFIED = 0;
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
  CORPUS_LOCAL = 4;
  CORPUS_NEWS = 5;
  CORPUS_PRODUCTS = 6;
  CORPUS_VIDEO = 7;
}
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Corpus corpus = 4;
}
1 đến
enum Corpus {
  CORPUS_UNSPECIFIED = 0;
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
  CORPUS_LOCAL = 4;
  CORPUS_NEWS = 5;
  CORPUS_PRODUCTS = 6;
  CORPUS_VIDEO = 7;
}
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Corpus corpus = 4;
}
2), vì chúng được dành riêng cho việc triển khai Bộ đệm giao thức—trình biên dịch bộ đệm giao thức sẽ phàn nàn nếu bạn sử dụng một trong những số dành riêng này trong
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của mình. Tương tự, bạn không thể sử dụng bất kỳ số trường nào trước đây

Chỉ định quy tắc trường

Các trường tin nhắn có thể là một trong những trường sau

  • enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    4. một thông báo được định dạng tốt có thể có 0 hoặc một trong các trường này (nhưng không nhiều hơn một). Khi sử dụng cú pháp proto3, đây là quy tắc trường mặc định khi không có quy tắc trường nào khác được chỉ định cho một trường nhất định. Bạn không thể xác định liệu nó đã được phân tích cú pháp từ dây. Nó sẽ được nối tiếp với dây trừ khi nó là giá trị mặc định. Để biết thêm về chủ đề này, hãy xem Hiện diện tại hiện trường
  • enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    5. giống như
    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    4, ngoại trừ việc bạn có thể kiểm tra xem liệu giá trị có được đặt rõ ràng hay không. Trường
    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    5 ở một trong hai trạng thái có thể
    • trường được đặt và chứa một giá trị được đặt hoặc phân tích cú pháp rõ ràng từ dây. Nó sẽ được nối tiếp với dây
    • trường không được đặt và sẽ trả về giá trị mặc định. Nó sẽ không được nối tiếp với dây
  • enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    8. loại trường này có thể được lặp lại 0 lần hoặc nhiều lần trong một thông báo được định dạng tốt. Thứ tự của các giá trị lặp lại sẽ được giữ nguyên
  • enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    9. đây là loại trường khóa/giá trị được ghép nối. Xem để biết thêm về loại trường này

Trong proto3, các trường

enum Corpus {
  CORPUS_UNSPECIFIED = 0;
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
  CORPUS_LOCAL = 4;
  CORPUS_NEWS = 5;
  CORPUS_PRODUCTS = 6;
  CORPUS_VIDEO = 7;
}
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Corpus corpus = 4;
}
8 của kiểu số vô hướng sử dụng mã hóa
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
1 theo mặc định. Bạn có thể tìm hiểu thêm về mã hóa
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
1 trong

Thêm các loại tin nhắn khác

Nhiều loại thông báo có thể được xác định trong một tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3. Điều này hữu ích nếu bạn đang xác định nhiều thư có liên quan – vì vậy, ví dụ: nếu bạn muốn xác định định dạng thư trả lời tương ứng với loại thư
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
4 của mình, bạn có thể thêm nó vào cùng một thư
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}

Thêm Nhận xét

Để thêm nhận xét vào tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của bạn, hãy sử dụng cú pháp kiểu C/C++
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
7 và
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
8

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}

Trường dành riêng

Nếu bạn loại thông báo bằng cách xóa hoàn toàn một trường hoặc nhận xét nó, thì người dùng trong tương lai có thể sử dụng lại số trường khi thực hiện cập nhật của riêng họ cho loại. Điều này có thể gây ra sự cố nghiêm trọng nếu sau đó họ tải các phiên bản cũ của cùng một

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3, bao gồm hỏng dữ liệu, lỗi bảo mật, v.v. Một cách để đảm bảo điều này không xảy ra là chỉ định rằng số trường (và/hoặc tên, cũng có thể gây ra sự cố cho việc tuần tự hóa JSON) của các trường đã xóa của bạn là
enum Foo {
  reserved 2, 15, 9 to 11, 40 to max;
  reserved "FOO", "BAR";
}
0. Trình biên dịch bộ đệm giao thức sẽ khiếu nại nếu bất kỳ người dùng nào trong tương lai cố gắng sử dụng các mã định danh trường này

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}

Lưu ý rằng bạn không thể trộn lẫn tên trường và số trường trong cùng một câu lệnh

enum Foo {
  reserved 2, 15, 9 to 11, 40 to max;
  reserved "FOO", "BAR";
}
0

Điều gì được tạo ra từ message Foo { reserved 2, 15, 9 to 11; reserved "foo", "bar"; } 3 của bạn?

Khi bạn chạy trên

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3, trình biên dịch sẽ tạo mã bằng ngôn ngữ bạn chọn, bạn sẽ cần làm việc với các loại thông báo bạn đã mô tả trong tệp, bao gồm nhận và đặt giá trị trường, tuần tự hóa thông báo của bạn thành luồng đầu ra,

  • Đối với C++, trình biên dịch tạo tệp
    enum Foo {
      reserved 2, 15, 9 to 11, 40 to max;
      reserved "FOO", "BAR";
    }
    
    4 và
    enum Foo {
      reserved 2, 15, 9 to 11, 40 to max;
      reserved "FOO", "BAR";
    }
    
    5 từ mỗi
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3, với một lớp cho từng loại thông báo được mô tả trong tệp của bạn
  • Đối với Java, trình biên dịch tạo một tệp
    enum Foo {
      reserved 2, 15, 9 to 11, 40 to max;
      reserved "FOO", "BAR";
    }
    
    7 với một lớp cho từng loại thông báo, cũng như một lớp
    enum Foo {
      reserved 2, 15, 9 to 11, 40 to max;
      reserved "FOO", "BAR";
    }
    
    8 đặc biệt để tạo các thể hiện của lớp thông báo
  • Đối với Kotlin, ngoài mã do Java tạo ra, trình biên dịch tạo tệp
    enum Foo {
      reserved 2, 15, 9 to 11, 40 to max;
      reserved "FOO", "BAR";
    }
    
    9 cho từng loại thông báo, chứa DSL có thể được sử dụng để đơn giản hóa việc tạo các phiên bản thông báo
  • Python hơi khác một chút — trình biên dịch Python tạo ra một mô-đun có bộ mô tả tĩnh của từng loại thông báo trong
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 của bạn, mô-đun này sau đó được sử dụng với một siêu dữ liệu để tạo lớp truy cập dữ liệu Python cần thiết trong thời gian chạy
  • Đối với Go, trình biên dịch tạo tệp
    message SearchResponse {
      repeated Result results = 1;
    }
    
    message Result {
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    }
    
    1 với loại cho từng loại thông báo trong tệp của bạn
  • Đối với Ruby, trình biên dịch tạo tệp
    message SearchResponse {
      repeated Result results = 1;
    }
    
    message Result {
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    }
    
    2 với mô-đun Ruby chứa các loại thông báo của bạn
  • Đối với Objective-C, trình biên dịch tạo tệp
    message SearchResponse {
      repeated Result results = 1;
    }
    
    message Result {
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    }
    
    3 và
    message SearchResponse {
      repeated Result results = 1;
    }
    
    message Result {
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    }
    
    4 từ mỗi
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3, với một lớp cho từng loại thông báo được mô tả trong tệp của bạn
  • Đối với C#, trình biên dịch tạo tệp
    message SearchResponse {
      repeated Result results = 1;
    }
    
    message Result {
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    }
    
    6 từ mỗi
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3, với một lớp cho từng loại thông báo được mô tả trong tệp của bạn
  • Đối với Dart, trình biên dịch tạo tệp
    message SearchResponse {
      repeated Result results = 1;
    }
    
    message Result {
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    }
    
    8 với một lớp cho từng loại thông báo trong tệp của bạn

Bạn có thể tìm hiểu thêm về cách sử dụng API cho từng ngôn ngữ bằng cách làm theo hướng dẫn cho ngôn ngữ bạn chọn (sắp có phiên bản proto3). Để biết thêm chi tiết về API, hãy xem tài liệu tham khảo API có liên quan (sắp có phiên bản proto3)

Các loại giá trị vô hướng

Trường thông báo vô hướng có thể có một trong các loại sau – bảng hiển thị loại được chỉ định trong tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 và loại tương ứng trong lớp được tạo tự động

proto TypeNotesC++ TypeJava/Kotlin Type[1]Python Type[3]Go TypeRuby TypeC# TypePHP TypeDart Typedoubledoubledoublefloatfloat64Floatdoublefloatdoublefloatfloatfloatfloatfloat32Floatfloatfloatdoubleint32Sử dụng mã hóa có độ dài thay đổi. Không hiệu quả để mã hóa số âm – nếu trường của bạn có thể có giá trị âm, hãy sử dụng sint32 để thay thế. int32intintint32Fixnum hoặc Bignum (theo yêu cầu)intintegerintint64Sử dụng mã hóa có độ dài thay đổi. Mã hóa số âm không hiệu quả – nếu trường của bạn có thể có giá trị âm, hãy sử dụng sint64 để thay thế. int64longint/long[4]int64Bignumlonginteger/string[6]Int64uint32Sử dụng mã hóa có độ dài thay đổi. uint32int[2]int/long[4]uint32Fixnum hoặc Bignum (theo yêu cầu)uintintegerintuint64Sử dụng mã hóa có độ dài thay đổi. uint64long[2]int/long[4]uint64Bignumulonginteger/string[6]Int64sint32Sử dụng mã hóa có độ dài thay đổi. Giá trị int đã ký. Những số âm này mã hóa hiệu quả hơn so với int32 thông thường. int32intintint32Fixnum hoặc Bignum (theo yêu cầu)intintegerintsint64Sử dụng mã hóa có độ dài thay đổi. Giá trị int đã ký. Những số âm này mã hóa hiệu quả hơn so với int64 thông thường. int64longint/long[4]int64Bignumlonginteger/string[6]Int64fixed32Luôn luôn bốn byte. Hiệu quả hơn uint32 nếu giá trị thường lớn hơn 228. uint32int[2]int/long[4]uint32Fixnum hoặc Bignum (theo yêu cầu)uintintegerintfixed64Luôn tám byte. Hiệu quả hơn uint64 nếu giá trị thường lớn hơn 256. uint64long[2]int/long[4]uint64Bignumulonginteger/string[6]Int64sfixed32Luôn luôn bốn byte. int32intintint32Fixnum hoặc Bignum (theo yêu cầu)intintegerintsfixed64Luôn tám byte. int64longint/long[4]int64Bignumlonginteger/string[6]Int64boolboolbooleanboolboolTrueClass/FalseClassboolbooleanboolstringMột chuỗi phải luôn chứa văn bản ASCII 7 bit hoặc mã hóa UTF-8 và không được dài hơn 232. stringStringstr/unicode[5]stringString (UTF-8)stringstringStringbytesCó thể chứa bất kỳ chuỗi byte tùy ý nào không dài hơn 232. stringByteStringstr (Python 2)
byte (Python 3)[]byteString (ASCII-8BIT)ByteStringstringList

Bạn có thể tìm hiểu thêm về cách các loại này được mã hóa khi bạn đánh số thứ tự thư của mình trong Mã hóa bộ đệm giao thức

[1] Kotlin sử dụng các loại tương ứng từ Java, ngay cả đối với các loại không dấu, để đảm bảo khả năng tương thích trong các cơ sở mã Java/Kotlin hỗn hợp

[2] Trong Java, các số nguyên 32 bit và 64 bit không dấu được biểu diễn bằng cách sử dụng các số nguyên có dấu của chúng, với bit trên cùng chỉ đơn giản là được lưu trữ trong bit dấu

[3] Trong mọi trường hợp, việc đặt giá trị cho một trường sẽ thực hiện kiểm tra loại để đảm bảo trường đó hợp lệ

[4] Các số nguyên 32 bit 64 bit hoặc không dấu luôn được biểu thị bằng long khi được giải mã, nhưng có thể là một số nguyên nếu một số int được cung cấp khi đặt trường. Trong mọi trường hợp, giá trị phải phù hợp với loại được biểu thị khi đặt. Xem [2]

[5] Các chuỗi Python được biểu diễn dưới dạng unicode khi giải mã nhưng có thể là str nếu một chuỗi ASCII được cung cấp (điều này có thể thay đổi)

[6] Số nguyên được sử dụng trên máy 64 bit và chuỗi được sử dụng trên máy 32 bit

Giá trị mặc định

Khi một thông báo được phân tích cú pháp, nếu thông báo được mã hóa không chứa một phần tử số ít cụ thể, thì trường tương ứng trong đối tượng được phân tích cú pháp được đặt thành giá trị mặc định cho trường đó. Các giá trị mặc định này là loại cụ thể

  • Đối với chuỗi, giá trị mặc định là chuỗi rỗng
  • Đối với byte, giá trị mặc định là byte trống
  • Đối với bool, giá trị mặc định là sai
  • Đối với các loại số, giá trị mặc định là 0
  • Đối với , giá trị mặc định là giá trị enum được xác định đầu tiên, giá trị này phải là 0
  • Đối với các trường thông báo, trường không được đặt. Giá trị chính xác của nó phụ thuộc vào ngôn ngữ. Xem hướng dẫn mã được tạo để biết chi tiết

Giá trị mặc định cho các trường lặp lại là trống (thường là danh sách trống bằng ngôn ngữ thích hợp)

Lưu ý rằng đối với các trường thông báo vô hướng, sau khi một thông báo được phân tích cú pháp, không có cách nào để biết liệu một trường có được đặt rõ ràng thành giá trị mặc định hay không (ví dụ: liệu một boolean đã được đặt thành

import "myproject/other_protos.proto";
0) hay hoàn toàn không được đặt. bạn nên ghi nhớ điều này khi xác định loại tin nhắn của mình. Ví dụ: không có boolean bật một số hành vi khi được đặt thành
import "myproject/other_protos.proto";
0 nếu bạn không muốn hành vi đó cũng xảy ra theo mặc định. Cũng lưu ý rằng nếu trường thông báo vô hướng được đặt thành mặc định, giá trị sẽ không được đánh số thứ tự trên dây

Xem hướng dẫn mã được tạo cho ngôn ngữ bạn đã chọn để biết thêm chi tiết về cách hoạt động mặc định trong mã được tạo

phép liệt kê

Khi bạn đang xác định loại thông báo, bạn có thể muốn một trong các trường của nó chỉ có một trong danh sách giá trị được xác định trước. Ví dụ: giả sử bạn muốn thêm trường

import "myproject/other_protos.proto";
2 cho mỗi
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
7, trong đó kho văn bản có thể là
import "myproject/other_protos.proto";
4,
import "myproject/other_protos.proto";
5,
import "myproject/other_protos.proto";
6,
import "myproject/other_protos.proto";
7,
import "myproject/other_protos.proto";
8,
import "myproject/other_protos.proto";
9 hoặc
// new.proto
// All definitions are moved here
0. Bạn có thể làm điều này rất đơn giản bằng cách thêm một
// new.proto
// All definitions are moved here
1 vào định nghĩa thư của bạn với một hằng số cho mỗi giá trị có thể

Trong ví dụ sau, chúng tôi đã thêm một

// new.proto
// All definitions are moved here
1 được gọi là
// new.proto
// All definitions are moved here
3 với tất cả các giá trị có thể và một trường loại
// new.proto
// All definitions are moved here
3

________số 8_______

Như bạn có thể thấy, hằng số đầu tiên của

// new.proto
// All definitions are moved here
3 enum ánh xạ tới 0. mọi định nghĩa enum phải chứa một hằng số ánh xạ tới 0 làm phần tử đầu tiên của nó. Điều này là do

  • Phải có một giá trị bằng 0, để chúng ta có thể sử dụng 0 như một số
  • Giá trị 0 phải là phần tử đầu tiên, để tương thích với ngữ nghĩa proto2 trong đó giá trị enum đầu tiên luôn là giá trị mặc định

Bạn có thể xác định bí danh bằng cách gán cùng một giá trị cho các hằng số enum khác nhau. Để làm điều này, bạn cần đặt tùy chọn

// new.proto
// All definitions are moved here
6 thành
// new.proto
// All definitions are moved here
7, nếu không, trình biên dịch giao thức sẽ tạo thông báo lỗi khi tìm thấy bí danh. Mặc dù tất cả các giá trị bí danh đều hợp lệ trong quá trình giải tuần tự hóa, nhưng giá trị đầu tiên luôn được sử dụng khi tuần tự hóa

enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}

Hằng số liệt kê phải nằm trong phạm vi số nguyên 32 bit. Vì các giá trị

// new.proto
// All definitions are moved here
1 sử dụng mã hóa varint trên dây nên các giá trị âm không hiệu quả và do đó không được khuyến nghị. Bạn có thể xác định các ____61_______1 bên trong định nghĩa thông báo, như trong ví dụ trên hoặc bên ngoài – các ____61_______1 này có thể được sử dụng lại trong bất kỳ định nghĩa thông báo nào trong tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của bạn. Bạn cũng có thể sử dụng loại
// new.proto
// All definitions are moved here
1 được khai báo trong một tin nhắn làm loại trường trong một tin nhắn khác, sử dụng cú pháp
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
03

Khi bạn chạy trình biên dịch bộ đệm giao thức trên một

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 sử dụng một
// new.proto
// All definitions are moved here
1, mã được tạo ra sẽ có một ____61_______1 tương ứng cho Java, Kotlin hoặc C++ hoặc một lớp đặc biệt
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
07 cho Python được sử dụng để tạo một tập hợp các hằng ký hiệu với các giá trị nguyên

** Thận trọng. ** mã được tạo có thể bị giới hạn theo ngôn ngữ cụ thể về số lượng điều tra viên (nghìn thấp cho một ngôn ngữ). Vui lòng xem lại các giới hạn đối với ngôn ngữ bạn định sử dụng

Trong quá trình khử lưu huỳnh, các giá trị enum không được nhận dạng sẽ được giữ nguyên trong thông báo, mặc dù cách thức này được biểu thị khi thông báo được giải tuần tự hóa phụ thuộc vào ngôn ngữ. Trong các ngôn ngữ hỗ trợ các kiểu enum mở với các giá trị nằm ngoài phạm vi của các ký hiệu đã chỉ định, chẳng hạn như C++ và Go, giá trị enum không xác định được lưu trữ đơn giản dưới dạng biểu diễn số nguyên cơ bản của nó. Trong các ngôn ngữ có kiểu enum đóng, chẳng hạn như Java, một trường hợp trong enum được sử dụng để biểu thị một giá trị không được nhận dạng và số nguyên bên dưới có thể được truy cập bằng các bộ truy cập đặc biệt. Trong cả hai trường hợp, nếu thông báo được đánh số thứ tự thì giá trị không được nhận dạng sẽ vẫn được đánh số thứ tự cùng với thông báo

Để biết thêm thông tin về cách làm việc với thông báo

// new.proto
// All definitions are moved here
1 trong ứng dụng của bạn, hãy xem hướng dẫn mã được tạo cho ngôn ngữ bạn chọn

Giá trị dành riêng

Nếu bạn là một loại enum bằng cách xóa hoàn toàn một mục nhập enum hoặc nhận xét nó, những người dùng trong tương lai có thể sử dụng lại giá trị số khi thực hiện cập nhật của riêng họ cho loại. Điều này có thể gây ra sự cố nghiêm trọng nếu sau đó họ tải các phiên bản cũ của cùng một

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3, bao gồm hỏng dữ liệu, lỗi bảo mật, v.v. Một cách để đảm bảo điều này không xảy ra là chỉ định rằng các giá trị số (và/hoặc tên, cũng có thể gây ra sự cố cho quá trình tuần tự hóa JSON) của các mục nhập đã xóa của bạn là
enum Foo {
  reserved 2, 15, 9 to 11, 40 to max;
  reserved "FOO", "BAR";
}
0. Trình biên dịch bộ đệm giao thức sẽ khiếu nại nếu bất kỳ người dùng nào trong tương lai cố gắng sử dụng các mã định danh này. Bạn có thể chỉ định rằng phạm vi giá trị số dành riêng của bạn tăng lên giá trị tối đa có thể bằng cách sử dụng từ khóa
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
11

enum Foo {
  reserved 2, 15, 9 to 11, 40 to max;
  reserved "FOO", "BAR";
}

Lưu ý rằng bạn không thể kết hợp tên trường và giá trị số trong cùng một câu lệnh

enum Foo {
  reserved 2, 15, 9 to 11, 40 to max;
  reserved "FOO", "BAR";
}
0

Sử dụng các loại tin nhắn khác

Bạn có thể sử dụng các loại thông báo khác làm loại trường. Ví dụ: giả sử bạn muốn bao gồm các thư

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
13 trong mỗi thư
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
4 – để làm điều này, bạn có thể xác định một loại thư
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
13 trong cùng một thư
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 và sau đó chỉ định một trường loại
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
13 trong
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
4

message SearchResponse {
  repeated Result results = 1;
}

message Result {
  string url = 1;
  string title = 2;
  repeated string snippets = 3;
}

Nhập định nghĩa

Trong ví dụ trên, loại thông báo

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
13 được xác định trong cùng một tệp như
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
4 – nếu loại thông báo bạn muốn sử dụng làm loại trường đã được xác định trong một tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 khác thì sao?

Bạn có thể sử dụng định nghĩa từ các tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 khác bằng cách nhập chúng. Để nhập định nghĩa của
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 khác, bạn thêm câu lệnh nhập vào đầu tệp của mình

import "myproject/other_protos.proto";

Theo mặc định, bạn chỉ có thể sử dụng các định nghĩa từ tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 được nhập trực tiếp. Tuy nhiên, đôi khi bạn có thể cần di chuyển tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 đến một vị trí mới. Thay vì di chuyển trực tiếp tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 và cập nhật tất cả các vị trí cuộc gọi trong một lần thay đổi, bạn có thể đặt tệp giữ chỗ
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 ở vị trí cũ để chuyển tiếp tất cả các lần nhập sang vị trí mới bằng cách sử dụng khái niệm
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
28

Lưu ý rằng chức năng nhập công khai không khả dụng trong Java

Các phụ thuộc của

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
28 có thể được dựa vào quá độ bởi bất kỳ mã nào nhập nguyên mẫu có chứa câu lệnh
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
28. Ví dụ

// new.proto
// All definitions are moved here
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
0
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
1

Trình biên dịch giao thức tìm kiếm các tệp đã nhập trong một tập hợp các thư mục được chỉ định trên dòng lệnh của trình biên dịch giao thức bằng cách sử dụng cờ

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
31/
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
32. Nếu không có cờ nào được đưa ra, nó sẽ tìm trong thư mục mà trình biên dịch được gọi. Nói chung, bạn nên đặt cờ
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
32 cho thư mục gốc của dự án và sử dụng các tên đủ điều kiện cho tất cả các mục nhập

Sử dụng các loại tin nhắn proto2

Có thể nhập các loại tin nhắn proto2 và sử dụng chúng trong tin nhắn proto3 của bạn và ngược lại. Tuy nhiên, không thể sử dụng trực tiếp enums proto2 trong cú pháp proto3 (không sao nếu thông báo proto2 đã nhập sử dụng chúng)

Các loại lồng nhau

Bạn có thể xác định và sử dụng các loại thông báo bên trong các loại thông báo khác, như trong ví dụ sau – ở đây thông báo

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
13 được xác định bên trong thông báo
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
4

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
2

Nếu bạn muốn sử dụng lại loại tin nhắn này bên ngoài loại tin nhắn gốc của nó, bạn gọi nó là

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
36

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
3

Bạn có thể lồng các tin nhắn sâu như bạn muốn

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
4

Cập nhật loại tin nhắn

Nếu một loại thông báo hiện có không còn đáp ứng tất cả các nhu cầu của bạn – ví dụ: bạn muốn định dạng thông báo có thêm một trường – nhưng bạn vẫn muốn sử dụng mã được tạo bằng định dạng cũ, đừng lo lắng. Rất đơn giản để cập nhật các loại thông báo mà không vi phạm bất kỳ mã hiện có nào của bạn. Chỉ cần nhớ các quy tắc sau

  • Không thay đổi số trường cho bất kỳ trường hiện có nào
  • Nếu bạn thêm các trường mới, bất kỳ thư nào được đánh số thứ tự theo mã sử dụng định dạng thư "cũ" của bạn vẫn có thể được phân tích cú pháp bằng mã mới được tạo của bạn. Bạn nên ghi nhớ các yếu tố này để mã mới có thể tương tác đúng với các thông báo được tạo bởi mã cũ. Tương tự, các thông báo được tạo bởi mã mới của bạn có thể được phân tích cú pháp bằng mã cũ của bạn. nhị phân cũ chỉ cần bỏ qua trường mới khi phân tích cú pháp. Xem phần để biết chi tiết
  • Các trường có thể bị xóa, miễn là số trường không được sử dụng lại trong loại thông báo cập nhật của bạn. Thay vào đó, bạn có thể muốn đổi tên trường, có thể thêm tiền tố "OBSOLETE_" hoặc tạo trường số , để những người dùng trong tương lai của
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 của bạn không thể vô tình sử dụng lại số
  • message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    38,
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    39,
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    40,
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    41 và
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    42 đều tương thích – điều này có nghĩa là bạn có thể thay đổi trường từ một trong các loại này sang loại khác mà không vi phạm khả năng tương thích tiến hoặc lùi. Nếu một số được phân tích cú pháp từ dây không khớp với loại tương ứng, bạn sẽ nhận được hiệu ứng tương tự như thể bạn đã chuyển số đó sang loại đó trong C++ (ví dụ: nếu một số 64 bit được đọc dưới dạng
  • message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    43 và
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    44 tương thích với nhau nhưng không tương thích với các kiểu số nguyên khác
  • message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    45 và
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    46 tương thích miễn là các byte hợp lệ UTF-8
  • Tin nhắn được nhúng tương thích với
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    46 nếu các byte chứa phiên bản được mã hóa của tin nhắn
  • message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    48 tương thích với
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    49 và
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    50 với
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    51
  • Đối với các trường
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    45,
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    46 và thông báo, các trường số ít tương thích với các trường
    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    8. Với dữ liệu được tuần tự hóa của một trường lặp lại làm đầu vào, các máy khách mong đợi trường này là số ít sẽ lấy giá trị đầu vào cuối cùng nếu đó là trường loại nguyên thủy hoặc hợp nhất tất cả các thành phần đầu vào nếu đó là trường loại thông báo. Lưu ý rằng điều này thường không an toàn đối với các loại số, bao gồm bool và enums. Các trường lặp lại của các loại số có thể được tuần tự hóa ở định dạng sẽ không được phân tích cú pháp chính xác khi một trường số ít được mong đợi
  • // new.proto
    // All definitions are moved here
    
    1 tương thích với
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    38,
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    39,
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    40 và
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    41 về định dạng dây (lưu ý rằng các giá trị sẽ bị cắt bớt nếu chúng không vừa). Tuy nhiên, hãy lưu ý rằng mã máy khách có thể xử lý chúng khác đi khi thông báo được giải tuần tự hóa. ví dụ: các loại proto3
    // new.proto
    // All definitions are moved here
    
    1 không được nhận dạng sẽ được giữ nguyên trong tin nhắn, nhưng cách điều này được thể hiện khi tin nhắn được giải tuần tự hóa phụ thuộc vào ngôn ngữ. Các trường int luôn chỉ bảo toàn giá trị của chúng
  • Việc thay đổi một trường hoặc tiện ích mở rộng
    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    5 thành một thành viên của một
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    62 mới là tương thích nhị phân, tuy nhiên đối với một số ngôn ngữ (đặc biệt là Go), API của mã được tạo sẽ thay đổi theo những cách không tương thích. Vì lý do này, Google không thực hiện những thay đổi như vậy trong các API công khai của mình, như được ghi lại trong. Với cùng một cảnh báo về khả năng tương thích nguồn, việc di chuyển nhiều trường sang một
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    62 mới có thể an toàn nếu bạn chắc chắn rằng không có mã nào đặt nhiều trường cùng một lúc. Di chuyển các trường vào một
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    62 hiện có là không an toàn. Tương tự như vậy, việc thay đổi một trường duy nhất
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    62 thành trường
    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    5 hoặc phần mở rộng là an toàn

Trường không xác định

Các trường không xác định là dữ liệu được tuần tự hóa trong bộ đệm giao thức được định dạng tốt biểu thị các trường mà trình phân tích cú pháp không nhận ra. Ví dụ: khi một nhị phân cũ phân tích dữ liệu được gửi bởi một nhị phân mới với các trường mới, những trường mới đó trở thành các trường không xác định trong nhị phân cũ

Ban đầu, các thông báo proto3 luôn loại bỏ các trường không xác định trong quá trình phân tích cú pháp, nhưng trong phiên bản 3. 5, chúng tôi đã giới thiệu lại việc bảo tồn các trường không xác định để phù hợp với hành vi proto2. Trong phiên bản 3. 5 trở lên, các trường không xác định được giữ lại trong quá trình phân tích cú pháp và được đưa vào đầu ra được tuần tự hóa

Không tí nào

Loại thông báo

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67 cho phép bạn sử dụng thông báo dưới dạng các loại được nhúng mà không cần. độ nét nguyên thủy. Một
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67 chứa một thông báo được đánh số thứ tự tùy ý là
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
46, cùng với một URL hoạt động như một mã định danh duy nhất trên toàn cầu và phân giải thành loại của thông báo đó. Để sử dụng loại
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67, bạn cần phải
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
71

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
5

URL loại mặc định cho một loại thông báo nhất định là

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
72

Các triển khai ngôn ngữ khác nhau sẽ hỗ trợ người trợ giúp thư viện thời gian chạy để đóng gói và giải nén các giá trị

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67 theo cách an toàn về kiểu – ví dụ: trong Java, kiểu
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67 sẽ có các trình truy cập đặc biệt
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
75 và
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
76, trong khi ở C++ có các phương thức
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
77 và
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
78

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
6

Hiện tại các thư viện thời gian chạy để làm việc với các loại

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67 đang được phát triển

Nếu bạn đã quen thuộc với cú pháp proto2, thì

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67 có thể chứa các tin nhắn proto3 tùy ý, tương tự như các tin nhắn proto2 có thể cho phép

Một trong

Nếu bạn có một thư có nhiều trường và nơi tối đa một trường sẽ được đặt cùng lúc, bạn có thể thực thi hành vi này và tiết kiệm bộ nhớ bằng cách sử dụng tính năng một trong những

Một trong các trường giống như các trường thông thường ngoại trừ tất cả các trường trong một bộ nhớ dùng chung và nhiều nhất một trường có thể được đặt cùng một lúc. Đặt bất kỳ thành viên nào của oneof sẽ tự động xóa tất cả các thành viên khác. Bạn có thể kiểm tra xem giá trị nào trong một trong số được đặt (nếu có) bằng cách sử dụng phương pháp

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
81 hoặc
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
82 đặc biệt, tùy thuộc vào ngôn ngữ bạn đã chọn

Lưu ý rằng nếu nhiều giá trị được đặt, giá trị được đặt cuối cùng được xác định theo thứ tự trong proto sẽ ghi đè lên tất cả các giá trị trước đó

Sử dụng Oneof

Để xác định một trong số trong

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của bạn, bạn sử dụng từ khóa
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
62 theo sau là tên của một trong số bạn, trong trường hợp này là
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
85

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
7

Sau đó, bạn thêm các trường oneof của mình vào định nghĩa oneof. Bạn có thể thêm các trường thuộc bất kỳ loại nào, ngoại trừ trường

enum Corpus {
  CORPUS_UNSPECIFIED = 0;
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
  CORPUS_LOCAL = 4;
  CORPUS_NEWS = 5;
  CORPUS_PRODUCTS = 6;
  CORPUS_VIDEO = 7;
}
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Corpus corpus = 4;
}
9 và trường
enum Corpus {
  CORPUS_UNSPECIFIED = 0;
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
  CORPUS_LOCAL = 4;
  CORPUS_NEWS = 5;
  CORPUS_PRODUCTS = 6;
  CORPUS_VIDEO = 7;
}
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Corpus corpus = 4;
}
8

Trong mã được tạo của bạn, một trong các trường có cùng getters và setters như các trường thông thường. Bạn cũng có một phương pháp đặc biệt để kiểm tra xem giá trị nào (nếu có) trong oneof được đặt. Bạn có thể tìm hiểu thêm về API oneof cho ngôn ngữ bạn đã chọn trong tài liệu tham khảo API có liên quan

Một trong những tính năng

  • Đặt trường oneof sẽ tự động xóa tất cả các thành viên khác của oneof. Vì vậy, nếu bạn đặt một số trường, chỉ trường cuối cùng bạn đặt sẽ vẫn có giá trị

    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    8
  • Nếu trình phân tích cú pháp gặp nhiều thành viên của cùng một trong số trên dây, thì chỉ thành viên cuối cùng được nhìn thấy được sử dụng trong thông báo được phân tích cú pháp

  • Một trong số không thể là

    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    8

  • Reflection API hoạt động cho một trong các trường

  • Nếu bạn đặt trường oneof thành giá trị mặc định (chẳng hạn như đặt trường oneof int32 thành 0), "trường hợp" của trường oneof đó sẽ được đặt và giá trị sẽ được đánh số thứ tự trên dây

  • Nếu bạn đang sử dụng C++, hãy đảm bảo rằng mã của bạn không gây ra sự cố bộ nhớ. Mã mẫu sau đây sẽ gặp sự cố vì

    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    89 đã bị xóa bằng cách gọi phương thức
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    90

    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    9
  • Một lần nữa trong C++, nếu bạn

    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    91 hai tin nhắn với một trường hợp, mỗi tin nhắn sẽ kết thúc bằng một trường hợp của tin nhắn kia. trong ví dụ dưới đây,
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    92 sẽ có một
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    89 và
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    94 sẽ có một
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    95

    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    0

Vấn đề tương thích ngược

Hãy cẩn thận khi thêm hoặc xóa một trong các trường. Nếu kiểm tra giá trị của một trong số trả về

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
96/
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
97, điều đó có thể có nghĩa là một trong số đó chưa được đặt hoặc nó đã được đặt thành một trường trong một phiên bản khác của một trong số đó. Không có cách nào để phân biệt sự khác biệt, vì không có cách nào để biết liệu một trường chưa biết trên dây có phải là thành viên của một trường không

Vấn đề sử dụng lại thẻ

  • Di chuyển các trường vào hoặc ra khỏi một trong các trường. Bạn có thể mất một số thông tin của mình (một số trường sẽ bị xóa) sau khi thư được đánh số thứ tự và phân tích cú pháp. Tuy nhiên, bạn có thể di chuyển một trường đơn lẻ sang một trường mới một cách an toàn và có thể di chuyển nhiều trường nếu biết rằng chỉ có một trường được đặt. Xem để biết thêm chi tiết
  • Xóa một trường một trong hai và thêm lại trường đó. Thao tác này có thể xóa trường oneof hiện được đặt của bạn sau khi thư được đánh số thứ tự và phân tích cú pháp
  • Tách hoặc hợp nhất một trong hai. Điều này có các vấn đề tương tự như di chuyển các trường thông thường

bản đồ

Nếu bạn muốn tạo bản đồ kết hợp như một phần của định nghĩa dữ liệu của mình, bộ đệm giao thức cung cấp cú pháp phím tắt tiện dụng

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
1

trong đó

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
98 có thể là bất kỳ loại tích phân hoặc chuỗi nào (vì vậy, bất kỳ loại nào ngoại trừ các loại dấu phẩy động và
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
46). Lưu ý rằng enum không phải là một
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
98 hợp lệ.
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
01 có thể là bất kỳ loại nào ngoại trừ bản đồ khác

Vì vậy, ví dụ: nếu bạn muốn tạo bản đồ các dự án trong đó mỗi thông báo

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
02 được liên kết với một khóa chuỗi, bạn có thể xác định nó như sau

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
2
  • Các trường bản đồ không thể là
    enum Corpus {
      CORPUS_UNSPECIFIED = 0;
      CORPUS_UNIVERSAL = 1;
      CORPUS_WEB = 2;
      CORPUS_IMAGES = 3;
      CORPUS_LOCAL = 4;
      CORPUS_NEWS = 5;
      CORPUS_PRODUCTS = 6;
      CORPUS_VIDEO = 7;
    }
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
      Corpus corpus = 4;
    }
    
    8
  • Thứ tự định dạng dây và thứ tự lặp lại bản đồ của các giá trị bản đồ không được xác định, vì vậy bạn không thể dựa vào các mục bản đồ của mình theo một thứ tự cụ thể
  • Khi tạo định dạng văn bản cho
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3, bản đồ được sắp xếp theo khóa. Các phím số được sắp xếp theo số
  • Khi phân tích cú pháp từ dây hoặc khi hợp nhất, nếu có các khóa bản đồ trùng lặp, khóa cuối cùng nhìn thấy sẽ được sử dụng. Khi phân tích cú pháp bản đồ từ định dạng văn bản, quá trình phân tích cú pháp có thể thất bại nếu có các khóa trùng lặp
  • Nếu bạn cung cấp khóa nhưng không cung cấp giá trị cho trường bản đồ, hành vi khi trường được đánh số thứ tự sẽ phụ thuộc vào ngôn ngữ. Trong C++, Java, Kotlin và Python, giá trị mặc định cho loại được tuần tự hóa, trong khi ở các ngôn ngữ khác, không có gì được tuần tự hóa

API bản đồ được tạo hiện có sẵn cho tất cả các ngôn ngữ được hỗ trợ proto3. Bạn có thể tìm hiểu thêm về API bản đồ cho ngôn ngữ bạn đã chọn trong tài liệu tham khảo API có liên quan

Tương thích ngược

Cú pháp bản đồ tương đương với cú pháp sau trên dây, vì vậy việc triển khai bộ đệm giao thức không hỗ trợ bản đồ vẫn có thể xử lý dữ liệu của bạn

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
3

Mọi triển khai bộ đệm giao thức hỗ trợ bản đồ đều phải tạo và chấp nhận dữ liệu có thể được chấp nhận theo định nghĩa trên

gói

Bạn có thể thêm một mã xác định

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
05 tùy chọn vào tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 để tránh xung đột tên giữa các loại thông báo giao thức

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
4

Sau đó, bạn có thể sử dụng trình xác định gói khi xác định các trường thuộc loại thông báo của mình

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
5

Cách trình xác định gói ảnh hưởng đến mã được tạo tùy thuộc vào ngôn ngữ bạn đã chọn

  • Trong C++, các lớp được tạo được bao bọc bên trong một không gian tên C++. Ví dụ:
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    07 sẽ nằm trong không gian tên
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    08
  • Trong Java và Kotlin, gói được sử dụng làm gói Java, trừ khi bạn cung cấp rõ ràng một
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    09 trong tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 của mình
  • Trong Python, chỉ thị gói bị bỏ qua, vì các mô-đun Python được tổ chức theo vị trí của chúng trong hệ thống tệp
  • Trong Go, gói được sử dụng làm tên gói Go, trừ khi bạn cung cấp rõ ràng một ____28_______11 trong tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 của mình
  • Trong Ruby, các lớp được tạo ra được bao bọc bên trong các không gian tên Ruby lồng nhau, được chuyển đổi sang kiểu viết hoa Ruby bắt buộc (chữ cái đầu tiên được viết hoa; nếu ký tự đầu tiên không phải là một chữ cái, thì _____28_______13 được thêm vào trước). Ví dụ:
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    07 sẽ nằm trong không gian tên
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    15
  • Trong C#, gói được sử dụng làm không gian tên sau khi chuyển đổi sang PascalCase, trừ khi bạn cung cấp rõ ràng một
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    16 trong tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 của mình. Ví dụ:
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    07 sẽ nằm trong không gian tên
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    19

Độ phân giải gói và tên

Nhập độ phân giải tên trong ngôn ngữ bộ đệm giao thức hoạt động như C++. đầu tiên, phạm vi trong cùng được tìm kiếm, sau đó là phạm vi trong cùng tiếp theo, v.v., với mỗi gói được coi là "bên trong" đối với gói mẹ của nó. Một sự dẫn đầu '. ' (ví dụ:

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
20) có nghĩa là bắt đầu từ phạm vi ngoài cùng thay vì

Trình biên dịch bộ đệm giao thức giải quyết tất cả các tên loại bằng cách phân tích cú pháp các tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 đã nhập. Trình tạo mã cho mỗi ngôn ngữ biết cách đề cập đến từng loại trong ngôn ngữ đó, ngay cả khi ngôn ngữ đó có các quy tắc phạm vi khác nhau

Xác định dịch vụ

Nếu bạn muốn sử dụng các loại thông báo của mình với hệ thống RPC (Gọi thủ tục từ xa), bạn có thể xác định giao diện dịch vụ RPC trong tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 và trình biên dịch bộ đệm giao thức sẽ tạo mã giao diện dịch vụ và sơ khai bằng ngôn ngữ bạn đã chọn. Vì vậy, ví dụ: nếu bạn muốn xác định một dịch vụ RPC bằng một phương thức lấy
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
7 của bạn và trả về một
enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 1;
  EAA_FINISHED = 2;
}
enum EnumNotAllowingAlias {
  ENAA_UNSPECIFIED = 0;
  ENAA_STARTED = 1;
  // ENAA_RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
  ENAA_FINISHED = 2;
}
4, bạn có thể xác định dịch vụ đó trong tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của mình như sau

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
6

Hệ thống RPC đơn giản nhất để sử dụng với bộ đệm giao thức là gRPC. một hệ thống RPC nguồn mở trung lập về ngôn ngữ và nền tảng được phát triển tại Google. gRPC hoạt động đặc biệt hiệu quả với bộ đệm giao thức và cho phép bạn tạo mã RPC có liên quan trực tiếp từ tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của mình bằng plugin trình biên dịch bộ đệm giao thức đặc biệt

Nếu bạn không muốn sử dụng gRPC, bạn cũng có thể sử dụng bộ đệm giao thức với triển khai RPC của riêng mình. Bạn có thể tìm hiểu thêm về điều này trong

Ngoài ra còn có một số dự án của bên thứ ba đang diễn ra để phát triển triển khai RPC cho Bộ đệm giao thức. Để biết danh sách các liên kết đến các dự án mà chúng tôi biết, hãy xem trang wiki tiện ích bổ sung của bên thứ ba

Ánh xạ JSON

Proto3 hỗ trợ mã hóa chuẩn trong JSON, giúp chia sẻ dữ liệu giữa các hệ thống dễ dàng hơn. Mã hóa được mô tả trên cơ sở từng loại trong bảng bên dưới

Khi phân tích cú pháp dữ liệu được mã hóa JSON vào bộ đệm giao thức, nếu một giá trị bị thiếu hoặc nếu giá trị của nó là

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
27, thì nó sẽ được hiểu là giá trị tương ứng

Khi tạo đầu ra được mã hóa JSON từ bộ đệm giao thức, nếu trường protobuf có giá trị mặc định và nếu trường không hỗ trợ sự hiện diện của trường, thì nó sẽ bị bỏ qua khỏi đầu ra theo mặc định. Việc triển khai có thể cung cấp các tùy chọn để bao gồm các trường có giá trị mặc định trong đầu ra

Trường proto3 được xác định bằng từ khóa

enum Corpus {
  CORPUS_UNSPECIFIED = 0;
  CORPUS_UNIVERSAL = 1;
  CORPUS_WEB = 2;
  CORPUS_IMAGES = 3;
  CORPUS_LOCAL = 4;
  CORPUS_NEWS = 5;
  CORPUS_PRODUCTS = 6;
  CORPUS_VIDEO = 7;
}
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Corpus corpus = 4;
}
5 hỗ trợ sự hiện diện của trường. Các trường có một bộ giá trị và sự hiện diện của trường hỗ trợ đó luôn bao gồm giá trị trường trong đầu ra được mã hóa JSON, ngay cả khi đó là giá trị mặc định

proto3JSONJSON exampleNotesmessageobject
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
29Generates JSON objects. Message field names are mapped to lowerCamelCase and become JSON object keys. If the
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
30 field option is specified, the specified value will be used as the key instead. Parsers accept both the lowerCamelCase name (or the one specified by the
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
30 option) and the original proto field name.
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
27 is an accepted value for all field types and treated as the default value of the corresponding field type.enumstring
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
33The name of the enum value as specified in proto is used. Parsers accept both enum names and integer values.mapobject
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
34All keys are converted to strings.repeated Varray
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
35
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
27 is accepted as the empty list
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
37.booltrue, false
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
38stringstring
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
39bytesbase64 string
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
40JSON value will be the data encoded as a string using standard base64 encoding with paddings. Either standard or URL-safe base64 encoding with/without paddings are accepted.int32, fixed32, uint32number
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
41JSON value will be a decimal number. Either numbers or strings are accepted.int64, fixed64, uint64string
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
42JSON value will be a decimal string. Either numbers or strings are accepted.float, doublenumber
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
43JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity". Either numbers or strings are accepted. Exponent notation is also accepted. -0 is considered equivalent to 0.Any
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
44
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
45If the
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
67 contains a value that has a special JSON mapping, it will be converted as follows:
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
47. Otherwise, the value will be converted into a JSON object, and the
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
48 field will be inserted to indicate the actual data type.Timestampstring
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
49Uses RFC 3339, where generated output will always be Z-normalized and uses 0, 3, 6 or 9 fractional digits. Offsets other than "Z" are also accepted.Durationstring
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
50Generated output always contains 0, 3, 6, or 9 fractional digits, depending on required precision, followed by the suffix "s". Accepted are any fractional digits (also none) as long as they fit into nano-seconds precision and the suffix "s" is required.Struct
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
44
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
52Any JSON object. See
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
53.Wrapper typesvarious types
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
54Wrappers use the same representation in JSON as the wrapped primitive type, except that
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
27 is allowed and preserved during data conversion and transfer.FieldMaskstring
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
56See
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
57.ListValuearray
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
58ValuevalueAny JSON value. Check for details.NullValuenullJSON nullEmptyobject
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
59An empty JSON object

tùy chọn JSON

Việc triển khai JSON proto3 có thể cung cấp các tùy chọn sau

  • Phát ra các trường có giá trị mặc định. Các trường có giá trị mặc định được bỏ qua theo mặc định trong đầu ra JSON của proto3. Việc triển khai có thể cung cấp tùy chọn ghi đè hành vi này và các trường đầu ra bằng các giá trị mặc định của chúng
  • Bỏ qua các trường không xác định. Trình phân tích cú pháp JSON của Proto3 sẽ từ chối các trường không xác định theo mặc định nhưng có thể cung cấp tùy chọn bỏ qua các trường không xác định khi phân tích cú pháp
  • Sử dụng tên trường proto thay vì tên LowerCamelCase. Theo mặc định, máy in JSON proto3 sẽ chuyển đổi tên trường thành LowerCamelCase và sử dụng tên đó làm tên JSON. Thay vào đó, việc triển khai có thể cung cấp tùy chọn sử dụng tên trường proto làm tên JSON. Trình phân tích cú pháp JSON Proto3 được yêu cầu chấp nhận cả tên LowerCamelCase đã chuyển đổi và tên trường proto
  • Phát ra các giá trị enum dưới dạng số nguyên thay vì chuỗi. Tên của một giá trị enum được sử dụng theo mặc định trong đầu ra JSON. Một tùy chọn có thể được cung cấp để sử dụng giá trị số của giá trị enum thay thế

Tùy chọn

Các khai báo riêng lẻ trong tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 có thể được chú thích bằng một số tùy chọn. Các tùy chọn không thay đổi ý nghĩa tổng thể của một tuyên bố, nhưng có thể ảnh hưởng đến cách nó được xử lý trong một ngữ cảnh cụ thể. Danh sách đầy đủ các tùy chọn có sẵn được xác định trong
/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
61

Một số tùy chọn là tùy chọn cấp tệp, nghĩa là chúng phải được viết ở phạm vi cấp cao nhất, không nằm trong bất kỳ thông báo, enum hoặc định nghĩa dịch vụ nào. Một số tùy chọn là tùy chọn cấp thông báo, nghĩa là chúng phải được viết bên trong định nghĩa thông báo. Một số tùy chọn là tùy chọn cấp trường, nghĩa là chúng phải được viết bên trong định nghĩa trường. Các tùy chọn cũng có thể được viết trên các loại enum, giá trị enum, một trong các trường, loại dịch vụ và phương thức dịch vụ;

Dưới đây là một số tùy chọn được sử dụng phổ biến nhất

  • /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    62 (tùy chọn tệp). Gói bạn muốn sử dụng cho các lớp Java/Kotlin đã tạo của mình. Nếu không có tùy chọn
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    62 rõ ràng nào được đưa ra trong tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3, thì theo mặc định, gói proto (được chỉ định bằng từ khóa "gói" trong tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3) sẽ được sử dụng. Tuy nhiên, các gói proto thường không tạo ra các gói Java tốt vì các gói proto không được mong đợi bắt đầu bằng các tên miền đảo ngược. Nếu không tạo mã Java hoặc Kotlin, tùy chọn này không có tác dụng

    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    7
  • /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    66 (tùy chọn tệp). Tên lớp (và do đó là tên tệp) cho lớp Java trình bao bọc mà bạn muốn tạo. Nếu không có
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    66 rõ ràng nào được chỉ định trong tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3, tên lớp sẽ được xây dựng bằng cách chuyển đổi tên tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 thành trường hợp lạc đà (do đó,
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    70 trở thành
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    71). Nếu tùy chọn
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    72 bị tắt, thì tất cả các lớp/enum/vv khác. được tạo cho tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 sẽ được tạo trong lớp Java bao bọc bên ngoài này dưới dạng các lớp/enum/vv lồng nhau. Nếu không tạo mã Java, tùy chọn này không có tác dụng

    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    8
  • /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    72 (tùy chọn tệp). Nếu sai, chỉ một tệp
    enum Foo {
      reserved 2, 15, 9 to 11, 40 to max;
      reserved "FOO", "BAR";
    }
    
    7 duy nhất sẽ được tạo cho tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 này và tất cả các lớp/enum/vv của Java. được tạo cho các thông báo, dịch vụ và bảng liệt kê cấp cao nhất sẽ được lồng vào bên trong một lớp bên ngoài (xem
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    66). Nếu đúng, các tệp
    enum Foo {
      reserved 2, 15, 9 to 11, 40 to max;
      reserved "FOO", "BAR";
    }
    
    7 riêng biệt sẽ được tạo cho từng lớp Java/enum/v.v. được tạo cho các thông báo, dịch vụ và bảng liệt kê cấp cao nhất và lớp Java trình bao bọc được tạo cho tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 này sẽ không chứa bất kỳ lớp/enum/v.v lồng nhau nào. Đây là một tùy chọn Boolean mặc định là
    import "myproject/other_protos.proto";
    
    0. Nếu không tạo mã Java, tùy chọn này không có tác dụng

    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    9
  • /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    81 (tùy chọn tệp). Có thể đặt thành
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    82,
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    83 hoặc
    /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    84. Điều này ảnh hưởng đến trình tạo mã C++ và Java (và có thể là trình tạo của bên thứ ba) theo các cách sau

    • /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      82 (mặc định). Trình biên dịch bộ đệm giao thức sẽ tạo mã để tuần tự hóa, phân tích cú pháp và thực hiện các thao tác phổ biến khác trên các loại thông báo của bạn. Mã này được tối ưu hóa cao
    • /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      83. Trình biên dịch bộ đệm giao thức sẽ tạo ra các lớp tối thiểu và sẽ dựa vào mã được chia sẻ, dựa trên sự phản chiếu để thực hiện tuần tự hóa, phân tích cú pháp và nhiều hoạt động khác. Do đó, mã được tạo sẽ nhỏ hơn nhiều so với
      /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      82, nhưng các thao tác sẽ chậm hơn. Các lớp sẽ vẫn triển khai chính xác API công khai giống như chúng thực hiện ở chế độ
      /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      82. Chế độ này hữu ích nhất trong các ứng dụng chứa một số lượng rất lớn
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      3 tệp và không cần tất cả chúng phải nhanh chóng mặt
    • /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      84. Trình biên dịch bộ đệm giao thức sẽ tạo ra các lớp chỉ phụ thuộc vào thư viện thời gian chạy "lite" (
      /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      91 thay vì
      /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      92). Thời gian chạy bản rút gọn nhỏ hơn nhiều so với thư viện đầy đủ (khoảng nhỏ hơn theo thứ tự cường độ) nhưng bỏ qua một số tính năng nhất định như bộ mô tả và phản chiếu. Điều này đặc biệt hữu ích cho các ứng dụng chạy trên các nền tảng hạn chế như điện thoại di động. Trình biên dịch sẽ vẫn tạo ra các triển khai nhanh của tất cả các phương thức như trong chế độ
      /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      82. Các lớp được tạo sẽ chỉ triển khai giao diện
      /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      94 trong mỗi ngôn ngữ, giao diện này chỉ cung cấp một tập hợp con các phương thức của giao diện
      /* SearchRequest represents a search query, with pagination options to
       * indicate which results to include in the response. */
      
      message SearchRequest {
        string query = 1;
        int32 page_number = 2;  // Which page number do we want?
        int32 result_per_page = 3;  // Number of results to return per page.
      }
      
      95 đầy đủ
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    0
  • /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    96 (tùy chọn tệp). Cho phép phân bổ đấu trường cho mã được tạo bằng C++

  • /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    97 (tùy chọn tệp). Đặt tiền tố lớp Objective-C được thêm vào trước tất cả các lớp và enum được tạo bởi Objective-C từ điều này. nguyên thủy. không có mặc định. Bạn nên sử dụng các tiền tố có từ 3-5 ký tự viết hoa như. Lưu ý rằng tất cả 2 tiền tố chữ cái đều được bảo lưu bởi Apple

  • /* SearchRequest represents a search query, with pagination options to
     * indicate which results to include in the response. */
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;  // Which page number do we want?
      int32 result_per_page = 3;  // Number of results to return per page.
    }
    
    98 (tùy chọn trường). Nếu được đặt thành
    // new.proto
    // All definitions are moved here
    
    7, cho biết rằng trường này không được dùng nữa và không nên được sử dụng bởi mã mới. Trong hầu hết các ngôn ngữ, điều này không có tác dụng thực sự. Trong Java, điều này trở thành một chú thích
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    00. Đối với C++, clang-tidy sẽ tạo cảnh báo bất cứ khi nào các trường không dùng nữa được sử dụng. Trong tương lai, các trình tạo mã dành riêng cho ngôn ngữ khác có thể tạo chú thích không dùng nữa trên trình truy cập của trường, điều này sẽ khiến cảnh báo được phát ra khi biên dịch mã cố gắng sử dụng trường. Nếu trường không được sử dụng bởi bất kỳ ai và bạn muốn ngăn người dùng mới sử dụng trường đó, hãy xem xét thay thế khai báo trường bằng một câu lệnh

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    1

Tùy chọn tùy chỉnh

Bộ đệm giao thức cũng cho phép bạn xác định và sử dụng các tùy chọn của riêng mình. Đây là một tính năng nâng cao mà hầu hết mọi người không cần. Nếu bạn nghĩ rằng bạn cần tạo các tùy chọn của riêng mình, hãy xem phần để biết chi tiết. Lưu ý rằng việc tạo các tùy chọn tùy chỉnh sử dụng , chỉ được phép cho các tùy chọn tùy chỉnh trong proto3

Tạo các lớp học của bạn

Để tạo mã Java, Kotlin, Python, C++, Go, Ruby, Objective-C hoặc C#, bạn cần làm việc với các loại thông báo được xác định trong tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3, bạn cần chạy trình biên dịch bộ đệm giao thức ________0____02 trên
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3. Nếu bạn chưa cài đặt trình biên dịch, hãy tải xuống gói và làm theo hướng dẫn trong README. Đối với Go, bạn cũng cần cài đặt plugin tạo mã đặc biệt cho trình biên dịch. bạn có thể tìm hướng dẫn này và hướng dẫn cài đặt trong kho lưu trữ golang/protobuf trên GitHub

Trình biên dịch giao thức được gọi như sau

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
2
  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    04 chỉ định một thư mục để tìm các tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 khi giải quyết các chỉ thị của
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    06. Nếu bỏ qua, thư mục hiện tại được sử dụng. Nhiều thư mục nhập có thể được chỉ định bằng cách chuyển tùy chọn
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    32 nhiều lần; .
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    08 có thể được dùng dưới dạng rút gọn của
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    message SearchResponse {
     ...
    }
    
    32
  • Bạn có thể cung cấp một hoặc nhiều chỉ thị đầu ra

    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10 tạo mã C++ trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã được tạo bởi C++ để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      12 tạo mã Java trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã được tạo bởi Java để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      14 tạo mã Kotlin bổ sung trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã được tạo bởi Kotlin để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      16 tạo mã Python trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tham chiếu mã do Python tạo để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      18 tạo mã Go trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã do Go tạo để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      20 tạo mã Ruby trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã được tạo bởi Ruby để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      22 tạo mã Objective-C trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã được tạo bởi Objective-C để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      24 tạo mã C# trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã được tạo C# để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      26 tạo mã PHP trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      11. Xem tài liệu tham khảo mã được tạo bởi PHP để biết thêm

    Để thuận tiện hơn, nếu

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    11 kết thúc bằng
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    29 hoặc
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    30, trình biên dịch sẽ ghi đầu ra vào một tệp lưu trữ định dạng ZIP duy nhất với tên đã cho.
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    30 đầu ra cũng sẽ được cung cấp một tệp kê khai theo yêu cầu của đặc tả Java JAR. Lưu ý rằng nếu kho lưu trữ đầu ra đã tồn tại, nó sẽ bị ghi đè;

  • Bạn phải cung cấp một hoặc nhiều tệp

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 làm đầu vào. Có thể chỉ định nhiều tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 cùng một lúc. Mặc dù các tệp được đặt tên liên quan đến thư mục hiện tại, nhưng mỗi tệp phải nằm trong một trong các
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    04 để trình biên dịch có thể xác định tên chính tắc của nó

Vị trí tập tin

Không muốn đặt các tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 trong cùng thư mục với các nguồn ngôn ngữ khác. Xem xét việc tạo một gói con
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
36 cho các tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3, bên dưới gói gốc cho dự án của bạn

Vị trí phải là ngôn ngữ bất khả tri

Khi làm việc với mã Java, thật tiện lợi khi đặt các tệp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 có liên quan trong cùng thư mục với nguồn Java. Tuy nhiên, nếu bất kỳ mã không phải Java nào sử dụng cùng một protos, thì tiền tố đường dẫn sẽ không còn ý nghĩa nữa. Vì vậy, nói chung, hãy đặt các protos trong một thư mục liên quan đến ngôn ngữ bất khả tri, chẳng hạn như
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
39

Ngoại lệ đối với quy tắc này là khi rõ ràng rằng các proto sẽ chỉ được sử dụng trong ngữ cảnh Java, chẳng hạn như để thử nghiệm