有人提 proposal 被拒了: https://github.com/protocolbuffers/protobuf/issues/9527#issue-1142821422
那像这种情况怎么搞?每个 response 都创建一个 wrapper ?
public class Response<T> {
@NotNull
private ResponseStatus status;
private T result;
}
1
a33291 23 小时 38 分钟前
是的,非常恶心
也不支持继承 或者写 t4 生成😂 |
3
gam2046 23 小时 28 分钟前
message {
bytes result = 1; } 自己根据类型,将 result 解析成正确的类型。 |
![]() |
4
sujin190 23 小时 17 分钟前 via Android
proto 作为协议数据声明,支持范型意味着声明侵入编码和传输过程,本来就不合适。不支持才是合理的。否则人家 isser 说了使用 any 类型就好了啊
|
![]() |
5
debuggerx 23 小时 0 分钟前 ![]() 谁叫好好的响应数据非要包一层呢
|
6
Rickkkkkkk 22 小时 59 分钟前 ![]() 用 string
支持泛型什么鬼,那和不支持泛型的语言怎么交互? |
7
nonempty 22 小时 57 分钟前
byte ?
|
8
ljzxloaf OP @sujin190 #4 怎么定义协议?泛型说白了也就是个 message ,只不过是个动态的 message 而已。而且我觉得最恶心的一点是他们不仅不愿意支持这功能,而且还不愿意接受外部设计,连提 pr 的机会都不给。
|
9
ljzxloaf OP @Rickkkkkkk #6 只是支持而已,你可以不用,也可以生成不含泛型的 sdk
|
11
Rickkkkkkk 22 小时 48 分钟前
@ljzxloaf 我确实没想到在一个不支持泛型的语言里要怎么用这个协议。这复杂度值得吗?
|
12
ljzxloaf OP @Rickkkkkkk #11 没有泛型的语言直接去掉泛型就好了,泛型只是个语法糖
|
![]() |
13
sujin190 22 小时 35 分钟前 ![]() @ljzxloaf #8 协议只是约定,好比 protobuf 用 id 号指定字段,这个字段的类型只是双方约定信息,实际数据中不包含这个类型信息也不应该包含,你要加泛型就要在实际数据中包含类型信息,而这个类型实现过程各个语言支持不一样,已经产生了平台依赖,破坏了协议应该和实际实现无关的只是抽象约定的逻辑
如果你想说泛型类型信息也可以是双方约定,那么这和你申明类型是 any 然后任然需要另外一个字段在实际数据传输类型标记有何区别,如果你想说为何不可以把这个过程实现在基础库里,逻辑就是这个不符合基础库不应该包含非原子操作,好比 cpu 机器码不应该包含一个读取文件的高等级 api 一个逻辑,你想要你自己封装扩展就是了 不要把接口设计和程序逻辑混在一起,理解不到位也不要怪别人 |
14
Rickkkkkkk 22 小时 34 分钟前
@ljzxloaf 去掉泛型,它的类型是什么?生成完的代码长啥样?而且这是藏逻辑,并不是好设计。
|
![]() |
15
brightguo 22 小时 31 分钟前
对,默认不支持。
我这边用的 golang ,我就把他改了,让 google.protobuf.Any 类型转换成了 interface{}。 你可以借鉴下( https://github.com/guoming0000/protobuf-go/commit/628f6211b3a75c96181c5137b1605fcfcedaaa4a ),然后改下 protobuf-java ,看看能不能满足你的需求。 不过这么改了就是非标了 |
![]() |
16
wunonglin 22 小时 23 分钟前 ![]() |
17
ljzxloaf OP @Rickkkkkkk #14 取舍问题,openapi 就支持了
|
![]() |
18
debuggerx 22 小时 8 分钟前
@ljzxloaf 很简单,正常响应直接返回数据,http 状态吗 200 ;接口出错时,前端参数问题就用 400 状态码,服务器问题就用 500 ,然后响应结构:{"code": 业务定义的错误码, "msg": 错误描述或希望显示的文案}
前端 api 设计形式类似 static fetchItemById = (id: number, onError: (code: number, msg: string) => void): Promise<Item | null> => {...} 直接根据 http 状态码去解析,而不是先解析,再根据状态搞泛型 |
20
eslizn 22 小时 1 分钟前
这不是 oneof 的场景吗?
|
![]() |
23
debuggerx 21 小时 50 分钟前
@ljzxloaf 并非只适用 http ,而是一种设计思路,websocket 、mqtt 也都可以用类似的设计。而且这并不是什么把业务状态放在协议里,http 协议的状态码本就希望服务器能够表达一些明确的意图,不管成功失败全用 200 才是自作聪明的反设计,曾经可能还有些场景有些理由这样做,现在可以扔掉这种惯性设计了。
|
![]() |
24
lesismal 21 小时 48 分钟前 ![]() > 而且我觉得最恶心的一点是他们不仅不愿意支持这功能,而且还不愿意接受外部设计,连提 pr 的机会都不给。
别人合理拒绝,却反过来说别人封闭,什么道理! 要都是随便接受外部设计和 pr ,各种项目早都得被乌合之众搞凉了! |
![]() |
25
iyaozhen 21 小时 29 分钟前
protobuf 肯定不要支持泛型呀
它一个二进制格式描述协议,和泛型有毛关系 你 pb idl 怎么写的,贴一下呢。就是需要 Response1 、Response2 一个个描述 如果你想 result 一会儿是这个 一会儿是那个,那这个场景就不适合用 pb 。直接裸写就行了,然后用 Swagger 的 Inheritance and Polymorphism 能力 |
26
ljzxloaf OP @lesismal #24 好吧,我表达的有问题,不是说随便接受 pr 。开源项目的一大优势不就是可以倾听社区的声音吗?我意思是没必要这样毫无余地的就拒绝,如果社区呼声很高,也是可以考虑的吧。
|
28
Rickkkkkkk 21 小时 19 分钟前
@ljzxloaf 说到取舍,与其用泛型,这里最好的设计就是字段是 string 。这个取舍稍微想想就能选对了。
|
![]() |
29
debuggerx 20 小时 46 分钟前 via Android
@ljzxloaf http 状态码 500 ,返回数据类似{"code": 610016, "msg": "余额不足"}
简单来说就是成功时 http 状态 200 ,响应数据直接是业务负载数据,错误时 http 状态非 200 ,然后响应数据返回业务错误码和信息文本 |
31
moudy 20 小时 37 分钟前
@ljzxloaf #9 问题就在这"可“字上。项目集成,维护,切换组件过程中麻烦事就够多了。
好比别人 boolean 都是 true false, 你的项目为了灵活定义 boolean 可以是 true false ""。代码都是 python 写的毫无问题,跟 js 交互也没问题。现在要跟 java 交互,项目组肯定日常问候。 |
![]() |
32
guanzhangzhang 20 小时 20 分钟前
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 ,自己序列化 |
![]() |
33
wolfie 19 小时 21 分钟前
很正常的需求,不用怀疑自己。
写过一些组件就懂泛型的意义了。 |
![]() |
34
InkStone 19 小时 15 分钟前
@ljzxloaf 它下面不是已经说理由了么,因为泛型太复杂了。如果要做泛型,那你需要做的不只是设计一套泛型语法,写一个看起来可行的实现,而是评估泛型在每一种 pb 可能交互的主流语言中使用会出现什么问题,在实现中解决这些问题,并给出一个健壮的测试集。又不是说你随便提个 PR 别人就必须得合的……
|
![]() |
35
flyqie 18 小时 46 分钟前 via Android
pb 不是有个类似于泛型的东西吗。
会在输出的时候额外加 type 来做标识。 我记错了? |
![]() |
37
jim9606 15 小时 1 分钟前
把泛型这个需要语言特性支持的东西放进 IDL 就不合适,给不支持泛型的语言 codegen 带来一堆麻烦。
any 或者 oneof 然后自己 cast 就好懂多了。 楼上提到几个魔改也只是特定语言 codegen 小改,没动 IDL 。 |
38
hyperbin 8 小时 14 分钟前 via Android
protobuf 的库是跨语言,那么那些不支持泛型的语言该如何适配?
|
39
fffq 7 小时 27 分钟前
pb.Any 然后自己玩
|
40
5261 7 小时 22 分钟前
我其实也在想 pb 的优势到底是啥? 除了跨语言外,还有就是同样的内容可能字节大小变小,但是现在流量不是过剩的情况下,json 不是也都满足嘛?
|
41
jigujigushanshan 7 小时 9 分钟前
@5261 性能啊,解析速度快 体积小 传输速度快,相反如果加泛型 想都不用想唯一的优势都没了,那还不如 json 各种场景一把梭
|
![]() |
42
hidemyself 7 小时 0 分钟前
我理解出现这种场景,说明不适合用 pb
|
![]() |
43
AEnjoyable 6 小时 47 分钟前
看你要传输什么东西 正常的就 any + wrapper 包, 不然就像楼上说的 byte,然后自己反序列化
|
44
bli22ard 6 小时 38 分钟前 ![]() 你是先有 proto 文件,再生成数据存储类,而不是先有你发的 Response<T> 这种定义。proto 定义的可能最佳做法是,定义一个 Head message ,定义 code 和 msg ,然后 service 的方法返回值,message RespOrderList{
Head head=1; repeated Order orderList=2; } 。protobuf 要是加个泛型,你让没有泛型的语言怎么实现。另外,即使 java 代码中使用 json , 我也不觉得,Response<T> 是一种好的做法。 |
45
lpxxn 6 小时 31 分钟前
最好不要用 bytes ,调用方非常难受。
|
46
rev1si0n 6 小时 25 分钟前 ![]() 这个问题,要么填 bytes 自己序列化,要么 oneof 。纠结这个说明你可能也没有深入使用也没有看看别人是怎么做的还说让人支持,你在破坏它的通用性,为了你的需求需要做两个版本的文档。建议自己搞个,最好别用,我只能说以后的坑还多了。
|
![]() |
47
MEIerer 6 小时 22 分钟前
这两天准备看这个来着
|
![]() |
48
itskingname 6 小时 21 分钟前
@debuggerx 写 Java 的人就喜欢什么都包好几层,就跟他们的空文件夹嵌套几十层一样。
|
49
securityCoding 6 小时 20 分钟前
可能是定位有偏差,你定义一个通用 baseResult 字段就好了,用反射来解决
|
50
rev1si0n 6 小时 20 分钟前
我觉得这个定义适合你做参考,开发的时候甚至没有那么多现成的项目可以让我参考该怎么做。https://github.com/firerpa/lamda/tree/6e1298b536d344527ddcb94e621f1b3a88aa6f32/lamda/rpc
|
51
zmcity 4 小时 40 分钟前
因为不是所有语言都支持泛型,如果 pb 强行兼容,在 c 语言等面向过程的语言的 sdk 里使用就会变得异常抽象。
所以要么使用 oneof ,要么换一个完全放弃面向过程的语言的库,比如 microsoft.bond |
![]() |
53
lesismal 1 小时 36 分钟前
> @lesismal #24 好吧,我表达的有问题,不是说随便接受 pr 。开源项目的一大优势不就是可以倾听社区的声音吗?我意思是没必要这样毫无余地的就拒绝,如果社区呼声很高,也是可以考虑的吧。
基础知识储量不够但是又有兴趣的话,可以多学下,等理解不到 pb 的设计、实现、原理、做这种更改尤其是是多语言的难度和影响,你大概就不会再使用 “也就是个 message”、“只是支持而已” 这些轻浮的话了,技术的问题最好是能让自己有理有据的输出、而不是“妄加评论” 相比于社会、生活中的很多事情,技术更严谨,无知者无畏、我穷我嗓门大我有理这种发声方式不是好的方法,你想想,自己不占理还要喷别人,跟那些非法医闹、水军舆论绑架有什么区别? “倾听社区的声音” 和 “倾听社区正确的声音” 是两码事。如果不懂,至少就请尊重和慎言,而不是诋毁。 越读书越学习越觉得自己无知,共勉! |