肯定一下项目价值,这是楼主的第一个 golang 项目,之前又做过 rust 的版本,是个热爱技术的人。这个 SDK 放到楼主自己的项目中去使用的话,肯定是能达到官方 SDK 效益的一倍以上的,毕竟自己写的,对接起来熟。
接下来探讨下技术话题,楼主是否了解过,你的代码为什么能比官方的 SDK 快一倍。
开玩笑的回答:因为阿里在给社区机会,自己制造出很有松弛感的 SDK,让大家有机会可以实现更好用的非官方版本。以下截图来自于阿里云的 golang sdk,圣地巡礼地址(https://github.com/aliyun/alibabacloud-sdk/issues/408)。

阿里的 SDK,在业界是垫底的存在,部分 SDK(点名百炼的通义 ccchat 客服机器人),甚至是调不通的。在 cchat 客服机器人案例中,由于机器人是 SSE 回复,而 SDK 死板的使用其 openapi(内部叫 darabonba)自动生成逻辑,直接 post 取 json response。sse event 肯定不是纯 json 啊,调用就直接报错。
为了支持整个平台所有业务的标准化,阿里搞了这套 openapi 机制,所有业务强制接入,做了一套通过 openapi 描述文件生成 SDK 的“通用”框架,优先支持语言为 java,即使团队再有能力,也很难单独定制一套自己负责的业务的 SDK。导致了 golang SDK 到处充斥着指针、不必要的 json 转换、毫无意义的逻辑判断。。。甚至内部人员不知道是自己边界处理有缺陷,还是 SDK 生成得有问题。
楼主已经做得比阿里好了,聊技术嘛,吹毛求疵下,还是存在一些可以优化的地方的。
问题集中在滥用 io.ReadAll。这个项目中,io.ReadAll 主要用其获取请求返回值,随意挑一个做例子。
object.go 的 162 行,这里使用了 io.ReadAll,代码简化如下:
func (obj Object) Download(client *Client) ([]byte, error) {
// ... 省略
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// ... 省略
}
这里是下载一个 oss 对象的代码。存在的的问题是,将流 (stream) 作为了块 (block) 来看待,是在设计上欠考虑了。你假定了用户需要直接在内存使用下载的 object 的内容,典型的终端思维。终端主要是展示,会将网络上的文件、图片等信息展示出来或直接应用,但后端更多的是做中继,比如企业内部文件的授权中继、前端所需资源的中转、网络 -> 文件系统的持久存储。打个比方,假若 OSS 是做大模型存储的,一个后端服务使用了这个 SDK,从 OSS 下载算法团队调教过的某个模型,瞬间内存就会被占用很多个 G,内存小的话,瞬间爆炸。
也许会反驳,在不知道返回体到底是什么的情况下,怎么知道 resp.Body 到底是个错误信息,还是 object 文件?不先读取出来,无法判断。
不是才刚骂完阿里嘛,还是要夸一句找补一下的,http 的 status code 就是这么用的,oss 严格的规定了,在 response 的 status code 为 200 的情况下,response body 一定是请求的文件内容。
最后再吐槽下楼主的标题,看你 7 位数 qq 邮箱注册,年龄应该也和咱差不多。
“盆友,SDK 好设计雄鹰一样用我们”。