Nhập số phức c++

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 tin nhắn

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 là loại vô hướng. 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 kiểu liệt kê 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 các số trường trong phạm vi từ 1 đến 15 cần 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 Mã hóa bộ đệm giao thức). 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 các 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 đã đặt trước nào

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 Sự 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 giá trị đã được đặt rõ ràng chưa. 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 Bản đồ để 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
91 theo mặc định. Bạn có thể tìm hiểu thêm về mã hóa
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
91 trong Mã hóa bộ đệm giao thức

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ư
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
94 của mình, bạn có thể thêm nó vào cùng một
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3

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

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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
97 và
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
98 kiểu C/C++

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

Trường dành riêng

Nếu bạn cập nhật một 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ó, những 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à
syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
00. 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 tên trường và số trường trong cùng một câu lệnh

syntax = "proto3";

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

Đ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ình biên dịch bộ đệm giao thức 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 mà bạn đã mô tả trong tệp, bao gồm nhận và đặt giá trị trường, sắp xếp thứ tự các thông báo của bạn thành một

  • Đối với C++, trình biên dịch tạo tệp
    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    04 và
    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    05 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 tệp
    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    07 với một lớp cho từng loại thông báo, cũng như một lớp
    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    08 đặ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
    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    09 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 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    21 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    22 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    23 và
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    24 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    26 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    28 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 Typedoubledoubledoublefloatfloat64Floatdoublefloatdoublefloatfloatfloatfloatfloat32Floatfloatfloatdoubleint32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32Fixnum or Bignum (as required)intintegerintint64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/long[4]int64Bignumlonginteger/string[6]Int64uint32Uses variable-length encoding.uint32int[2]int/long[4]uint32Fixnum or Bignum (as required)uintintegerintuint64Uses variable-length encoding.uint64long[2]int/long[4]uint64Bignumulonginteger/string[6]Int64sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32Fixnum or Bignum (as required)intintegerintsint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/long[4]int64Bignumlonginteger/string[6]Int64fixed32Always four bytes. More efficient than uint32 if values are often greater than 228.uint32int[2]int/long[4]uint32Fixnum or Bignum (as required)uintintegerintfixed64Always eight bytes. More efficient than uint64 if values are often greater than 256.uint64long[2]int/long[4]uint64Bignumulonginteger/string[6]Int64sfixed32Always four bytes.int32intintint32Fixnum or Bignum (as required)intintegerintsfixed64Always eight bytes.int64longint/long[4]int64Bignumlonginteger/string[6]Int64boolboolbooleanboolboolTrueClass/FalseClassboolbooleanboolstringA string must always contain UTF-8 encoded or 7-bit ASCII text, and cannot be longer than 232.stringStringstr/unicode[5]stringString (UTF-8)stringstringStringbytesMay contain any arbitrary sequence of bytes no longer than 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 enum, giá trị mặc định là giá trị enum được xác định đầu tiên, giá trị này phải bằng 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, một khi 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 giá trị boolean đã được đặt thành

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
10) 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
10 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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
12 cho mỗi
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
7, trong đó kho văn bản có thể là
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
14,
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
15,
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
16,
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
17,
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
18,
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
19 hoặc
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
10. Bạn có thể làm điều này rất đơn giản bằng cách thêm một
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 được gọi là
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
13 với tất cả các giá trị có thể và một trường loại
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
13

________số 8

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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
13 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ó giá trị bằng 0 để chúng tôi có thể sử dụng 0 làm giá trị mặc định 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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
16 thành
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
17, 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

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

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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 bên trong định nghĩa thông báo, như trong ví dụ trên hoặc bên ngoài – những
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 đượ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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
403

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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11, mã được tạo ra sẽ có một
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 tương ứng cho Java, Kotlin hoặc C++ hoặc một lớp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
407 đặc biệt 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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
11 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 cập nhật một loại enum bằng cách loại bỏ 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 đã xóa của bạn là
syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
00. 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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
411

syntax = "proto3";

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

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

syntax = "proto3";

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

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 thông báo

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
413 trong mỗi thông báo
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
94 – để làm điều này, bạn có thể xác định loại thông báo
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
413 trong cùng một
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 và sau đó chỉ định trường loại
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
413 trong
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
94

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

