< 返回版块

Mike Tang 发表于 2020-06-24 18:41

Tags:翻译,rust,love

副标题:这里是直接从 Rustacean 他们那里得到的反馈:为什么 Rust 获得如此厚爱。
作者:Ryan Donovan
原文地址:https://stackoverflow.blog/2020/06/05/why-the-developers-who-use-rust-love-it-so-much/

背景:本文是 StackOverflow 在 Rust 语言连续第 5 次夺得最受程序员喜爱的语言评比第一名后的一篇专述文章,发表在 S​tackOverflow 官方博客上。文中的许多观点,非常深刻,​读来酣畅淋漓,强烈推荐。

--

2020 年开发者调查结果出来了,又一次,Rust 是参与调查的 65,000 名程序员中最受喜爱的语言的第一名。Rust 从 2016 年就开始夺冠,表明它有一些东西,让使用它的开发者爱不释手。调查反馈表明,正在使用 Rust 的开发者中,有 86.1% 的人想在下一年继续使用它。这已经是连续第 5 年 Rust 摘得此冠了,因此我们来探究一下它到底有什么特别的地方。

几个月前,我们询问了 Stack Overflow 的首席 Rust 贡献者,Jake Goulding (也叫 Shepmaster),让他解释一下,是什么让 Rust 击中了用它做开发的程序员。如下是其中一段:

“简短的答案就是 Rust 解决了呈现在其它许多语言中的痛点,为(我们)前进提供了坚实的一步,而它只有为数不多的缺点”。

全文非常值得阅读,对从其它语言来的程序员来说,他讲到了(使用) Rust 的收益(以及痛苦的地方)。尽管 Jake 雄辩且令人信服,我们还是想听到更多用户的声音。于是我去 Rust 聊天室Rust 论坛上留了一些言。Rust 用户是一群热情的人,在一些友好的辩论后,我得到了迷人而深入的见解。

(由于内容长度和结构清晰度的原因,下面的内容摘引被编辑加工,并且按概念进行了分组。其中许多内容来自于 Rust 用户论坛的这个 thread,所以如果你想获取更全面的内容和上下文信息,请跳转到那个地址查看)。

言归正传,下面就是直接从 Rustacean 他们那里得到的反馈:为什么 Rust 获得如此厚爱。

真正全新和深思熟虑的特性

当一些新语言只是在现有的概念上锦上添花,以及将它们变得更易使用时,有几个用户感觉 Rust 真正对编程语言做了一些实际性的创新,而不只是一些表面华丽的东东,他们感觉 Rust 的设计选择解决了现代编程语言中的一些困难问题。

ZiCog: “Rust 是我专业编程 40 年来用过的一打语言中的唯一一个引入了真正全新特性的语言。就是在一个编译型的、没有垃圾回收或复杂运行时的、货真价实的系统编程语言中,实现内存使用安全的这一整套想法”。

Denys Séguret: “当我们发现遮掩在一个环境变量下的一个强大的特性——比如说读取一个编译语境中的元素——能被如此优雅地实现,甚至在编译期就解决问题,而没有任何丑陋的不一致的时候,我们对 Rust 就常常产生一种狂热感”。

janriemer: ”引用一下 Chris Dickinson(npm 工程师)的话,对我来说,他已经很完美的总结了,因为在知道这句话之前,我的想法也是一样的:‘我对 Rust 最大的赞美,就是它很乏味,这是一个令人吃惊的赞美。’

Rust 看起来像是一个被用户体验设计师开发的编程语言。他们对这个语言有一个清晰的视野,会仔细选择把什么添加到语言中,哪些会回炉重造,同时也会聆听社区小伙伴真正想要什么。没有马马虎虎的地方(没有没系紧的地方),整体上是连贯一致的,能完美支撑开发者的工作流。”

skysch: “我从 Haskell 过来,我感觉 Haskell 是一门非常优雅和安全的语言。对我来说,最大的不同在于:Haskell 中,高性能代码和地道的‘干净’代码之间的差别比在 Rust 中的要大。大部分 Rust 代码看起来就跟其它 Rust 代码一样,即使它们性能更好。Haskell 也可以变得不寻常的快,如果某人在不同的库和目标(与你通常操作的方式不同)下折腾的话。小的语法不同会导致行为上的巨大差异,而 Rust 在这方面就统一得多。”

