📕
innohub
  • KEEP LEARNING
  • WebInfo
    • JS 部分运算符操作
    • javascript 中的object array
    • 错误处理以及异常捕获
    • JavaScript Bases
    • LaoZi & Confucius
  • PyInfo
    • Python3 输入与输出
    • Python3OS
    • python 修饰器的使用
    • python3 与mysql数据库连接使用实例
    • Format-specifier
    • CGI初学踩坑
    • Django 项目测试
    • Assert-info
    • 使用ngnix和uWSGI配置Django
    • write|SVN​
    • Matplotlib 基本使用
    • 重读 Python 官方文档
    • Python3 Base
    • python3 多线程
    • Python3 函数解析
    • python3 str 对象的基本操作
    • protocl buffers
    • Iterator-Generator
    • Django base
    • Decorator 2
    • Export to wheel or egg-info
    • 三. 运算、数据及逻辑
  • GoInfo
    • Info
      • Select 语句使用
      • First class function
      • Work Pools
      • StructTag
      • Go struct
      • 常用函数
      • Strings操作
      • Golang Bases
      • 数组以及切片
      • 文件操作
      • Golang 中的指针类型
      • Golang Map 类型
      • Reflection
      • 函数闭包
      • 接口
      • Panic and Recover
      • Go中的错误处理
      • 并发
      • defer usage
      • Method in golang
      • Object-oriented Programming
      • Goalng 包管理机制
  • RustInfo
    • Info
      • 包、crate、模块
      • Rust 中的错误处理
      • 智能指针
      • 泛型 generics
      • 数据布局与内存对齐
      • Functions and methods
      • 无畏并发
      • Actix-web 基本使用
      • Got from guessing game
      • 结构体的使用
      • Rust 中的函数式语言功能
      • 集合类型
      • 枚举以及模式匹配
      • Slice 类型
      • 生命周期
      • 测试
      • Rust 中的所有权
      • trait
      • 不安全 Rust
      • Format_print
      • Rust 通用编程概念
      • Macro
  • OS
    • info
      • 内存屏障 -- Part 1
      • 内存屏障 -- Part 2
      • CPU 上下文切换
      • 文件读写与零拷贝
      • ELF 文件
  • MySql
    • info
      • MySql 架构与历史
      • 02-key
  • kubernetes
    • 第二章 k8s 基本概念
    • 第一章 Kubernetes -- 伟大舵手
  • Redis
    • info
      • Redis 总览
      • 02-underline-ds
  • Shell&CInfo
    • GCC 与make的使用
    • C++ 中 malloc 与 new
    • 位运算符操作
    • Base of C macro
    • C 语言中 extern 关键字的用法
  • Distributed
    • info
      • 分布式理论概述
  • Java
    • info
      • Java 内存模型
  • Prometheus
    • Prometheus -- 不灭之火
Powered by GitBook
On this page
  • 1. 定义结构体
  • 没有任何字段的结构体
  • 2. 结构体变量的创建
  • 2.1 变量与字段同名
  • 2.2 使用其他实例的值构建实例
  • 3. 结构体的所有权
  • 4. 结构体的方法
  • 4.1 自动引用与解引用
  • 4.2 关联函数(associated function)
  • 4.3 通过 trait 增加其他功能

Was this helpful?

  1. RustInfo
  2. Info

结构体的使用

[TOC]

1. 定义结构体

使用关键字struct定义结构体,定义每一个字段(field)名称以及对应的数据类型。

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

也可以定义类似元组的结构体,可以使用()进行定义,不需要指明每一个字段的名称,只需要指明每一个字段的类型,以及结构体的类型。注意,即使具有相同字段的元组结构体,但是类型不同,不可以相互间进行赋值。使用元组结构体中的字段时,可以使用点操作符,后面跟上字段的顺序。color.0, color.2.

没有任何字段的结构体

可以定义一个没有任何字段的结构体!它们被称为 类单元结构体(unit-like structs)因为它们类似于 (),即 unit 类型。类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用。

2. 结构体变量的创建

