rust为什么显示不了国服_Rust编程语言初探

adc5fa481e38e9879d88d366d27fbd62.png

静态、强类型而又不带垃圾收集的编程语言领域内,很久没有新加入者参与竞争了,大概大部分开发者认为传统的C/C++的思路已经不太适合新时代的编程需求,即便有Ken Tompson这样的大神参与设计的golang也采用了GC的思路来设计其新一代的语言;一方面垃圾收集技术和即使编译技术一直在发展和完善,另一方面是大量的未经过严格计算机科学基础训练的开发人员进入市场,似乎让开发者永远停留在逻辑层面而不是去直接操纵内存是个更为现代的选择,Mozilla却仍然坚信一门静态而又高效低利用系统资源的“偏底层”的语言也依然会有巨大的生命力;于是站在现代成熟的软件工程实践上的Rustlang(以下简称Rust)为创造出来,其新版本的发布不时引起HackNews等极客圈的关注。

本文试图通过其官方文档对该语言(以及其相关的生态系统)做简单的研习。

核心语言特性设计目标

按照其官方描述,Rust需要满足其以下几个核心目标

  1. 适用于系统编程场景 - 这意味着能够有直接访问操作系统基础设施和硬件的能力。
  2. 开源参与和协作 - 毕竟其背后的推动者是创造了第一代浏览器的Mozilla,比任何商业公司更懂得依靠开源社区的力量
  3. 安全而又高效 - 在现代的软件工程环境中,安全是不可或缺的,而面向系统编程场景的语言必然少不了对性能的极致要求
  4. 充分利用现代多核和并发处理技术的能力 - 这也是传统的C/C++语言的软肋所在;同时也是Google的Golang的设计目标之一
  5. 容易学习的语法 - 减少类似于段错误或隐式的多线程编程等相对底层的细节应该尽量被隐藏

根据以上目标可以相对容易的理解一些核心的语言设计策略背后的决策依据。

基本语法特性

作为一门面向系统编程的偏底层的程序语言,其基本语法和传统的C/C++/Java系列语言共享了很多共同之处,这里仅需要看看其不同之处。

类型系统

静态语言的基本元素之一是变量和类型;不同的语言会选择不同的类型定义和内置的开箱可用的基本类型;这些类型及内置类的设计往往反映了编程语言设计者的决策策略和权衡要素。

类型声明和自动推断

毕竟要面对的是偏严肃的系统编程领域,选择静态类型可以在编译阶段尽可能早地发现更多的程序错误是题中之义;同时作为一门比较现代的编程语言,每次让程序员自己输入每个变量的类型这类臃肿的做法也被废弃,自动类型推断必不可少 - 当编译器可以”聪明地”推导出合适的类型的时候,变量类型指定可以忽略。

譬如需要声明一个某种类型的变量,Rust用let x: someType = 来表示;当然对于编译器可以推导出来类型的情况下,类型是可以省略的这样可以少写一些啰嗦的代码,let x = 2就会定义一个整数类型的变量x;比较新的编程语言基本都是这么做的,没有什么新意。

作为一门强类型的语言,任何变量或者表达式必须有唯一的类型,否则编译的时候就会报错。当然Rust支持一种特殊的变量隐藏机制(Shadow),即同一个名字的变量可以重新使用,并设置为一个完全不同的类型;这个时候原来的变量就不能被访问了。如

let var = "something"; //string literallet var = 1; //changed to int

这种机制从某种程度上来说,反而会使代码变得不太容易理解,如果程序员习惯了C/C++的编程方式的话;同时也会给IDE等工具的解析带来一些挑战;当然这个是仁者见仁智者见智的事情。

类型可变性约束

Rust要求所有定义的变量必须指定是否是可变的;并且作为变量的基本特征强制程序员做合理的选择。可变的变量用类似let mut varName:Type = value的语法来定义,顾名思义可以在声明之后被重新赋值修改;而不可变的变量少了一个mut关键字,其定义的变量在初始化一次后续就不能再修改了。