Jay Oster, PubNub 架构师: “除了安全和性能,我们还有:

  • 泛型;
  • 特征;
  • 代数类型;
  • 函数式和命令式范式;
  • 可能是世界上最好的依赖管理和构建工具,实际上解决了‘依赖地狱’问题;
  • 对内嵌文档、测试和性能评测的美妙支持;
  • 一个大的且正在生长的库、抽象、工具生态;
  • 过程宏;
  • 与已有代码的 FFI 交互性;
  • 支持一打平台(更多的在路上!);
  • 对开发者体验是正向的、毋庸置疑的满足。

Rust 是唯一一个下面所有框框都打勾的语言:

  • 内存安全
  • 类型安全
  • 消除数据竞争
  • 使用前编译
  • 建立(并且鼓励)在零抽象之上
  • 最小的运行时(无停止世界的垃圾搜集器,无 JIT 编译器,无 VM)
  • 低内存占用(程序可以运行在资源受限的环境,比如小的微控制器)
  • 裸金属目标(比如,写一个 OS 内核或者设备驱动,把 Rust 当一个 ‘高层’汇编器使用)”

daboross:“编译时保证:当我想到‘静态类型语言’的时候,我会想到 Java, 或 C#,或者比如像 TypeScript。它们提供编译时的保证,保证你的代码有正确的类型,将一些运行时的错误转移到编译时。Rust 在这上面又前进了一大步!编译时检查扩展到了线程安全、所有权语义、有效性验证。

枚举意味着,我可以在编译时,声明我的数据取值的变体集合,然后当我访问那些数据时,我被强制要求考虑所有可能性。特征意味着当我的代码被模板化/泛型化时,我可以精确知道我能做哪些事情。

Rust 向后兼容做得非常好。我可以运行用 Rust 1.0 写的代码。同样的,我可以继续放心写代码,这些代码在我下次升级 Rust 的时候,不需要再改动。

并且不止是 Rust 本身——这个语言也让所有库具有了同样的保证。考虑如下两点:

  • 类型检查的时候,只会考虑函数签名,而不依赖具体的实现来确定调用者是否是正确的(像你在 Scala, 或 Haskell 中做的那样)
  • 通篇的类型系统意味着对接口不正确的使用会变成一个类型错误,而不是运行时错误

因为这两件事情,库可以 100% 保证当发布一个新接口的时候,能维持向后兼容性。在 Python, Java, Javascript,甚至 Scala 或 Haskell 中,如果你想保证向后兼容性,你需要在事物的实现上付出额外的注意力。而在 Rust 中,这是轻松的:如果你没有改变函数签名,那它就是相同的。”

Peter Varo: “Rust 有一个很香的地方:它像 C 和 C++ 那样底层,因此也具有底层的这些优势(比如,控制、大小、速度等)。同时呢,它又像 Haskell 那样高层,自带令人吃惊的大量功能传承。它还是命令式的,所以容易被大多数人上手。然后它又像 Python 一样灵活,比如,'鸭子类型(duck-typing)'的概念出现在编译时(比如,特征限定),然后它又没有陈旧的面向对象模型以及由这个模型导致的各种出名的问题。

最后但很重要的是,还有一连串的东西被包含进来:精简短小的语法,语言提供的数目不多的特性,标准库及其一致性,高质量的文档的集成,包括对初学者和高级用户都适用的学习材料,这些都是促成因素。”

blonk: “有了 Rust/Cargo,我可以聚焦到实际的代码上,而不是把精力花在构建系统上。不需要再花一整天阅读另一个构建系统的资料。Rust 的交叉编译是如此的简单和愉快,当你知道怎么操作它时,你忍不住会想‘等等,我是不是遗漏了什么’。

若你从外面看 Rust,你往往只会听到空洞的口号,但当你开始使用它时,你会相当惊奇地发现这里面有很多干货:

  • 当你花费时间与编译器做斗争让你的代码编译通过,你反而节省了调试代码的时间。
  • 你不再恐惧大的重构。一旦你的重构代码通过编译,它就像预期的那样工作。
  • 你强迫自己做了正确的多线程编程(好吧,你仍然会遇到死锁的情况,但是那种让程序崩溃的缺陷很难再出现了)

