β

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

chai2010的个人页面 15 阅读
go

<p> 项目地址: </p> <ul> <li> <a href="https://github.com/chai2010/qingcloud-go" rel="nofollow"> https://github.com/chai2010/qingcloud-go </a> </li> </ul> <p> 项目目标: </p> <ul> <li> 基于 Protobuf-V3 语法维护规范, 便于升级和维护 </li> <li> 更完整的服务支持, 新服务第一时间提供支持 </li> <li> 更好用的编程接口 </li> </ul> <p> 在线文档: </p> <ul> <li> <a href="https://docs.qingcloud.com" rel="nofollow"> https://docs.qingcloud.com </a> </li> <li> <a href="https://godoc.org/github.com/chai2010/qingcloud-go" rel="nofollow"> https://godoc.org/github.com/chai2010/qingcloud-go </a> </li> </ul> <p> 接口规范: </p> <ul> <li> <a href="https://github.com/chai2010/qingcloud-go/tree/master/spec.pb" rel="nofollow"> spec.pb </a> </li> </ul> <h2> 配置文件 </h2> <p> 当前用户的配置文件在 <code> ${HOME}/.qingcloud/config.yaml </code> , 内容如下: </p> <pre><code># 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' </code></pre> <p> 将 <code> qy_access_key_id </code> 和 <code> qy_secret_access_key </code> 字段替换为 API密钥 中的内容. </p> <p> 其中 <code> json_disable_unknown_fields </code> 是新加的变量, 表示在JSON解码时忽略 proto.Message 遇到未定义成员的错误. </p> <h2> 快速入门 </h2> <p> 以下为 <a href="https://github.com/chai2010/qingcloud-go/tree/master/hello.go" rel="nofollow"> hello.go </a> 的内容: </p> <pre><code>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 := &amp;jsonpb.Marshaler{ OrigName: true, EnumsAsInts: true, EmitDefaults: true, Indent: " ", } s, err := jsonMarshaler.MarshalToString(m) if err != nil { log.Fatal(err) } return s } </code></pre> <p> 初始化子服务也可以用以下方式: </p> <pre><code>nicService := pb.NewNicService(config.MustLoadUserConfig(), "pek3a") </code></pre> <p> 运行例子: </p> <pre><code>go run hello.go </code></pre> <p> <a href="https://github.com/chai2010/qingcloud-go/tree/master/examples" rel="nofollow"> 更多例子 </a> . </p> <h2> 文档指南 </h2> <p> 使用青云SDK一般是以下步骤: </p> <ol> <li> 用 <a href="https://godoc.org/github.com/chai2010/qingcloud-go/config" rel="nofollow"> config </a> 包构造一个配置对象, 里面含有最重要的 API密钥, 还包含日志级别等信息. </li> <li> 基于配置对象调用 <a href="https://godoc.org/github.com/chai2010/qingcloud-go/service" rel="nofollow"> service </a> 包的 <a href="https://godoc.org/github.com/chai2010/qingcloud-go/service#Init" rel="nofollow"> <code> Init </code> </a> 函数构造一个青云主服务对象 <a href="https://godoc.org/github.com/chai2010/qingcloud-go/service#QingCloudService" rel="nofollow"> <code> qcService </code> </a> , 其中会根据配置文件设置日志级别. </li> <li> 假设有一个 <a href="https://github.com/chai2010/qingcloud-go/tree/master/spec.pb/user_data.proto" rel="nofollow"> UserData </a> 子服务, 那么调用 <a href="https://godoc.org/github.com/chai2010/qingcloud-go/service#QingCloudService.UserData" rel="nofollow"> <code> qcService.UserData("pek3a") </code> </a> 方法将返回子服务对象, 其中参数是区域 </li> <li> 使用子服务对象就可以调用每个子对象的方法了 </li> </ol> <p> 我们可以查看子服务对应的接口规范, 在 <a href="https://github.com/chai2010/qingcloud-go/tree/master/spec.pb/user_data.proto" rel="nofollow"> spec.pb/user_data.proto </a> 文件定义 ( <a href="https://docs.qingcloud.com/api/userdata/index.html" rel="nofollow"> 青云文档 </a> ): </p> <pre><code>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; } </code></pre> <p> 其中 <code> service </code> 关键字开头的表示定义一组子服务, 其中 <code> rpc </code> 开头的表示子服务中每个具体的方法. 方法的输入参数和返回值分别为 <code> UploadUserDataAttachmentInput </code> 和 <code> UploadUserDataAttachmentInput </code> 结构体类型, 它们由后面的 <code> message </code> 关键字定义. </p> <p> <a href="https://github.com/chai2010/qingcloud-go/tree/master/protoc-gen-go/qingcloud/qingcloud.go" rel="nofollow"> SDK的代码生成插件 </a> 会生成以下的Go语言代码: </p> <pre><code>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, ) { // ... } </code></pre> <p> 规范文件的语法细节可以参考 <a href="https://github.com/chai2010/qingcloud-go/tree/master/spec.pb/README.md" rel="nofollow"> spec.pb/README.md </a> , proto3 文件语法可以参考 <a href="https://developers.google.cn/protocol-buffers/docs/proto3" rel="nofollow"> Protobuf </a> 的官方文档. </p> <h2> 与官方文档的兼容性 </h2> <ul> <li> 该 SDK 和 官方 SDK 的 API 保持最大的兼容性 </li> <li> 即使有不兼容的地方, API 也是非常相似的 </li> </ul> <p> 假设青云的REST规范的文档中有一个名为 <code> job_id </code> 的输入参数, 对应 <code> XXXInput </code> 结构体的成员. </p> <p> 官方文档是根据 <a href="https://github.com/yunify/qingcloud-api-specs/tree/master/2013-08-30/swagger" rel="nofollow"> json定义的规范 </a> , 然后通过一个名为 <a href="https://github.com/yunify/snips" rel="nofollow"> snips </a> 的工具加自己定义的 模板 生成的代码, <code> XXXInput </code> 输入参数生成的代码可能类似以下结构: </p> <pre><code>type XXXInput struct { JobID string json:"job_id" name:"job_id" location:"elements" } </code></pre> <p> 而我们的SDK采用Protobuf3标准工具生成的代码: </p> <pre><code>type XXXInput struct { JobId string protobuf:"bytes,5,opt,name=job_id,json=jobId" json:"job_id,omitempty" } </code></pre> <p> 其中有两个大的差异: 一个是成员名称不同, 分别为 <code> JobID </code> 和 <code> JobId </code> ; 另一个为类型不同, 分别为 <code> *string </code> 和 <code> string </code> . </p> <p> <a href="https://github.com/yunify/snips" rel="nofollow"> snips </a> 采用和 Protobuf-V2 类似的生成规则, 零值是 <code> nil </code> , 空值是空字符串, 二者是不等价的. 在 Protobuf3 的生成规则中, 默认将零值和空值等价. </p>

go
作者:chai2010的个人页面
chai2010的博客
原文地址:青云 SDK Go Version (兼容官方 SDK), 感谢原作者分享。

发表评论