1. 程式人生 > 實用技巧 >Protocol buffer時間處理(golang)

Protocol buffer時間處理(golang)

Protocol buffer

protocol buffer 是一種資料傳輸協議,比 Json、xml 等效率更高。

準確的說 pb 是傳輸協議,而後兩者是序列化協議。

序列化協議有兩個屬性:

  • 結構化程度(人類可讀性)
  • 壓縮程度(序列化後的資料大小)

同一個物件序列化後,以上兩個屬性基本上是此消彼長、不可兼得的。因為要想人類可讀就必須是字串,且需要加入如{}[],以及換行符等符號做輔助,必然資料不能很好地壓縮。

因此,pb 相對於 Json、XML 結構化很差,但是壓縮程度很高,所以傳輸效率高。只不過人類程式設計師不需要去閱讀序列化後的資料文字,其定義了.proto檔案後直接生成客戶端、服務端程式碼,程式設計師在兩端都只需要關心程式中的物件(序列化前的物件和已反序列化後的物件)。

關於變數的處理

protocol buffer 本身是有時間戳的支援的,與 golang 可以融洽地結合。

實際大部分程式設計對時間的處理只需要精確到秒,也可以簡略一點,直接使用 int32 或 int64 傳輸時間戳。

Timestamp

.proto檔案中使用google.protobuf.Timestamp型別定義時間:

syntax = "proto3";

package pb;

import public "google/protobuf/timestamp.proto";

message person{
  google.protobuf.Timestamp birthday = 1;
}

對應生成的 .pb.go 檔案中型別為*timestamp.Timestamp

type Person struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Birthday *timestamp.Timestamp `protobuf:"bytes,1,opt,name=birthday,proto3" json:"birthday,omitempty"`
}

其中,timestamp.Timestamp

的 message 型別定義如下

message Timestamp {
  // Represents seconds of UTC time since Unix epoch
  // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
  // 9999-12-31T23:59:59Z inclusive.
  int64 seconds = 1;

  // Non-negative fractions of a second at nanosecond resolution. Negative
  // second values with fractions must still have non-negative nanos values
  // that count forward in time. Must be from 0 to 999,999,999
  // inclusive.
  int32 nanos = 2;
}

go 語言 time.Time 型別與 timestamp.Timestamp互相轉換使用github.com/golang/protobuf/ptypes包下方法:

package pb

import (
	"fmt"
	"github.com/golang/protobuf/ptypes"
	"time"
)

func TimeStampFeature() {
	//Timestamp 轉 Time
	//獲取的是系統時區的時間戳
	pbTimestamp := ptypes.TimestampNow()
	//此方法預設 UTC 時區
	goTime, _ := ptypes.Timestamp(pbTimestamp)
	//設定為系統時區
	fmt.Println(goTime.Local())

	//Time 轉 Timestamp
	goTime2 := time.Now()
	pbTimestamp2, _ := ptypes.TimestampProto(goTime2)
	fmt.Println(pbTimestamp2)
}

輸出為:

=== RUN   TestTimeStampFeature
2020-10-26 14:10:48.69129 +0800 CST
seconds:1603692648  nanos:691445000
--- PASS: TestTimeStampFeature (0.00s)
PASS

秒級時間戳

若只時間處理只精確到秒,則不必使用 time.Timetimestamp.Timestamp來處理和傳輸時間戳,直接使用 int32int64來表示秒級時間戳,免去型別互相轉換。