我发现自己的样板代码(重复代码)也写得少多了。当我需要写样板代码的时候,我经常可以把它藏在另一个模块中,从而不妨碍写实际的应用逻辑代码(最常见的例子就是错误类型转换)。”

上规模后的安全性与速度

现在许多的编程讨论都在围绕是使用一个快速的、底层的能让你自行进行内存管理的语言,还是一个高层的能更好地防止安全性问题的语言。而对于 Rust 的粉丝来说,他们喜欢它的地方就是,这两样它都做到了。

Jay Oster, Architect at PubNub: “就好像整个职业生涯都游荡在完全的黑暗中,突然一道光亮照了进来,认识到两个真相:

  1. 你并不完美。你会犯错。那些缺陷会给你造成很多问题。
  2. 其实并不是必须走这条路。

我知道的一种常见辩解是,一些人宣称他们自己事实上非常完美,不会写出错误的代码,每件事都是极好的,然后他们不能理解为什么其他所有人都对 Rust 这么感兴趣。但其实对这些老家伙而言,事实是非常清楚的,只是他们没意识到而已。问题严格来说,不在他们自身,而在于其它每个人。这实际上是规模经济的问题。

换句话说,不管是在语言上,还是在实现细节上,我自己独立的情况下也可以写出没有瑕疵和缺陷的代码——如果我有足够的时间和精力来关注每个微小的细节,仔细把每行代码都打磨得很漂亮。但那不起作用。一旦我开始依赖其它人写的代码,或者新的贡献者来修改我的代码,那么我所有的这些所谓的“完美性的保证”就不切实际了。‘靠约定(保证)的正确性’无法扩大规模。

约定的执行也会有遗漏,然后大家会付出难以想象的大量时间和精力来尝试自动化一些补救措施(以强制执行这些约定),而这些措施本来就不应该存在于第一层面。“啊哈”时刻出现了,(我)正意识到我们实际上可以得到更强的保障,那就是把这些约定直接烘焙到语言和编译器里面。

除此以外,如果你想的话,你还可以得到与你精心手写的汇编代码同等的性能。鱼和熊掌可以兼得!”

daboross: “作为库的作者,有了复杂的 trait/泛型系统,我可以精打细造功能复杂、但容易使用的接口。这些接口无法被不正确的使用,这意味着我不需要进行运行时检查,然后我的用户甚至不需要思考那些有问题的情况,因为他们无法写出它们。

而作为库的使用者,丰富且广泛的 crates 生态让我可以写不同领域的代码,而不需要深挖每一个领域的细节。我不需要知道怎样使用 serde 来让一个 JSON 解析器或构建器工作起来——然而我在这块儿知识的缺乏并不会成为 bug 的来源,因为我会得到编译时错误,而不是运行时错误。

当使用 Rust 的时候,我直接感觉是被关照了。有那么多琐碎的事情,从包升级,到字打错,到给一个接口传入它不想要的字符串时得到一个随机的运行时错误,这些,在 Rust 中都不存在。我只需要思考算法!”

一帮癖好者对一个有挑战的语言的喜爱?

还记得我提到过的争论么?我看到的争论中的其中一些回合来自于不确定是否这个‘最受喜爱’的抬头是不是因为 Rust 有一个出于自愿的主要使用这个语言的规模不大的用户基数。确实如此,我们的调查反馈者中只有 5.1% 的人在过去一年使用过 Rust,而这一部分人愿意继续使用 Rust。

CAD97: “完全坦率地说:我认为 Rust 完全受益于只有很少的人是被强迫使用 Rust 的。大部份人仍然是自愿使用 Rust。

我不是说 Rust 不配这个标签(我确定它非常配!),我只是主张 Rust 实际上在 SO 所做的这个调查里面的指标游戏中占了便宜。因为它在它的热心粉丝中有相当大的采用率,而在那些强制人们使用一个他们将不再继续使用的语言的人或公司中却很少被采用。”

ZiCog: “任何一种语言,如果你使用得足够久,你都会觉得他糟透了。不管多少种语言,只要用够年份,都会觉得不爽。

那些用了各种语言进行编程,并且有能力和天赋的人,最后都会发明和实现他们自己的新的编程语言,来修复他们过去遭遇的所有痛处。于是你看到了,新的语言像杂草一样层出不穷。

鉴于以上观点,如果你问程序员哪种语言是他的最爱,那不会是他们正在使用的或者曾经用过的一个。

