protobuf 不支持泛型?
有人提 proposal 被拒了: github.com/protocolbuffers/protobuf/issues/9527#issue-1142821422
那像这种情况怎么搞?每个 response 都创建一个 wrapper ?
public class Response
@NotNull
private ResponseStatus status;
private T result;
}
是的,非常恶心
也不支持继承
或者写 t4 生成😂
#1 写 t4 生成是啥意思
message {
bytes result = 1;
}
自己根据类型,将 result 解析成正确的类型。
proto 作为协议数据声明,支持范型意味着声明侵入编码和传输过程,本来就不合适。不支持才是合理的。否则人家 isser 说了使用 any 类型就好了啊
谁叫好好的响应数据非要包一层呢
用 string
支持泛型什么鬼,那和不支持泛型的语言怎么交互?
byte ?
#4 怎么定义协议?泛型说白了也就是个 message ,只不过是个动态的 message 而已。而且我觉得最恶心的一点是他们不仅不愿意支持这功能,而且还不愿意接受外部设计,连提 pr 的机会都不给。
#6 只是支持而已,你可以不用,也可以生成不含泛型的 sdk
#5 我在工作中看到的响应体都是这样设计的,看下你们的设计?
我确实没想到在一个不支持泛型的语言里要怎么用这个协议。这复杂度值得吗?
#11 没有泛型的语言直接去掉泛型就好了,泛型只是个语法糖
#8 协议只是约定,好比 protobuf 用 id 号指定字段,这个字段的类型只是双方约定信息,实际数据中不包含这个类型信息也不应该包含,你要加泛型就要在实际数据中包含类型信息,而这个类型实现过程各个语言支持不一样,已经产生了平台依赖,破坏了协议应该和实际实现无关的只是抽象约定的逻辑
如果你想说泛型类型信息也可以是双方约定,那么这和你申明类型是 any 然后任然需要另外一个字段在实际数据传输类型标记有何区别,如果你想说为何不可以把这个过程实现在基础库里,逻辑就是这个不符合基础库不应该包含非原子操作,好比 cpu 机器码不应该包含一个读取文件的高等级 api 一个逻辑,你想要你自己封装扩展就是了
不要把接口设计和程序逻辑混在一起,理解不到位也不要怪别人
去掉泛型,它的类型是什么?生成完的代码长啥样?而且这是藏逻辑,并不是好设计。
对,默认不支持。
我这边用的 golang ,我就把他改了,让 google.protobuf.Any 类型转换成了 interface{}。
你可以借鉴下( github.com/guoming0000/protobuf-go/commit/628f6211b3a75c96181c5137b1605fcfcedaaa4a ),然后改下 protobuf-java ,看看能不能满足你的需求。
不过这么改了就是非标了
github.com/go-kratos/kratos/issues/1952#issuecomment-1822297919
不要再包一层啦。
#14 取舍问题,openapi 就支持了
很简单,正常响应直接返回数据,http 状态吗 200 ;接口出错时,前端参数问题就用 400 状态码,服务器问题就用 500 ,然后响应结构:{"code": 业务定义的错误码, "msg": 错误描述或希望显示的文案}
前端 api 设计形式类似 static fetchItemById = (id: number, onError: (code: number, msg: string) => void): Promise
直接根据 http 状态码去解析,而不是先解析,再根据状态搞泛型
#16 没看懂,但是他这个问题不是加个 optional 就能进解决吗。。
这不是 oneof 的场景吗?
#18 这只适用于 http 接口,而且即使是 http 接口,我也认为这样并不好,把业务状态放在协议里了
#15 搞不了搞不了...没那个能力...我还是老老实实多写几个 wrapper 吧
并非只适用 http ,而是一种设计思路,websocket 、mqtt 也都可以用类似的设计。而且这并不是什么把业务状态放在协议里,http 协议的状态码本就希望服务器能够表达一些明确的意图,不管成功失败全用 200 才是自作聪明的反设计,曾经可能还有些场景有些理由这样做,现在可以扔掉这种惯性设计了。
而且我觉得最恶心的一点是他们不仅不愿意支持这功能,而且还不愿意接受外部设计,连提 pr 的机会都不给。
别人合理拒绝,却反过来说别人封闭,什么道理!
要都是随便接受外部设计和 pr ,各种项目早都得被乌合之众搞凉了!
protobuf 肯定不要支持泛型呀
它一个二进制格式描述协议,和泛型有毛关系
你 pb idl 怎么写的,贴一下呢。就是需要 Response1 、Response2 一个个描述
如果你想 result 一会儿是这个 一会儿是那个,那这个场景就不适合用 pb 。直接裸写就行了,然后用 Swagger 的 Inheritance and Polymorphism 能力
#24 好吧,我表达的有问题,不是说随便接受 pr 。开源项目的一大优势不就是可以倾听社区的声音吗?我意思是没必要这样毫无余地的就拒绝,如果社区呼声很高,也是可以考虑的吧。
#23 像“余额不足”这种业务情况如何用 status 表达,不还是得用自定义的 code 和 message
说到取舍,与其用泛型,这里最好的设计就是字段是 string 。这个取舍稍微想想就能选对了。
http 状态码 500 ,返回数据类似{"code": 610016, "msg": "余额不足"}
简单来说就是成功时 http 状态 200 ,响应数据直接是业务负载数据,错误时 http 状态非 200 ,然后响应数据返回业务错误码和信息文本
是具体是哪个 4xx 可能还可需要讨论,但肯定不该是 http 500 ...
#9 问题就在这"可“字上。项目集成,维护,切换组件过程中麻烦事就够多了。
好比别人 boolean 都是 true false, 你的项目为了灵活定义 boolean 可以是 true false ""。代码都是 python 写的毫无问题,跟 js 交互也没问题。现在要跟 java 交互,项目组肯定日常问候。
pb 这种就是不支持泛型的,就像 http 里一个接口返回的 json 内容里有个 list 的值可能为
[1,2,3,4]和["1","2","3"]的,你序列化难道不是要 case int 和 string 吗,这样叫泛型吗,泛型是编译推导代码内的类型后去做类型擦除的。
可以是任意类型的话那应该用 json rpc 啥的有个 id 和 id 对应 data body 之类的,以及使用一个 websocket 传输不一样数据结构的 socketio 协议。
你应该考虑用 oneof 或者 message id | message body 这种。或者把那段类型指定为 byte ,自己序列化
很正常的需求,不用怀疑自己。
写过一些组件就懂泛型的意义了。
它下面不是已经说理由了么,因为泛型太复杂了。如果要做泛型,那你需要做的不只是设计一套泛型语法,写一个看起来可行的实现,而是评估泛型在每一种 pb 可能交互的主流语言中使用会出现什么问题,在实现中解决这些问题,并给出一个健壮的测试集。又不是说你随便提个 PR 别人就必须得合的……
pb 不是有个类似于泛型的东西吗。
会在输出的时候额外加 type 来做标识。
我记错了?
#33
有意义确实不假,但问题是太过于复杂了。
pb 最开始走的那个以 codegen 为主的模式做泛型会很麻烦。
把泛型这个需要语言特性支持的东西放进 IDL 就不合适,给不支持泛型的语言 codegen 带来一堆麻烦。
any 或者 oneof 然后自己 cast 就好懂多了。
楼上提到几个魔改也只是特定语言 codegen 小改,没动 IDL 。
一直感觉电脑是根据人脑的特征做出来的,那计算机最基本的总线,在人身上存在吗?人身上这么多外围配件,数据交换类似电脑的总线吗?如果有,做一个外部的“总线控制器”能不能接管外部配件…
之前在节点发过求推荐的帖子,可惜进水深火热了,iqoo 双十一 1580 京东到手,其实 pdd 能做到 1400 ,但害怕阴阳屏退换还是选择东子了,还好到货屏幕没问题。 主…
事情原因: 老板拿来一个蓝牙测试板, 让前端搞一个小程序 demo 页面 需求: 新建一个小程序页面创建, 三个操作. 发现蓝牙设备. 连接, 断开. 本人项目经理兼开发, 还…