青雲 SDK Go Version (兼容官方 SDK)

項目地址:

項目目標:

  • 基於 Protobuf-V3 語法維護規範, 便於升級和維護
  • 更完整的服務支持, 新服務第一時間提供支持
  • 更好用的編程接口

在線文檔:

接口規範:

配置文件

當前用戶的配置文件在 ${HOME}/.qingcloud/config.yaml, 內容如下:

# QingCloud services configuration

qy_access_key_id: 'ACCESS_KEY_ID'
qy_secret_access_key: 'SECRET_ACCESS_KEY'

host: 'api.qingcloud.com'
port: 443
protocol: 'https'
uri: '/iaas'
connection_retries: 3

json_disable_unknown_fields: false

# Valid log levels are "debug", "info", "warn", "error", and "fatal".
log_level: 'warn'

qy_access_key_idqy_secret_access_key 字段替換爲 API密鑰 中的內容.

其中 json_disable_unknown_fields 是新加的變量, 表示在JSON解碼時忽略 proto.Message 遇到未定義成員的錯誤.

快速入門

以下爲 hello.go 的內容:

package main

import (
	"fmt"
	"log"

	"github.com/chai2010/qingcloud-go/config"
	pb "github.com/chai2010/qingcloud-go/service"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
)

func main() {
	// 初始化 青雲 服務對象
	qcService, err := pb.Init(config.MustLoadUserConfig())
	if err != nil {
		log.Fatal(err)
	}

	// 返回 NIC 子服務, pek3a 爲 北京3區-A
	nicService, err := qcService.Nic("pek3a")
	if err != nil {
		log.Fatal(err)
	}

	// 列出所有網卡
	reply, err := nicService.DescribeNics(nil)
	if err != nil {
		log.Fatal(err)
	}

	// 原始返回的json數據
	// nicService.LastResponseBody

	// JSON 格式打印
	fmt.Println(jsonpbEncode(reply))
}

// pb轉json, 採用原始名稱, 不忽略空值
func jsonpbEncode(m proto.Message) string {
	jsonMarshaler := &jsonpb.Marshaler{
		OrigName:     true,
		EnumsAsInts:  true,
		EmitDefaults: true,
		Indent:       "  ",
	}
	s, err := jsonMarshaler.MarshalToString(m)
	if err != nil {
		log.Fatal(err)
	}
	return s
}

初始化子服務也可以用以下方式:

nicService := pb.NewNicService(config.MustLoadUserConfig(), "pek3a")

運行例子:

go run hello.go

更多例子.

文檔指南

使用青雲SDK一般是以下步驟:

  1. config 包構造一個配置對象, 裏面含有最重要的 API密鑰, 還包含日誌級別等信息.
  2. 基於配置對象調用 service 包的 Init 函數構造一個青雲主服務對象 qcService, 其中會根據配置文件設置日誌級別.
  3. 假設有一個 UserData 子服務, 那麼調用 qcService.UserData("pek3a") 方法將返回子服務對象, 其中參數是區域
  4. 使用子服務對象就可以調用每個子對象的方法了

我們可以查看子服務對應的接口規範, 在 spec.pb/user_data.proto 文件定義 (青雲文檔):

service UserDataService {
	rpc UploadUserDataAttachment(UploadUserDataAttachmentInput) returns (UploadUserDataAttachmentOutput);
}

message UploadUserDataAttachmentInput {
	bytes attachment_content = 2;
	string attachment_name = 1;
}

message UploadUserDataAttachmentOutput {
	string action = 1;
	int32 ret_code = 2;
	string message = 3;

	string attachment_id = 4;
}

其中service關鍵字開頭的表示定義一組子服務, 其中rpc開頭的表示子服務中每個具體的方法. 方法的輸入參數和返回值分別爲UploadUserDataAttachmentInputUploadUserDataAttachmentInput結構體類型, 它們由後面的message關鍵字定義.

SDK的代碼生成插件 會生成以下的Go語言代碼:

type UserDataService struct {
	// ...
}

func (p *QingCloudService) UserData(zone string) (*UserDataService, error) {
	// ...
}

type UploadUserDataAttachmentInput struct {
	// ...
}
type UploadUserDataAttachmentOutput struct {
	// ...
}

func (p *UserDataService) UploadUserDataAttachment(
	in *UploadUserDataAttachmentInput,
) (
	*UploadUserDataAttachmentOutput,
	error,
) {
	// ...
}

規範文件的語法細節可以參考 spec.pb/README.md, proto3 文件語法可以參考 Protobuf 的官方文檔.

與官方文檔的兼容性

  • 該 SDK 和 官方 SDK 的 API 保持最大的兼容性
  • 即使有不兼容的地方, API 也是非常相似的

假設青雲的REST規範的文檔中有一個名爲 job_id 的輸入參數, 對應 XXXInput 結構體的成員.

官方文檔是根據 json定義的規範, 然後通過一個名爲 snips 的工具加自己定義的 模板 生成的代碼, XXXInput 輸入參數生成的代碼可能類似以下結構:

type XXXInput struct {
	JobID *string `json:"job_id" name:"job_id" location:"elements"`
}

而我們的SDK採用Protobuf3標準工具生成的代碼:

type XXXInput struct {
	JobId string   `protobuf:"bytes,5,opt,name=job_id,json=jobId" json:"job_id,omitempty"`
}

其中有兩個大的差異: 一個是成員名稱不同, 分別爲 JobIDJobId; 另一個爲類型不同, 分別爲 *stringstring.

snips 採用和 Protobuf-V2 類似的生成規則, 零值是 nil, 空值是空字符串, 二者是不等價的. 在 Protobuf3 的生成規則中, 默認將零值和空值等價.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章