• rust类型


    内置类型列表:

    • 原生类型(primitive types):
      • 布尔型(Boolean) — true 或 false
      • 数字类(Numeric) — 整型(integer) 和 浮点型(float)
      • 文本类(Textual) — 字符型(char) 和 字符串切片(str)
      • never类型 — ! 没有值的类型
    • 序列类型(sequence types):
      • 元组(Tuple)
      • 数组(Array)
      • 切片(Slice)
    • 用户自定义类型(user-defined types):
      • 结构体(Struct)
      • 枚举(Enum)
      • 联合体(Union)
    • 函数类型(function types):
      • 函数(Functions)
      • 闭包(Closures)
    • 指针类型(pointer types):
      • 引用(References)
      • 裸指针(Raw pointers)
      • 函数指针(Function pointers)
    • trait类型(Trait types):
      • trait对象(Trait objects)
      • 实现trait(Impl trait)

    一、布尔类型

    bool
    布尔类型的大小为1个字节。

    二、数字类型

    1.整数

    长度有符号类型无符号类型
    8位i8u8
    16位i16u16
    32位i32u32
    64位i64u64
    128位i128u128
    视运行的cpu而定isizeusize

    isize 和 usize 类型取决于程序运行的CPU宽度: 若CPU是32位的,则这两个类型是32位的,若CPU是64位,那么它们则是64位。

    2.浮点数
    f32 32位
    f64 64位
    默认浮点类型是f64,在现代的CPU中它的速度与f32几乎相同,但精度更高。

    三、文本类型

    1.字符类型
    char
    4个字节,值是字符的Unicode码。取值范围为0x0000~0xD7FF0xE000~0x10FFFF

    2.字符串
    str
    str类型的值的表示方法与 [u8] 相同。但是,Rust标准库对 str 做了额外的限定:str的方法会假定数据是有效的UTF-8。
    由于 str 是一个动态大小类型,所以只能使用它的指针类型,比如&str。

    四、never类型

    用!表示
    never类型是一个没有值的类型。一些根本无返回值的情况,比如崩溃、break、continue等行为
    !类型的表达式可以自动转换为任何其他类型。

    在函数从不返回的时候充当返回值。例如:

    fn bar() -> ! {
         // --snip--
    }
    
    • 1
    • 2
    • 3

    这读 “函数bar从不返回”,而从不返回的函数被称为 发散函数(diverging functions)。不能创建 ! 类型的值,所以bar也不可能返回值。

    不过一个不能创建值的类型有什么用呢?

    let guess: u32 = match guess.trim().parse() {
         Ok(num) => num,
         Err(_) => panic!(),
    };
    
    • 1
    • 2
    • 3
    • 4

    match要求所有分支必须是相同类型的,为什么这里允许一个分支返回u32而另一个分支却是panic!()呢?因为panic!()的类型是 !,可以自动转换成u32。

    五、元组

    由多个不同类型组合成一个类型

    TupleType :
    ( )
    | ( ( Type , )+ Type? )
    
    • 1
    • 2
    • 3

    元组类型的语法规则为一对圆括号封闭的逗号分割的类型有序列表。一元元组的元素类型后面需要有一个逗号。
    元组类型的元素也叫字段。
    字段数是类型列表的长度。字段的数量决定元组的元数。有n个字段的元组叫做n元元组。例如,有两个字段的元组就是二元元组。
    元组有着固定的长度。一旦定义,就不能再增长或缩小。
    元组的字段用它在列表中的位置序号来索引。第一个字段索引为0。第二个字段索引为1。然后以此类推。

    不带元素的元组类型(),称为单元类型(unit type)。它的值称为单元值。
    元组类型的值是使用元组表达式来构造的。如果一个表达式没有其他有意义的值,那么将返回单元值。

    元组类型的示例:

    ()
    (f64, f64)
    (String, i32)
    (i32, String) 
    (i32, f64, Vec, Option)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    六、数组

    ArrayType :
    [ Type ; Expression ]
    
    • 1
    • 2

    数组是N个类型为T的元素组成的固定长度的序列,
    数组类型写为 [T; N]。
    长度是一个计算结果为 usize 的常量表达式。
    示例:

    let array: [i32; 3] = [1, 2, 3];// 一个栈分配的数组
    
    • 1

    数组的所有元素总是初始化过的,使用Rust中的安全方法或操作符来访问数组时总是会先做越界检查。

    七、切片(Slice)

    切片就是数组片段

    SliceType :
    [ Type ]
    
    • 1
    • 2

    切片是一种动态大小类型。切片的大小是运行时才可知的,并不是数组那种编译时就必须确定的。
    切片类型写为 [T]。但要使用切片类型时,必须使用它的指针类型,例如:
    &[T],共享切片(‘shared slice’),常直接称为切片(slice),它不拥有它指向的数据,只是借用。
    &mut [T],可变切片(‘mutable slice’),可变借用它指向的数据。
    示例:

    let slice: &[i32] = &boxed_array[..];// 数组上的切片
    
    • 1

    切片的所有元素总是初始化过的,使用Rust中的安全方法或操作符来访问切片时总是会做越界检查。

    八、结构体

    结构体是一种自定义的数据类型,它可以将多个不同类型组合在一起形成一个新的类型。这些其他类型称为结构体类型的字段
    结构体的实例可以用结构体表达式来构造。
    结构体的字段可以由可见性修饰符限定,以允许从模块之外来访问结构体中的数据。
    元组结构体类型与结构体类型类似,只是字段是匿名的。
    单元结构体类型类似于结构体类型,只是它没有字段。

    结构体与元组的区别是结构体的每个字段和其本身都有一个名字,这样访问字段的时候就不用记住下标了。

    九、枚举

    枚举是一种自定义的数据类型,它可以表示多个可能的值。

    十、联合体

    联合体类型是一种类似C语言里的union的类型,具体的类型名称由联合体项的名称表示。
    声明联合体和声明结构体的语法一样,除了用 union 代替 struct外

    十一、函数

    当引用函数时,会产生函数类型的值。
    例子

    fn foo() { }
    let x = &mut foo::;
    *x = foo::; // 错误:类型不匹配
    
    • 1
    • 2
    • 3

    函数类型到函数指针的自动强转

    // 这里 `foo_ptr_1` 标注使用了 `fn()` 这个函数指针类型。
    let foo_ptr_1: fn() = foo::;
    // ... `foo_ptr_2`  类型自动推断。
    let foo_ptr_2 = if want_i32 {
              foo::
         } else {
             foo::
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    十二、闭包

    闭包类型相当于包含捕获变量的结构体。
    比如以下闭包示例:

    fn f String> (g: F) {
         println!("{}", g());
    }
    let mut s = String::from("foo");
    let t = String::from("bar");
    f(|| {
         s += &t;
         s
    });
    // 打印 "foobar".
    生成大致如下所示的闭包类型:
    struct Closure<'a> {
         s : String,
         t : &'a String,
    }
    impl<'a> FnOnce<()> for Closure<'a> {
         type Output = String;
         fn call_once(self) -> String {
             self.s += &*self.t;
             self.s
         }
    }
    所以调用f相当于:
    f(Closure{s: s, t: &t});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    十三、引用

    Rust中所有的指针都是显式的头等(first-class)值。 它们可以被移动或复制,存储到其他数据结构中,或从函数中返回。

    ReferenceType :
       & Lifetime? mut? TypeNoBounds
    
    • 1
    • 2

    共享引用(&)
    共享引用(&)指向由其他值拥有的内存。不可更改其值。对一个值的共享引用的次数没有限制。
    共享引用类型被写为 &type;当需要指定显式的生存期时可写为 &'a type。

    可变引用(&mut)
    可变引用(&mut)也指向其他值所拥有的内存。可更改其值。对一个值只能有一个可变引用。
    可变引用类型被写为 &mut type或 &'a mut type。

    十四、裸指针

    RawPointerType :
       * ( mut | const ) TypeNoBounds
    
    • 1
    • 2

    裸指针是没有安全性保证的指针。
    裸指针写为 *const T或 *mut T,例如,*const i32表示指向32-bit有符号整数的裸指针。拷贝或销毁裸指针对任何其他值的生命期都没有影响。对 裸指针的解引用是非安全操作,可以通过重新借用裸指针(&* 或 &mut *)将其转换为引用。
    在Rust代码中不鼓励使用裸指针;它们是为了提升与外部代码的互操作性,以及编写对性能要求很高的函数或很底层的函数。
    在比较裸指针时,比较的是它们的地址,而不是它们指向的数据。当比较裸指针和动态尺寸类型时,还会比较它们指针上的附加/元数据。
    可以直接使用 core::ptr::addr_of! 创建 *const类型的裸指针,通过 core::ptr::addr_of_mut! 创建 *mut类型的裸指针。

    十五、函数指针

    BareFunctionType :
    ForLifetimes? unsafe? (extern Abi?)? fn( FunctionParametersMaybeNamedVariadic? ) -> TypeNoBounds?
    
    • 1
    • 2

    函数指针类型指向那些在编译时不必知道名字的函数。它们也可以由函数类型或非捕获闭包经过自动强转而来。
    非安全(unsafe)限定符表示类型的值是一个非安全函数,而外部(extern)限定符表示它是一个外部函数。
    示例

    fn add(x: i32, y: i32) -> i32 {
         x + y
    }
    let mut x = add(5,7);
    type Binop = fn(i32, i32) -> i32;     //Binop为函数指针类型:
    let bo: Binop = add;
    x = bo(5,7);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    十六、trait对象

    TraitObjectType :
       dyn? TypeParamBounds
    TraitObjectTypeOneBound :
       dyn? TraitBound
    
    • 1
    • 2
    • 3
    • 4

    trait对象是关键字dyn后跟一组trait约束。
    trait对象是动态尺寸类型。像所有的 DST 一样,trait对象常被用在某种类型的指针后面;例如 &dyn SomeTraitBox
    例子:

    trait Printable {
         fn stringify(&self) -> String;
    }
    impl Printable for i32 {
         fn stringify(&self) -> String { self.to_string() }
    }
    impl Printable for f32 {
         fn stringify(&self) -> String { self.to_string() }
    }
    fn print(a: Box) {
         println!("{}", a.stringify());
    }
    fn main() {
         print(Box::new(10));
         print(Box::new(10.0));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    十七、实现trait

    ImplTraitType : impl TypeParamBounds
    ImplTraitTypeOneBound : impl TraitBound
    
    • 1
    • 2

    impl后跟一组trait约束

    trait作为函数参数类型

    trait Trait {}
    fn foo(arg: impl Trait) {}
    
    • 1
    • 2

    trait作为函数返回值类型

    fn bar() -> impl Trait {}
    
    • 1

    十八、自动推断型类型

    InferredType : _
    
    • 1

    编译器自动推断出实际使用类型。它只用于泛型参数中:

    let x: Vec<_> = (0..10).collect();
    
    • 1
  • 相关阅读:
    SpringCloud Alibaba - 基于 FeignClient 整合 Sentinel,实现“线程隔离”和“熔断降级”
    使用FreeMarker导出word文档(支持循环导出实时多张图片)
    基于springboot的校园跑腿系统
    13链表-简单思路练习
    银行卡四要素API接口的验证流程
    C/C++内存管理
    七天入门node.js(05)
    【NLP基础】英文关键词抽取RAKE算法
    电源芯片的选择简略
    TensorFlow实战教程(十七)-Keras搭建分类神经网络及MNIST数字图像案例分析
  • 原文地址:https://blog.csdn.net/inxunxun/article/details/133588677