因为到现在为止,几乎还没有程序员长时间地使用 Rust,当然他们会说他们喜爱 Rust。”

Jay Oster, Architect at PubNub: “对过去几十年的各种语言,我曾经也持这样一个偏见:类似于‘青草总是更绿’。但是我认为这并不是现在这个现象的主因之一。如果它是,我们也许会期望在这些调查中应该是一些新语言霸榜,不是吗?”

H2CO3: “Rust 是到目前为止我最喜欢的语言,尽管现在我已经持续使用它超过 4 年了(个人项目也有,实现带性能需求的实战代码也有)。而我之前使用 C 和 C++ 拥有这么多经验的时候,我已经发现了他们的一些严重缺点。

见鬼的是,即使是 Hashkell,优雅语言中的精英,在我大概用了一年,当我开始摆弄语言扩展和方言以让一个相对高级一点的库能够编译时,也显露出了它的无法掩饰的丑陋。

而 Rust 就不会出现这种情况。footgun(译者注:指在一个产品上添加一个新东西,容易让枪打着自己脚。表明设计不好,促使用户不敢加东西。对应到这里,就是用来实现这个产品的语言不够好) 的包袱和设计错误从来不会(从不知道的什么地方)突然冒出来。“

asafigan: “我相信 Rust 学起来有挑战,但是用起来绝对是有回报的。我认为令人惊奇的是,有这么多人在回报足够大的情况下享受这种被挑战。

我发现 Rust 很难学,但是很容易使用。我认为许多从一个不同的语言来到 Rust 的人会惊讶它有这么多的不同(因此很难学)。但是他们忘记了才开始学习编程的时候也是多么困难。在大学里,我们有两堂使用 Java 进行面向对象编程的课,直到最后,许多人都没有意识到这一点。Rust 与其它语言有太多不同导致很难学。比如,如果你只知道 OOP,那么函数式语言也很难学。如果你只使用 GC 或者手动内存管理,所有权也很难学,特征也很怪异。但是为了更好的软件,值得学。”

cfsamson: “在 Rust 里面,我发觉很多努力都被提前载入了。它让一些简单的问题某种程度上比较难上手,但是它并没有在后续过程中创造难题。如果有问题,最有可能是本身比我预想的要困难的领域上的问题,而与我使用的工具无关。我发现我所得到的东西完全对得起我提前付出的代价。我还发现只要你较好的理解了这门语言,这个代价其实很低。“

一个热情的、能给予支援的社区

通过与粉丝聊天,我发现他们对这门语言的热爱直接溢于言表,即使他们不承认(我这个说法)。Rust 用户 blonk 把这种现象归结为一种社区特色。

blonk:“非常清晰的是,‘尊重’在整个社区中体现得非常好。曾经出现过一些情况,有人带着恶意(在我看来是的)问一些问题,但是社区成员并没有对此大发雷霆,而是非常友善地回答,并因此缓和了局势。”

为什么 Rust 团队认为这个语言被厚爱

如果你想知道是什么造就了这种全心投入的支持者,那就与最投入的人交谈,是不?于是,我找到了 Rust 团队来揭示他们认为 Rust 越来越受欢迎的原因。格式有点乱,我保持一问一答的布局形式。

Erin Power

Erin Power 是位于柏林的一位开发者。她从 2015 年 1.0 开始就在用 Rust 了。她是 Rust 治理工作组的领导之一,也是"Tokei" (一个用 Rust 写的流行的开源代码统计工具)的的创作者。

Q: 使用 Rust的人看起来确实喜欢它;你觉得为什么会这样?

A: 我认为是因为 Rust 给了大的承诺,并且兑现了它们。像其它高级语言一样,Rust 提供了自动内存管理,但是这是在编译期搞定的,因此不存在隐藏的代价或行为。

Rust 总是被设计为我们在现代硬件上期望的样子。线程安全和数据竞争,普遍在其它语言中是七伤拳(footgun, 伤自己的脚的枪)一类的存在,而它们在 Rust 中被纳入了语言层面。因此,现在要完全发挥出你的工作站的能力优势是一件极其简单的事,不需要做多少改动,再也不需要头痛了。rayon (一个流行的 Rust 库)这个库总是让我印象深刻,只需要改动一行代码,它就可以并行化你的整个工作负载。

