Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Installation and Setup
安装与环境准备

What you’ll learn: How to install Rust and set up your IDE, the Cargo build system vs MSBuild/NuGet, your first Rust program compared to C#, and how to read command-line input.
本章将学到什么: 如何安装 Rust 并配置开发环境,Cargo 构建系统和 MSBuild / NuGet 的对应关系,第一段 Rust 程序和 C# 的对照,以及如何读取命令行输入。

Difficulty: 🟢 Beginner
难度: 🟢 入门

Installing Rust
安装 Rust

# Install Rust (works on Windows, macOS, Linux)
# 安装 Rust(Windows、macOS、Linux 都可用)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# On Windows, you can also download from: https://rustup.rs/
# 在 Windows 上也可以直接从这个地址下载安装包:https://rustup.rs/

Rust Tools vs C# Tools
Rust 工具链与 C# 工具链对照

C# Tool
C# 工具
Rust Equivalent
Rust 对应物
Purpose
作用
dotnet newcargo newCreate new project
创建新项目
dotnet buildcargo buildCompile project
编译项目
dotnet runcargo runRun project
运行项目
dotnet testcargo testRun tests
运行测试
NuGetCrates.ioPackage repository
包仓库
MSBuildCargoBuild system
构建系统
Visual StudioVS Code + rust-analyzerIDE
集成开发环境

IDE Setup
IDE 配置

  1. VS Code (Recommended for beginners)
    1. VS Code(适合刚上手的人)

    • Install the rust-analyzer extension
      安装 rust-analyzer 扩展
    • Install CodeLLDB for debugging
      安装 CodeLLDB 作为调试器
  2. Visual Studio (Windows)
    2. Visual Studio(Windows)

    • Install a Rust support extension
      安装 Rust 支持扩展
  3. JetBrains RustRover (Full IDE)
    3. JetBrains RustRover(完整 IDE)

    • Similar to Rider for C# developers
      对 C# 开发者来说,使用感受和 Rider 比较接近

Your First Rust Program
第一段 Rust 程序

C# Hello World
C# 版 Hello World

// Program.cs
using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

Rust Hello World
Rust 版 Hello World

// main.rs
fn main() {
    println!("Hello, World!");
}

Key Differences for C# Developers
C# 开发者需要先记住的差别

  1. No classes required - Functions can exist at the top level
    1. 不需要类,函数可以直接定义在顶层。
  2. No namespaces - Uses module system instead
    2. 没有 namespace,Rust 用模块系统组织代码。
  3. println! is a macro - Notice the !
    3. println! 是宏,后面的 ! 不是摆设。
  4. No semicolon after println! - Expression vs statement
    4. println! 这一段开始要慢慢习惯 Rust 里“表达式”和“语句”的区别。
  5. No explicit return type - main returns () (unit type)
    5. 没有显式返回类型main 默认返回 (),也就是单元类型。

Creating Your First Project
创建第一个项目

# Create new project (like 'dotnet new console')
# 创建新项目(相当于 'dotnet new console')
cargo new hello_rust
cd hello_rust

# Project structure created:
# 生成出来的项目结构:
# hello_rust/
# ├── Cargo.toml      (like .csproj file)
# │                   (相当于 .csproj 文件)
# └── src/
#     └── main.rs     (like Program.cs)
#                      (相当于 Program.cs)

# Run the project (like 'dotnet run')
# 运行项目(相当于 'dotnet run')
cargo run

Cargo vs NuGet/MSBuild
Cargo 与 NuGet / MSBuild 的对应关系

Project Configuration
项目配置文件

C# (.csproj)
C#(.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>
  
  <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  <PackageReference Include="Serilog" Version="3.0.1" />
</Project>

Rust (Cargo.toml)
Rust(Cargo.toml

[package]
name = "hello_rust"
version = "0.1.0"
edition = "2021"

[dependencies]
serde_json = "1.0"    # Like Newtonsoft.Json
log = "0.4"           # Like Serilog

Common Cargo Commands
常用 Cargo 命令

# Create new project
# 创建新项目
cargo new my_project
cargo new my_project --lib  # Create library project
                             # 创建库项目

# Build and run
# 编译与运行
cargo build          # Like 'dotnet build'
cargo run            # Like 'dotnet run'
cargo test           # Like 'dotnet test'

# Package management
# 包管理
cargo add serde      # Add dependency (like 'dotnet add package')
cargo update         # Update dependencies

# Release build
# 发布构建
cargo build --release  # Optimized build
cargo run --release    # Run optimized version

# Documentation
# 文档
cargo doc --open     # Generate and open docs

Workspace vs Solution
Workspace 与 Solution 的对照

C# Solution (.sln)
C# 的 Solution(.sln

MySolution/
├── MySolution.sln
├── WebApi/
│   └── WebApi.csproj
├── Business/
│   └── Business.csproj
└── Tests/
    └── Tests.csproj

Rust Workspace (Cargo.toml)
Rust 的 Workspace(写在 Cargo.toml 里)

[workspace]
members = [
    "web_api",
    "business", 
    "tests"
]

Reading Input and CLI Arguments
读取输入与命令行参数

Every C# developer knows Console.ReadLine(). Here’s how Rust handles user input, environment variables, and command-line arguments.
Console.ReadLine() 写 C# 的都熟,Rust 这边处理用户输入、环境变量和命令行参数的方式也得顺手摸清。

Console Input
控制台输入

// C# — reading user input
// C#:读取用户输入
Console.Write("Enter your name: ");
string? name = Console.ReadLine();  // Returns string? in .NET 6+
Console.WriteLine($"Hello, {name}!");

// Parsing input
// 解析输入
Console.Write("Enter a number: ");
if (int.TryParse(Console.ReadLine(), out int number))
{
    Console.WriteLine($"You entered: {number}");
}
else
{
    Console.WriteLine("That's not a valid number.");
}
use std::io::{self, Write};

fn main() {
    // Reading a line of input
    // 读取一行输入
    print!("Enter your name: ");
    io::stdout().flush().unwrap(); // flush because print! doesn't auto-flush
                                  // print! 不会自动刷新,所以要手动 flush

    let mut name = String::new();
    io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim(); // remove trailing newline
                            // 去掉结尾换行
    println!("Hello, {name}!");

    // Parsing input
    // 解析输入
    print!("Enter a number: ");
    io::stdout().flush().unwrap();

    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("Failed to read");
    match input.trim().parse::<i32>() {
        Ok(number) => println!("You entered: {number}"),
        Err(_)     => println!("That's not a valid number."),
    }
}

Command-Line Arguments
命令行参数

// C# — reading CLI args
// C#:读取命令行参数
static void Main(string[] args)
{
    if (args.Length < 1)
    {
        Console.WriteLine("Usage: program <filename>");
        return;
    }
    string filename = args[0];
    Console.WriteLine($"Processing {filename}");
}
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    // args[0] = program name (like C#'s Assembly name)
    // args[1..] = actual arguments
    // args[0] 是程序名,args[1..] 才是真正传进来的参数

    if args.len() < 2 {
        eprintln!("Usage: {} <filename>", args[0]); // eprintln! -> stderr
                                                    // eprintln! 会写到标准错误
        std::process::exit(1);
    }
    let filename = &args[1];
    println!("Processing {filename}");
}