Nhập định nghĩa

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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
413 được xác định trong cùng một tệp với
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
94 – 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 các đị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 các đị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

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

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 trang 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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
428

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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
428 có thể được dựa vào quá độ bởi bất kỳ mã nào nhập proto có chứa câu lệnh
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
428. Ví dụ

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

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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
431/
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
432. 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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
432 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 lần 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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
413 được xác định bên trong thông báo
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
94

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

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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
436

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

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

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

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 giá trị mặc định cho các phần tử này để mã mới có thể tương tác đúng cách với các thông báo do mã cũ tạo ra. 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 Trường không xác định để 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 riêng số trườ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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    438,
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    439,
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    440,
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    441 và
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    442 đề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 xuôi hoặc ngược. 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    443 và
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    444 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    445 và
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    446 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    446 nếu các byte chứa phiên bản được mã hóa của tin nhắn
  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    448 tương thích với
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    449 và
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    450 với
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    451
  • Đối với các trường ________ 2445, ________ 2446 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 sắp xếp theo thứ tự ở định dạng đóng gói, định dạng này 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
  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    11 tương thích với ________ 2438, ________ 2439, ________ 2440 và ________ 2441 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
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    11 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
  • Thay đổi một trường hoặc phần 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    462 mới là an toàn và tương thích nhị phân. Di chuyển nhiều trường sang một
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    462 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 bất kỳ trường nào vào một
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    462 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    462 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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467 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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467 chứa một thông báo được đánh số thứ tự tùy ý là
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
446, 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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467, bạn cần nhập
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
471

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

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

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

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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467 theo cách an toàn về kiểu – ví dụ: trong Java, loại
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467 sẽ có các bộ truy cập đặc biệt
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
475 và
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
476, trong khi ở C++ có các phương thức
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
477 và
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
478

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

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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467 đang được phát triển

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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467 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 các tiện ích mở rộng

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 phương pháp

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
481 hoặc
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
482 đặ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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
462 theo sau là tên của một trong số bạn, trong trường hợp này là
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
485

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

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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    48
  • 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    489 đã bị xóa bằng cách gọi phương thức
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    490

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    49
  • Một lần nữa trong C++, nếu bạn

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    491 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    492 sẽ có một
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    489 và
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    494 sẽ có một
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    495

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

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 Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
496/
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
497, đ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
  • 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

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

trong đó

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
498 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 vô hướng nào ngoại trừ các loại dấu phẩy động và
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
446). Lưu ý rằng enum không phải là một
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
498 hợp lệ.
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
801 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

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
802 được liên kết với một khóa chuỗi, bạn có thể xác định nó như sau

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
82
  • 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, do đó, 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

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

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 trình xác định

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
805 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

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

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

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

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ụ:
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    807 sẽ nằm trong không gian tên
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    808
  • Trong Java và Kotlin, gói được sử dụng làm gói Java, trừ khi bạn cung cấp một cách rõ ràng một
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    809 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
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    811 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 được bao bọc bên trong các không gian tên ruby ​​lồng nhau, được chuyển đổi thành phong cách viết hoa ruby ​​cần thiết (chữ cái đầu tiên được viết hoa; nếu nhân vật đầu tiên không phải là một chữ cái,
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    813 được chuẩn bị). Ví dụ:
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    807 sẽ nằm trong không gian tên
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    815
  • 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
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    816 trong tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 của mình. Ví dụ:
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    807 sẽ nằm trong không gian tên
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    819

Độ 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ụ:

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
820) 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
94, bạn có thể xác định nó trong tệp
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
3 của mình như sau

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

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 Hướng dẫn ngôn ngữ Proto2

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

Nếu một giá trị bị thiếu trong dữ liệu được mã hóa JSON hoặc nếu giá trị của nó là

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
827, thì giá trị đó sẽ được hiểu là giá trị mặc định phù hợp khi được phân tích cú pháp vào bộ đệm giao thức. Nếu một trường có giá trị mặc định trong bộ đệm giao thức, nó sẽ được bỏ qua trong dữ liệu được mã hóa JSON theo mặc định để tiết kiệm dung lượng. Việc triển khai có thể cung cấp các tùy chọn để phát ra các trường có giá trị mặc định trong đầu ra được mã hóa JSON