于是就出现了很多用 Rust 写的高质量和高性能的实现,然后由于 cargo 和 crates.io (Rust 的包管理工具和社区维护的包仓库)的存在,在内部以及更广大的世界复用和分享你的代码,从来没有变得如此简单。

Cargo 处理包含几个到数十个包的大仓库,就像处理一个(那么容易),你再也不需要花费几天时间书写构建文件以达到你想要的配置。

不仅管理和维护你的 Rust 工程依赖很简单,使用 Rustup(自带的一个默认工具链版本管理器),Rust 本身的升级,以及在不同版本间的切换,也是难以置信的简单。

上面所说的随便一点,就足以让人喜欢上 Rust 了。但是所有这些点汇合在一起,让 Rust 变成了一个富有吸引力的语言。用 Rust 创建和编码你的项目,令人耳目一新。

Q: Rust 团队要保证用户始终喜爱它的计划是什么?

A: 好吧,我没法说出团队已经做出的所有计划,因为 Rust 有数十(还是十几)个主要是由半自治的志愿者们组成的团队,他们都在努力改进 Rust 语言和周边的生态。你可以在 Github 上找到今年的工程路线图(尽管我注意到这是在 COVID-19 之前提议和写成的)。

Q: 你会常规使用 Rust 吗? 为什么会这样?

A: 从 2015 年 Rust 到达 1.0 以来我一直在写 Rust,并且从那开始我尝试花尽量多的编程时间来写 Rust。我书写并维护了一些开源应用和库,然后我从 2018 年开始专职使用 Rust 工作。

Q: 我看到一些评论说 Rust 很难掌握,并且在我们的调查中,只有一小部分人(大约 5%)使用过 Rust。那么你认为是不是进入 Rust 的门槛比较高?为什么是,或不是?

A: 我认为 Rust 中确实有一些比较特定的概念,学起来和使用起来有一定的高门槛。不过有趣的是,我在 Rust 之前的背景是全栈 Web 开发和设计;我之前没有“系统级”或“函数式”语言的经验,我却发现学习 Rust 中的那些概念比学习其它已有语言更容易,所以我不赞同 Rust 整体来说门槛高这个说法。

我感觉许多门槛来自于 Rust 本身是一个相对新的编程语言,现在还没有来自其它视角(这些视角满足人们不同的思维模型)的丰富的资源供学习,就像那些已经很成熟的语言一样。可以指望的是,随着时间推移,我们会有更多不同方面的学习材料,来帮助改进教学和理解这些概念。

虽然只有一小部分人写过 Rust,但是它的采用率已经是一种成功了,许多人们日常使用的软件的关键部分已经用 Rust 重写,或用 Rust 创建了。Rust 在最大的五个科技公司的每一个中都被看见采用了。并且还不只是大企业感兴趣,小一点的科技公司,像 Dropbox 或 OneSignal,他们的服务的核心基础设施中有很多 Rust。

Florian Gilcher

Florian Gilcher 从 2013 年以来一直使用 Rust 编程。他从社区团队组建开始就是其中一员,并且现在是核心团队的一部分。Florian 联合组织了前 5 次 RustFest 和 OxidizeConf。在那之前,他活跃在 Ruby 社区。

Q: 使用 Rust的人看起来确实喜欢它;你觉得为什么会这样?

A: 第一简单反应是:因为在它许多方面是一个好的产品。Jake Goulding已经做了一个好的概述,因此我不准备在你的博客中重复了。

除此之外,我要强调几个我心中所爱之处:

  1. 谈及这门语言时,是自信的,而不是对抗的;
  2. 相当一些新的挑逗头脑的概念;
  3. 非常灵活的结构,能覆盖在其它工程中被忽略的许多东西。

我会稍微深入一点讲讲为什么那个很重要:许多编程语言和工具在市场宣传的时候是以对抗的和比较式的方式来做。“比 X 好”;“X 是新 Y”等等。Rust 总是采用让好的特性自己显露的方式。比如,一种廉价的框定 Rust 的方式是说,所有权和借用是对 C 和 C++ 问题的修复。然而,这会走向一个可怕的论点:他们虽然在许多事情上是好的,但是这个论点会立即把 Rust 置于 C 和 C++ 的对立面。这只会以愤怒的争论收场。Rust 出生于改进(业界)最前沿状态的欲望,它对它之前的语言怀着巨大的尊重。由于这个原因,我们宣传的所有权和借用是构建一个程序语言基石的有用概念。在这之上,是各种灵活多样的支撑点,这些支撑点支撑了 Rust 程序员的逻辑思考。我认为这种基本的积极的方式,形成了人们对这门语言的感觉体验。

