从零开始学 Rust:基本概念——变量、数据类型、函数、控制流

文章目录

    • [Variables and Mutability](#Variables and Mutability)
    • [Data Types](#Data Types)
      • [Scalar Types](#Scalar Types)
      • [Compound Types](#Compound Types)
    • Functions
      • [Function Parameters](#Function Parameters)
    • Comments
    • [Control Flow](#Control Flow)
      • [Repetition with Loops](#Repetition with Loops)

Variables and Mutability

rust 复制代码
fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}
rust 复制代码
fn main() {
    let x = 5;
    let x = x + 1;
    let x = x * 2;
    println!("The value of x is: {}", x);
}
  • constant: const MAX_POINTS: u32 = 100_000;

Shadowing

The other difference between mut and shadowing is that because we're effectively creating a new variable when we use the let keyword again, we can change the type of the value but reuse the same name.

Data Types

Keep in mind that Rust is a statically typed language, which means that it must know the types of all variables at compile time.

Scalar Types

  • Integer Types

    • Signed numbers are stored using two's complement representation.
    • Each signed variant can store numbers from − ( 2 n − 1 ) -(2^{n - 1}) −(2n−1) to 2 n − 1 − 1 2^{n - 1} - 1 2n−1−1 inclusive, where n is the number of bits that variant uses. So an i8 can store numbers from − ( 2 7 ) -(2^7) −(27) to 2 7 − 1 2^7 - 1 27−1, which equals -128 to 127. Unsigned variants can store numbers from 0 to 2 n − 1 2^n - 1 2n−1, so a u8 can store numbers from 0 to 2 8 − 1 2^8 - 1 28−1, which equals 0 to 255.
    • The isize and usize types depend on the kind of computer your program is running on: 64 bits if you're on a 64-bit architecture and 32 bits if you're on a 32-bit architecture.
    • All number literals except the byte literal allow a type suffix, such as 57u8, and _ as a visual separator, such as 1_000.
    • Integer Overflow
  • Floating-Point Types

    rust 复制代码
    fn main() {
        let x = 2.0; // f64
        let y: f32 = 3.0; // f32
    }
  • The Boolean Type

  • The Character Type

    • Rust's char type is four bytes in size and represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII.

Compound Types

  • The Tuple Type

    • Tuples have a fixed length: once declared, they cannot grow or shrink in size.

      rust 复制代码
      fn main() {
          let tup: (i32, f64, u8) = (500, 6.4, 1);
      }
    • destructure by pattern matching:

      rust 复制代码
      fn main() {
          let tup = (500, 6.4, 1);
          let (x, y, z) = tup;
          println!("The value of y is: {}", y);
      }
    • period(.):

      rust 复制代码
      fn main() {
          let x: (i32, f64, u8) = (500, 6.4, 1);
          let five_hundred = x.0;
          let six_point_four = x.1;
          let one = x.2;
      }
  • The Array Type (fixed length)

    rust 复制代码
    fn main() {
        let a = [1, 2, 3, 4, 5];
    }
    rust 复制代码
    let a: [i32; 5] = [1, 2, 3, 4, 5];
    rust 复制代码
    let a = [3; 5];
    rust 复制代码
    let a = [3, 3, 3, 3, 3];
    • An array is a single chunk of memory allocated on the stack.
    • Invalid Array Element Access

Functions

You've also seen the fn keyword, which allows you to declare new functions.

Rust code uses snake case as the conventional style for function and variable names.

rust 复制代码
fn main() {
    println!("Hello, world!");

    another_function();
}

fn another_function() {
    println!("Another function.");
}

Rust doesn't care where you define your functions, only that they're defined somewhere.

Function Parameters

  • 形参 parameter
  • 实参 argument
rust 复制代码
fn main() {
    another_function(5, 6);
}

fn another_function(x: i32, y: i32) {
    println!("The value of x is: {}", x);
    println!("The value of y is: {}", y);
}
  • Statements are instructions that perform some action and do not return a value.
  • Expressions evaluate to a resulting value.
  • Statements do not return values. Therefore, you can't assign a let statement to another variable.
rust 复制代码
fn main() {
    let x = 5;

    let y = {
        let x = 3;
        x + 1
    };

    println!("The value of y is: {}", y);
}

This expression:

rust 复制代码
{
    let x = 3;
    x + 1
}

is a block that, in this case, evaluates to 4. That value gets bound to y as part of the let statement. Note the x + 1 line without a semicolon at the end, which is unlike most of the lines you've seen so far. Expressions do not include ending semicolons. If you add a semicolon to the end of an expression, you turn it into a statement, which will then not return a value.

In Rust, the return value of the function is synonymous with the value of the final expression in the block of the body of a function. You can return early from a function by using the return keyword and specifying a value, but most functions return the last expression implicitly.

rust 复制代码
fn five() -> i32 {
    5
}

fn main() {
    let x = five();

    println!("The value of x is: {}", x);
}
rust 复制代码
fn main() {
    let x = plus_one(5);

    println!("The value of x is: {}", x);
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

Comments

Control Flow

rust 复制代码
fn main() {
    let number = 3;

    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }
}

It's also worth noting that the condition in this code must be a bool.

Rust will not automatically try to convert non-Boolean types to a Boolean. You must be explicit and always provide if with a Boolean as its condition.

rust 复制代码
fn main() {
    let condition = true;
    let number = if condition { 5 } else { 6 };

    println!("The value of number is: {}", number);
}

In this case, the value of the whole if expression depends on which block of code executes. This means the values that have the potential to be results from each arm of the if must be the same type.

Repetition with Loops

  • loop

    The loop keyword tells Rust to execute a block of code over and over again forever or until you explicitly tell it to stop.

    rust 复制代码
    fn main() {
        let mut counter = 0;
    
        let result = loop {
            counter += 1;
    
            if counter == 10 {
                break counter * 2;
            }
        };
    
        println!("The result is {}", result);
    }
  • while

    rust 复制代码
    	fn main() {
    	    let mut number = 3;
    	
    	    while number != 0 {
    	        println!("{}!", number);
    	
    	        number -= 1;
    	    }
    	
    	    println!("LIFTOFF!!!");
    	}
  • for

    rust 复制代码
    fn main() {
        let a = [10, 20, 30, 40, 50];
    
        for element in a.iter() {
            println!("the value is: {}", element);
        }
    }
    rust 复制代码
    fn main() {
        for number in (1..4).rev() {
            println!("{}!", number);
        }
        println!("LIFTOFF!!!");
    }
相关推荐
掘根10 小时前
【消息队列项目】客户端四大模块实现
开发语言·后端·ruby
疯狂的挖掘机16 小时前
记一次基于QT的图片操作处理优化思路(包括在图上放大缩小,截图,画线,取值等)
开发语言·数据库·qt
cnxy18816 小时前
围棋对弈Python程序开发完整指南:步骤4 - 提子逻辑和劫争规则实现
开发语言·python·机器学习
NAGNIP16 小时前
多个 GitHub 账户SSH 密钥配置全攻略
后端
NAGNIP16 小时前
Windows命令行代码自动补全详细步骤
后端
意趣新16 小时前
C 语言源文件从编写完成到最终生成可执行文件的完整、详细过程
c语言·开发语言
追逐时光者17 小时前
精选 8 款 .NET 开源、前后端分离的快速开发框架,提高开发生产效率!
后端·.net
李艺为17 小时前
根据apk包名动态修改Android品牌与型号
android·开发语言
古城小栈17 小时前
Rust变量设计核心:默认不可变与mut显式可变的深层逻辑
算法·rust
用户479492835691517 小时前
性能提升 4000%!我是如何解决 运营看板 不能跨库&跨库查询慢这个难题的
数据库·后端·postgresql