proto3JSONJSON exampleNotesmessageobject
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
828Generates JSON objects. Message field names are mapped to lowerCamelCase and become JSON object keys. If the
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
829 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
829 option) and the original proto field name.
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
827 is an accepted value for all field types and treated as the default value of the corresponding field type.enumstring
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
832The name of the enum value as specified in proto is used. Parsers accept both enum names and integer values.mapobject
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
833All keys are converted to strings.repeated Varray
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
834
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
827 is accepted as the empty list
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
836.booltrue, false
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
837stringstring
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
838bytesbase64 string
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
839JSON 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
840JSON value will be a decimal number. Either numbers or strings are accepted.int64, fixed64, uint64string
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
841JSON value will be a decimal string. Either numbers or strings are accepted.float, doublenumber
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
842JSON 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
843
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
844If the
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
467 contains a value that has a special JSON mapping, it will be converted as follows:
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
846. Otherwise, the value will be converted into a JSON object, and the
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
847 field will be inserted to indicate the actual data type.Timestampstring
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
848Uses 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
849Generated 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
843
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
851Any JSON object. See
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
852.Wrapper typesvarious types
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
853Wrappers use the same representation in JSON as the wrapped primitive type, except that
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
827 is allowed and preserved during data conversion and transfer.FieldMaskstring
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
855See
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
856.ListValuearray
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
857ValuevalueAny JSON value. Check google.protobuf.Value for details.NullValuenullJSON nullEmptyobject
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
858An 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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
860

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

  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    861 (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
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    861 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

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    87
  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    865 (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ó
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    865 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 đó,
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    869 trở thành
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    870). Nếu tùy chọn
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    871 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 trình bao bọc bên ngoài này dưới dạng các lớp/enums/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

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    88
  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    871 (tùy chọn tệp). Nếu sai, chỉ một tệp
    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    07 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
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    865). Nếu đúng, các tệp
    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }
    
    07 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à
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    10. Nếu không tạo mã Java, tùy chọn này không có tác dụng

    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    89
  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    880 (tùy chọn tệp). Có thể đặt thành
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    881,
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    882 hoặc
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    883. Đ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

    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      881 (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
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      882. 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ã dựa trên sự phản chiếu, được chia sẻ để 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
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      881, 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ế độ
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      881. 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 các tệp
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      3 và không cần tất cả chúng phải nhanh chóng mặt
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      883. Trình biên dịch bộ đệm giao thức sẽ tạo các lớp chỉ phụ thuộc vào thư viện thời gian chạy "lite" (
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      890 thay vì
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      891). 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ế độ
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      881. Các lớp được tạo sẽ chỉ triển khai giao diện
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      893 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
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      894 đầy đủ
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    0
  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    895 (tùy chọn tệp). Cho phép phân bổ đấu trường cho mã được tạo bằng C++

  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    896 (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 theo khuyến nghị của Apple. Lưu ý rằng tất cả 2 tiền tố chữ cái đều được bảo lưu bởi Apple

  • message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    897 (tùy chọn trường). Nếu được đặt thành
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    17, 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";
    }
    
    899. 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 tuyên bố dành riêng

    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 Hướng dẫn ngôn ngữ Proto2 để 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 các tiện ích mở rộ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
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
01 trên tệp
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";
    }
    
    03 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";
    }
    
    05. 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 Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    432 nhiều lần; .
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    07 có thể được dùng dưới dạng viết tắt của
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    432
  • 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";
      }
      
      09 tạo mã C++ trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. 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";
      }
      
      11 tạo mã Java trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. 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";
      }
      
      13 tạo mã Kotlin bổ sung trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. Xem tài liệu tham khảo mã do Kotlin tạo để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      15 tạo mã Python trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. Xem tham chiếu mã do Python tạo để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      17 tạo mã Go trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. 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";
      }
      
      19 tạo mã Ruby trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. Xem tài liệu tham khảo mã do Ruby tạo để biết thêm
    • message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      21 tạo mã Objective-C trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. 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";
      }
      
      23 tạo mã C# trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. 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";
      }
      
      25 tạo mã PHP trong
      message Foo {
        reserved 2, 15, 9 to 11;
        reserved "foo", "bar";
      }
      
      10. 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";
    }
    
    10 kết thúc bằng
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    28 hoặc
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    29, 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. Các đầu ra của
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    29 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. Nhiều tệp
    message Foo {
      reserved 2, 15, 9 to 11;
      reserved "foo", "bar";
    }
    
    3 có thể được chỉ định 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";
    }
    
    03 để 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";
}
35 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 bất khả tri về ngôn ngữ có liên quan, chẳng hạn như
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
38

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