Rust里边同时支持常量类型,用const来声明,像是从C++里借鉴来的。它和可变类型mutable有一些细微的不同: 对于常量类型我们必须使用类型注解,不能声明可变的常量类型(不允许混合const和mut),而且常量类型只能被赋值为一个常量表达式, 不能用函数调用的结果或者是其他一些运行时计算出来的值来初始化。综合来看,Rust的常量类型和C++11中新引入的constexpr行为比较接近。

内置类型

内置类型一般用于提供大部分程序员都要用到的基本数据结构。除了一些其他语言都常见的基本类型(Rust称之为标量类型),Rust也提供了一些相对比较复杂的类型。

基本标量类型包含以下这些基本的类型

  • 整型类型,包括定长的8/16/32/64位的有符号和无符号类型(如u16是无符号16位整型,i32是有符号32位类型), 还支持平台相关的有符号/无符号类型,分别用isize和usize表示
  • 浮点类型,支持单精度(f32)和双精度(f64)类型,这些在数值计算的时候比较关键
  • 布尔类型,和C++中的比较类似,有true和false两种可能的取值,当然没有C/C++中的那些隐式转换的麻烦
  • 字符类型,支持Unicode
复合类型`

比较新一点的语言都支持一些复杂一点的基本组合类型。

tuple和其它语言的比较类似,用括号语法来声明,基本用法可以看下边这个简单的例子

let tup = (1, 2.2, "something")let (a, b, c) = tuplet secondElem = tup.1

第一行代码声明一个含有三个不同类型的元素的元组;第二行代码则将元组中的元素逐一取出,和Python的用法比较类似。除了这种提取方式,元组元素也可以用点语法来访问元素,如上边的第三行代码则用tup.1则取出第二个元素;比C++11的模板元语法简单多了。

数组则用于表示具有相同类型的元素的集合,如let arr = [1, 2, 3, 4, 5],如果类型不一致则会有编译错误报出。和C/C++这中的类似,数组元素一般是分配在栈上的,其大小在编译器应该是预先确定的;如果需要可变长的容器,则需要Vector类型。数组越界的检查默认也包含在语言中了,如果访问越界的下标,默认程序就会崩溃;当然Rust的错误处理机制也有些特殊,容后探讨。

容器类型

Rust支持以下基本的容器类型

  • Vector 该类型用于存储逻辑上的列表类型,其正式名字是Vec,用Vec::new()创建空的向量,因为其是用泛型实现的,我们必须指定类型注解;即使用 let v: Vec = Vec::new() 来生成一个新的向量v
  • String 是作为一个库提供的而不是基本的语言机制;其实现和C++的比较类似,内部也使用一个Vec来存储数据的,因此考虑到国际化的原因,其操作可能比其它语言中的要复杂一些;幸运的是,这些细节以及被标准库所封装。
  • Hashmap 用于表述逻辑上的哈希关联容器;其提供的API和C++/Java的比较类似,功能上比C++的复杂一些但比Java的更精简一点

函数

作为基本编程要素的函数在Rust中的定义没有什么特别特殊的地方,除了其类型声明是后置风格之外,其返回类型(如果不能被自动推断)用->来声明,比如

//一个返回int类型的函数fn thisIsAFunction(parA: i32, parB: string) -> int {    //some implementation}

函数的实现体本质上是一个block,由一系列的表达式组成(当然表达式也是用分号分隔的),同时它还支持Ruby风格的自动返回最后一个表达式的写法, 仅仅需要最后一个表达式省略分号即可;比如这个简单的函数

fn five() -> i32 {    5}

懒惰是伟大程序员的优良品质嘛。由于我们有内置的tuple类型,因此Rust是可以允许有多个返回值的;比较典型的一个场景是用户错误处理的情况,可以返回一个Result,同时携带错误码和可能的原因;稍后会仔细看一下异常处理的部分。

函数和宏

Rust本身支持语法层面的宏,并且其标准库提供了很多各种各样的宏,譬如最常用的打印函数其实就是一个宏;所有的宏使用!后缀来区分。 println!("The value of x is {}, y is {}", x, y)用于打印

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值