Environment Variables
环境变量

// C#
string dbUrl = Environment.GetEnvironmentVariable("DATABASE_URL") ?? "localhost";
#![allow(unused)]
fn main() {
use std::env;

let db_url = env::var("DATABASE_URL").unwrap_or_else(|_| "localhost".to_string());
// env::var returns Result<String, VarError> — no nulls!
// env::var 返回的是 Result<String, VarError>,不会给个 null 糊弄过去
}

Production CLI Apps with clap
clap 编写正式 CLI 程序

For anything beyond trivial argument parsing, use the clap crate. It fills the role that System.CommandLine or CommandLineParser libraries play in C#.
只要参数解析稍微复杂一点,就该把 clap 拿出来了。它在 Rust 里的定位,大致就和 C# 里的 System.CommandLineCommandLineParser 一个级别。

# Cargo.toml
[dependencies]
clap = { version = "4", features = ["derive"] }
use clap::Parser;

/// A simple file processor — this doc comment becomes the help text
/// 一个简单的文件处理器,这段文档注释会直接变成帮助文本
#[derive(Parser, Debug)]
#[command(name = "processor", version, about)]
struct Args {
    /// Input file to process
    /// 要处理的输入文件
    #[arg(short, long)]
    input: String,

    /// Output file (defaults to stdout)
    /// 输出文件,默认写到标准输出
    #[arg(short, long)]
    output: Option<String>,

    /// Enable verbose logging
    /// 打开详细日志
    #[arg(short, long, default_value_t = false)]
    verbose: bool,

    /// Number of worker threads
    /// 工作线程数量
    #[arg(short = 'j', long, default_value_t = 4)]
    threads: usize,
}

fn main() {
    let args = Args::parse(); // auto-parses, validates, generates --help
                              // 自动解析、校验,并生成 --help

    if args.verbose {
        println!("Input:   {}", args.input);
        println!("Output:  {:?}", args.output);
        println!("Threads: {}", args.threads);
    }

    // Use args.input, args.output, etc.
    // 后面直接使用 args.input、args.output 等字段即可
}
# Auto-generated help:
# 自动生成的帮助信息:
$ processor --help
A simple file processor

Usage: processor [OPTIONS] --input <INPUT>

Options:
  -i, --input <INPUT>      Input file to process
  -o, --output <OUTPUT>    Output file (defaults to stdout)
  -v, --verbose            Enable verbose logging
  -j, --threads <THREADS>  Number of worker threads [default: 4]
  -h, --help               Print help
  -V, --version            Print version
// C# equivalent with System.CommandLine (more boilerplate):
// C# 里用 System.CommandLine 的对应写法,样板代码会更多一些:
var inputOption = new Option<string>("--input", "Input file") { IsRequired = true };
var verboseOption = new Option<bool>("--verbose", "Enable verbose logging");
var rootCommand = new RootCommand("A simple file processor");
rootCommand.AddOption(inputOption);
rootCommand.AddOption(verboseOption);
rootCommand.SetHandler((input, verbose) => { /* ... */ }, inputOption, verboseOption);
await rootCommand.InvokeAsync(args);
// clap's derive macro approach is more concise and type-safe
// clap 用 derive 宏写起来更紧凑,类型约束也更自然
C#RustNotes
说明
Console.ReadLine()io::stdin().read_line(&mut buf)Must provide buffer, returns Result
必须先准备缓冲区,返回 Result
int.TryParse(s, out n)s.parse::<i32>()Returns Result<i32, ParseIntError>
返回 Result<i32, ParseIntError>
args[0]env::args().nth(1)Rust args[0] = program name
Rust 里的 args[0] 是程序名。
Environment.GetEnvironmentVariableenv::var("KEY")Returns Result, not nullable
返回 Result,不是可空引用。
System.CommandLineclapDerive-based, auto-generates help
基于 derive,能自动生成帮助信息。