通过为每一个字段指定一个具体值来创建一个实例。对于普通结构体使用大括号以及key: value创建,元组结构体使用小括号,以参数形式构建。为了获取某一个实例的属性,可以使用点操作符。需要改变某一个实例的属性,需要将实例定义为可变类型。注意整个实例可以是可变的,不可以是某些字段可变,某些不可变。

let mut user1 = User {
    email: String::from("someone@example.com"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1,
};

user1.email = String::from("anotheremail@example.com");

2.1 变量与字段同名

当变量与字段同名时可以省略字段的名称,直接使用变量构建结构体。

fn build_user(email: String, username: String) -> User {
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
}

2.2 使用其他实例的值构建实例

可以使用结构体更新语法构建新的变量,可以直接使用点操作符,指定某些字段。也可以使用..ins指定之后的字段都是用ins的值。

 let user2 = User {
    email: String::from("another@example.com"),
    username: String::from("anotherusername567"),
    ..user1
};

3. 结构体的所有权

如果在结构体的字段中使用不拥有所有权的值,比如&str,必须指明生命周期。为了使得结构体拥有其所有数据,也就是结构体有效时,所有的属性也有效。

4. 结构体的方法

对于结构体的使用,可以定义常规的函数,将结构体作为参数进行使用。也可以在结构体上定义相应的方法,通过impl语句块实现相应的功能。

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

为一个结构体定义方法的方式与golang中的概念相似。通过使用impl语句块,保证了方法的接收器是某种确定的类型。注意对于方法语句,第一个参数需要是self,可以根据是否需要传递所有权,是否需要改变变量确定是否使用引用。&self, &mut self。上面的area方法通过借用一个Rectangle变量实现了相应的计算。由于这里的使用不需要获取所有权,只进行变量的读取,所以借用即可满足需求。如果需要进行变量值的写入,可以使用可变引用&mut self。

只使用self作为方法的第一个参数比较少见,一般适用于方法将self转化为别的实例时。

使用方法替代函数的好处:

  • 不需要在每一个函数中重复self的类型

  • 提高了代码的可组织性,将关于一个类型的方法全部放入一个代码块中,而不是要在所有的函数中寻找相应代码

4.1 自动引用与解引用

Rust与golang在方法的处理上就有相似的手法。一个方法定义时的第一个参数类型是引用,如果需要调用时,可以不使用引用类型,而是直接使用值进行调用。编译器自动进行引用操作。如果是一个指针类型调用方法,自动进行解引用操作。

当使用 object.something() 调用方法时,Rust 会自动为 object 添加 &、&mut 或 * 以便使 object 与方法签名匹配。

4.2 关联函数(associated function)

可以在impl块中定义第一个参数不是self的方法,从而实现关联函数。这些函数与结构体相关,但不是结构体的方法,任然是函数。一个典型的实例是String::from就是一个关联函数。

同时,对于一个结构体,可以定义多个impl块分别用来定义几个相对独立的方法块。

// methods impl rectangle
impl Rectangle {
    pub fn area(&self) -> u64 {
        self.width * self.length
    }

    pub fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.length > other.length
    }

    // associated function of the struct
    pub fn Square(size: u64) -> Rectangle {
        Rectangle{width: size, length: size}
    }

    pub fn Increase(&mut self, wid: u64, len: u64) {
        self.width += wid;
        self.length += len;
    }
}

4.3 通过 trait 增加其他功能

关于println!宏可以处理格式化输出。对于自定义类型如果使用{}进行格式化输出,输出的是std::fmt::Display.对于所有的基本类型,都实现了该trait。但是对于结构体类型,由于输出的格式是不明确的。Rust不会试图猜测用户的意图,所以需要实现相应的trait。

如果使用{:?}的格式需要实现std::fmt::Debugtrait。可以通过注释在结构体定义前显式添加 #[derive(debug)] 实现默认的打印调试信息的功能。使用{:#?}可以输出详细的定义。

PreviousGot from guessing gameNextRust 中的函数式语言功能

Last updated 5 years ago

Was this helpful?