所有的序列化操作都会在SerializeFieldWithCachedSizes这个函数里进行。根据不同的类型调用对应的序列化函数,例如对于string类型
case FieldDescriptor::TYPE_STRING: {
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE, field->name().c_str());
WireFormatLite::WriteString(field->number(), value, output);
break;
而对于bytes类型
case FieldDescriptor::TYPE_BYTES: {
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
WireFormatLite::WriteBytes(field->number(), value, output);
break;
可以看到在序列化时主要有两点区别:
string类型调用了VerifyUTF8StringNamedField函数
序列化函数不同:WriteString vs WriteBytes
出于效率,我们应当在确定字段编码格式后直接使用bytes,减少utf8编码的判断,效率上会有提高。
注意以上代码在pb2.6下,2.4不会输出field_name。
据了解java接口上有一定的区别,分别对应String以及ByteString。