这带出了第 2 个点):Rust 把之前停留在研究领域的新概念带到桌面上来了。这些概念其实在其它语言中也有。所有权就是这样一个例子:“我的程序中的哪一部分对这片数据负责?”在整个编程过程中,这都是一个值得问自己的好问题,但是 Rust 把它作为一个核心概念,严谨地对待它。花时间在 Rust 上的程序员会发现有东西让他变成更好的程序员,即使他们并不会立即把 Rust 作为他们选择使用的语言。这点对 Rust 来说不是唯一的(优点),但是经常被提到。

最后一点是,Rust 选择了一个全面的和灵活的工程结构,已经成功吸引了很多经验丰富的人。要创造一个 A+ 社区的工程也意味着我们处理的东西远不止代码。如果你看看团队结构,你会注意到有许多团队,他们的任务你并不会觉得是构建一个编程语言的核心任务。整体来说,我们包含一个社区和一个合理的核心团队,致力于文档建设的团队,还有一些专门领域工作组,比如嵌入式工作组等。这种结构总是处于动态变化中,并一直欢迎更多的(人们的)付出和经验。这允许我们保持灵活度,并快速应对人们的特定需求。这也意味着你的特定的问题总是能到达某个(专业的)人那里。

Q: Rust 团队要保证用户始终喜爱它的计划是什么?

A: 让一个伟大的产品变得更好。

对于每一段对 Rust 的良好工具和良好设计的表扬,仍然还有一堆的东西可以改进!

我不代表团队发言,但是这里是我个人的我想帮助其改进的列表:

  • 通过提供适合初学者群体的文档,来提升 Rust 的亲和力;
  • 提供更多本地化的文档,应该更有帮助;
  • 将 Rust 用在目前为止还未使用的工业环境(特别是安全攸关的系统)
  • 为所有常见平台解决现存的边界情况和问题;
  • 确保 Rust 有一个优秀的开箱即用的 IDE 体验。

我对这门语言现在的状态感到满意,聚焦于把已经不错的工具持续改进,算是一个好主意。

Q: 你会常规使用 Rust 吗? 为什么会这样?

A: 我每天都在使用 Rust,至少是思考它。我开了一家 Rust 咨询公司,训练其它人更好地使用 Rust。

Q: 我看到一些评论说 Rust 很难掌握,并且在我们的调查中,只有一小部分人(大约 5%)使用过 Rust。那么你认为是不是进入 Rust 的门槛比较高?为什么是,或不是?

从长期来看,相对于其它语言,我不认为 Rust 有一个更高的学习门槛。它是一门相当一致的语言,一旦你掌握了基础,它们可以把你载到非常远的地方。虽然在那条道路上立马会遭遇一些障碍:如果你想学会走路之前就跑的话,Rust 是所有语言中最坏的语言。原因在于它的核心概念,特别是所有权,在其它语言中没有对照的东西。然后这个概念又特别细致入微。这意味着 Rust 很难在一到两天内捡起。大部分人报告说他们大约需要一到两周才能使它产生生产力。已经在 Rust 上有生产力的人会感激这种严格和对正确性的努力,但是这需要一点时间来达到。

在过去几年,在业界和工具中,我们已经看到了一种对“立即得到生产力”这种观点的偏离,我能理解上 Rust 这条船的体验是多么不同于人们已习惯的许多其它语言。我希望我们找到了一种方式,在不损失长期体验的情况下,来提供这种(更好的)新手体验。


如果你正在寻找更多为何用户喜爱 Rust 的原因,daboross 建议了几个链接:

--
翻译:Mike Tang
时间:2020-06-24
链接:https://rustcc.cn/article?id=3ce10a05-9506-475d-8c8a-3ad74130ad83

转载请尊重原创版权。


Ext Link: https://stackoverflow.blog/2020/06/05/why-the-developers-who-use-rust-love-it-so-much/

评论区

写评论

还没有评论

1 共 0 条评论, 1 页