Rust: Tipos-chave na Biblioteca Padrão do Rust
Última atualização: 2026-08-26
A biblioteca padrão do Rust (std) fornece tipos essenciais para interagir com o sistema operacional — medição de tempo, variáveis de ambiente, gerenciamento de processos e operações de caminho. Ao dominar esses tipos, seus programas em Rust serão capazes de se comunicar de fato com o sistema.
Se a própria linguagem Rust é o “motor”, então a biblioteca padrão é o “volante, o painel de instrumentos e o sistema de navegação”. Sem a biblioteca padrão, seu programa só consegue realizar cálculos básicos (adição, subtração, multiplicação e divisão; concatenação de strings). Com a biblioteca padrão, seu programa pode determinar a hora atual, ler argumentos da linha de comando, executar comandos externos e manipular caminhos de arquivos — tornando-se, assim, um verdadeiro “aplicativo”.
1. O que você vai aprender
std::time::Durationestd::time::Instant— Medição de intervalos de tempo e cronometragem de programasstd::time::SystemTime— Obtendo a hora do sistema operacionalstd::env::args— Ler argumentos da linha de comandostd::env::var— Como ler e definir variáveis de ambientestd::process::Command— Executar um comando externo e recuperar a saídastd::path::PathePathBuf— Operações de caminho multiplataforma
2. A história do script de backup programado
(1) O incômodo: o incômodo dos backups manuais
Tom é um engenheiro de operações que precisa fazer manualmente o backup de dados importantes dos servidores todos os dias antes de sair do trabalho. Esse processo é um verdadeiro pesadelo para ele:
- Ele precisa fazer login no servidor e digitar manualmente o comando
tar - Os nomes dos arquivos de backup devem incluir a data —
backup_20260703.tar.gz—, pois ele costuma digitá-la errado. - O caminho do backup está armazenado em uma variável de ambiente, mas preciso verificá-lo todas as vezes usando
echo $BACKUP_PATH - Ele quer escrever um script de automação, mas nunca sabe há quanto tempo o programa está em execução.
- Os separadores de caminho variam de acordo com o sistema operacional — o Windows usa
\, enquanto o Linux usa/
“Se eu pudesse escrever um programa em Rust que recuperasse automaticamente a hora atual, lesse o caminho do backup a partir das variáveis de ambiente, executasse o comando de compactação e registrasse o tempo de processamento... isso seria perfeito.”
(2) A abordagem da Biblioteca Padrão do Rust
use std::time::{Instant, SystemTime, UNIX_EPOCH};
use std::env;
use std::process::Command;
fn main() {
let start = Instant::now();
println!("=== Scheduled Backup Script ===");
// 1. Get the current system time
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
println!("[Time] Currently Unix Timestamp: {}s", now);
// 2. Read Environment Variables
let backup_dir = env::var("BACKUP_DIR")
.unwrap_or_else(|_| String::from("./backup"));
let db_name = env::var("DB_NAME")
.unwrap_or_else(|_| String::from("my_database"));
println!("[Layout] Backup Directory: {}", backup_dir);
println!("[Layout] Database Name: {}", db_name);
// 3. Constructing Backup File Names
let archive_name = format!("{}/backup_{}.tar.gz", backup_dir, now);
// 4. Execute harmless external commands (Simulated Backup)
let output = Command::new("echo")
.arg(format!("Simulating backup of {} to {}", db_name, archive_name))
.output()
.expect("Command execution failed");
println!("[Execute] Command Output: {}", String::from_utf8_lossy(&output.stdout));
// 5. Computation time
let elapsed = start.elapsed();
println!("[Time taken] Operation time: {:?}", elapsed);
println!("=== Backup Complete ===");
}
Este script, com menos de 30 linhas, demonstra os principais recursos da biblioteca padrão do Rust:
Instantmedir o tempo decorrido,SystemTimeobter a hora do sistema,env::varler variáveis de ambiente eCommandexecutar comandos externos. Cada um desses recursos funciona como uma “janela” para obter informações do sistema operacional ou controlá-lo.
3. Conceitos fundamentais
(1) Sistemas de tipos de chave na biblioteca padrão
graph TB
A[Rust Key Types in the Standard Library] --> B[Time-related]
A --> C[Environment-Related]
A --> D[Process-Related]
A --> E[Path-related]
B --> B1["Duration: Time Period"]
B --> B2["Instant: Instant Timing"]
B --> B3["SystemTime: System Clock"]
C --> C1["env::args(): Command-Line Arguments"]
C --> C2["env::var(): Environment Variables"]
C --> C3["env::set_var(): Set a variable"]
D --> D1["Command::new"]
D --> D2["status() / output()"]
D --> D3["stdin / stdout / stderr"]
E --> E1["Path: Immutable Path Slices"]
E --> E2["PathBuf: Paths to Growth"]
E --> E3["join / parent / exists"]
(2) Comparação dos principais tipos
| Tipo/Função | Módulo | Finalidade | Principais métodos |
|---|---|---|---|
Duration |
std::time |
Intervalo de tempo (por exemplo, 5 segundos, 100 milissegundos) | from_secs, from_millis, as_secs |
Instant |
std::time |
Temporizador monotônico desde a inicialização do programa | now, elapsed, duration_since |
SystemTime |
std::time |
Hora do relógio do sistema (pode ser ajustada por NTP) | now, duration_since, UNIX_EPOCH |
env::args |
std::env |
Ler argumentos da linha de comando | Retornar o iterador Args |
env::var |
std::env |
Ler variáveis de ambiente | Voltar para Result<String, VarError> |
Command std::process Executar comandos externos new, arg, output, status |
|||
PathBuf |
std::path |
Caminho do arquivo personalizável | push, pop, set_extension |
| Referência de caminho imutável |
(3) A relação entre Path e PathBuf
Path |
PathBuf |
|
|---|---|---|
| Tipos semelhantes a strings | &str (referência imutável) |
String (propriedade) |
| Mutabilidade | Imutável (operações somente de leitura) | Mutável (push, pop, etc.) |
| Local na memória | Referência na pilha ou no heap | Buffer no heap |
| Operações comuns | exists, is_dir, parent, join |
push, pop, set_extension |
| Conversão | path.to_path_buf() → PathBuf |
path_buf.as_path() → &Path |
(4) Referência rápida para comparar tipos de tempo
| Tipo | Finalidade | Aumento monotônico | Precisão | Pode ser ajustado pelo sistema | Usos típicos |
|---|---|---|---|---|---|
Instant |
Cronometragem dentro do programa | Sim | Nanossegundos | Não | Medir o tempo de execução do código |
SystemTime |
Hora do relógio do sistema | Não | Nanossegundos | Sim (NTP, etc.) | Obter data e hora atuais |
Duration |
Período/Intervalo de tempo | N/A | Nanossegundos | N/A | Tempo limite, suspensão, operações aritméticas |
A relação entre
PathePathBufé exatamente análoga àquela entre&streString:PathBufé um caminho mutável com propriedade, ePathé uma fatia de caminho imutável e emprestada. Todas as operações de caminho (join,parent, etc.) são definidas emPath.
4. Exemplos de tipos de chave na biblioteca padrão
▶ Exemplo 1: Medição do tempo — duração, instante e SystemTime (Dificuldade ⭐)
// ============================================
// Demo: The Three Time Types in the std::time Module
// Simulation: Program Timer and System Clock
// ============================================
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
fn main() {
println!("=== Time Type Demonstration ===\n");
// --- 1. Duration: Time Period ---
let five_secs = Duration::from_secs(5);
let hundred_ms = Duration::from_millis(100);
let two_mins = Duration::from_secs(2 * 60);
println!("[Duration] 5 seconds = {:?}", five_secs);
println!("[Duration] 100ms = {:?}", hundred_ms);
println!("[Duration] 2 minutes = {:?}", two_mins);
// Duration Operations: Addition, Subtraction, and Comparison
let total = five_secs + hundred_ms;
println!("[Duration] 5 seconds+100ms = {:?}", total);
println!("[Duration] 5 seconds > 100ms = {}", five_secs > hundred_ms);
// --- 2. Instant: Program Timer ---
let start = Instant::now();
// Simulate some time-consuming operations
let mut sum: u64 = 0;
for i in 0..1_000_000 {
sum = sum.wrapping_add(i);
}
let elapsed = start.elapsed();
println!("\n[Instant] Calculation sum={} Time taken: {:?}", sum, elapsed);
println!("[Instant] Takes milliseconds: {}ms", elapsed.as_millis());
println!("[Instant] Takes microseconds: {}µs", elapsed.as_micros());
// --- 3. SystemTime: System Time ---
let now = SystemTime::now();
let since_epoch = now.duration_since(UNIX_EPOCH).unwrap();
println!("\n[SystemTime] Current timestamp: {} seconds", since_epoch.as_secs());
println!("[SystemTime] Current timestamp: {} milliseconds", since_epoch.as_millis());
// Calculate the time one day ago
let one_day_ago = now - Duration::from_secs(24 * 60 * 60);
let since_epoch_ago = one_day_ago.duration_since(UNIX_EPOCH).unwrap();
println!("[SystemTime] Timestamp from one day ago: {} seconds", since_epoch_ago.as_secs());
println!("\n=== The time demonstration has ended ===");
}
Resultado:
=== Time Type Demonstration ===
[Duration] 5 seconds = 5s
[Duration] 100ms = 100ms
[Duration] 2 minutes = 120s
[Duration] 5 seconds+100ms = 5.1s
[Duration] 5 seconds > 100ms = true
[Instant] Calculation sum=499999500000 Time taken: 2.345ms
[Instant] Takes milliseconds: 2ms
[Instant] Takes microseconds: 2345µs
[SystemTime] Current timestamp: 1783012250 seconds
[SystemTime] Current timestamp: 1783012250123 milliseconds
[SystemTime] Timestamp from one day ago: 1782925850 seconds
=== The time demonstration has ended ===
Durationrepresenta um intervalo de tempo (por exemplo, “5 segundos”) e suporta operações de adição, subtração e comparação.Instanté um “temporizador monotônico desde o início do programa” — adequado para medir o tempo de execução do código, não sendo afetado por ajustes na hora do sistema.SystemTimelê o relógio do sistema (que pode ser ajustado por NTP) e é adequado para obter a data e a hora atuais.duration_since(UNIX_EPOCH)recupera o timestamp do Unix.
▶ Exemplo 2: Ambiente e argumentos da linha de comando — env::args e env::var (Dificuldade ⭐⭐)
// ============================================
// Demo: std::env Module for reading command-line arguments and environment variables
// Simulation: A configurable backup tool
// ============================================
use std::env;
fn main() {
println!("=== Environment and Parameter Explorer ===\n");
// --- 1. Reading Command-Line Arguments ---
let args: Vec<String> = env::args().collect();
println!("[args] Number of command-line arguments: {}", args.len());
if args.len() > 1 {
println!("[args] Program Name: {}", args[0]);
println!("[args] Input Parameters:");
for (i, arg) in args.iter().enumerate().skip(1) {
println!(" args[{}] = {}", i, arg);
}
} else {
println!("[args] No additional parameters were passed");
println!("[args] Presentation: The operating procedure is as follows");
println!(" cargo run -- --mode=backup --target=./data");
}
// --- 2. Read Environment Variables ---
println!("\n--- Environment Variable Detection ---");
// Try reading a few common environment variables
check_env_var("PATH");
check_env_var("HOME");
check_env_var("USER");
check_env_var("BACKUP_DIR"); // It may not exist.
check_env_var("DB_CONNECTION"); // It may not exist.
// --- 3. Read and Parse Custom Configuration ---
println!("\n--- Layout Analysis ---");
// Set an environment variable for demonstration purposes (Valid only within the current process)
// Note: Use set_var with caution in actual projects, it will affect the current process
env::set_var("MY_APP_MODE", "backup");
env::set_var("MY_APP_VERBOSE", "true");
let mode = env::var("MY_APP_MODE").unwrap_or_else(|_| "default".to_string());
let verbose = env::var("MY_APP_VERBOSE")
.map(|v| v == "true" || v == "1")
.unwrap_or(false);
println!("[Layout] Operating Mode: {}", mode);
println!("[Layout] Detailed Output: {}", verbose);
// --- 4. Iterate through all environment variables (Show only the first few) ---
println!("\n--- List of Environment Variables(first 5)---");
for (i, (key, value)) in env::vars().enumerate().take(5) {
println!(" {} = {}", key, value);
}
println!("\n=== Survey Complete ===");
}
/// Try reading the environment variables and printing them
fn check_env_var(name: &str) {
match env::var(name) {
Ok(val) => println!("[env] {} = {}", name, val),
Err(env::VarError::NotPresent) => println!("[env] {} = (Not set)", name),
Err(env::VarError::NotUnicode(_)) => println!("[env] {} = (non-UTF-8 value)", name),
}
}
Resultado:
=== Environment and Parameter Explorer ===
[args] Number of command-line arguments: 1
[args] No additional parameters were passed
[args] Presentation: The operating procedure is as follows
cargo run -- --mode=backup --target=./data
--- Environment Variable Detection ---
[env] PATH = C:\Windows\system32;C:\Windows;...
[env] HOME = (Not set)
[env] USER = (Not set)
[env] BACKUP_DIR = (Not set)
[env] DB_CONNECTION = (Not set)
--- Layout Analysis ---
[Layout] Operating Mode: backup
[Layout] Detailed Output: true
--- List of Environment Variables(first 5)---
ALLUSERSPROFILE = C:\ProgramData
APPDATA = C:\Users\Administrator\AppData\Roaming
...
=== Survey Complete ===
env::args()Retorna um iterador sobre os argumentos da linha de comando; o primeiro elemento é o caminho do programa.env::var(name)Lê uma variável de ambiente e retornaResult<String, VarError>— isso pode falhar se a variável não existir (NotPresent) ou se o valor não for válido em Unicode (NotUnicode).env::set_varDefine uma variável de ambiente (válida apenas para o processo atual).env::vars()Itera por todas as variáveis de ambiente.
▶ Exemplo 3: Comando e caminho — Execução de comandos externos e operações com caminhos (Dificuldade ⭐⭐)
// ============================================
// Demo: std::process::Command and std::path::Path/PathBuf
// Simulation:Backup Script——Build Path、Execute the compression command
// ============================================
use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
println!("=== Demonstration of Path Operations and External Commands ===\n");
// --- 1. Path and PathBuf Basic Operations ---
println!("--- Path Operations ---");
// Create PathBuf (Variable Paths with Ownership)
let mut backup_dir = PathBuf::new();
backup_dir.push("data");
backup_dir.push("backups");
println!("[PathBuf] Initial Path: {}", backup_dir.display());
// Set File Extensions
let mut archive = backup_dir.clone();
archive.push("database");
archive.set_extension("tar.gz");
println!("[PathBuf] Archived Files: {}", archive.display());
// Path Read-only operations
let path = Path::new("C:/Users/Alice/Documents/report.pdf");
println!("\n[Path] File Path: {}", path.display());
println!("[Path] File Name: {:?}", path.file_name());
println!("[Path] File extension: {:?}", path.extension());
println!("[Path] Parent directory: {:?}", path.parent());
println!("[Path] Does it exist?: {}", path.exists());
// Path Concatenation
let docs = Path::new("./docs");
let full_path = docs.join("rust").join("guide.md");
println!("[Path] Path Concatenation: {}", full_path.display());
// --- 2. Usage Command Execute an external command ---
println!("\n--- Executing External Commands ---");
// Example A: Execute "echo" Command (Harmless Command)
let echo_result = Command::new("echo")
.arg("Hello from Rust! Backup process started.")
.output()
.expect("echo Command execution failed");
println!("[Command] echo Output: {}",
String::from_utf8_lossy(&echo_result.stdout));
// Example B: Execute "whoami" Command (Show Current User)
let whoami_output = Command::new("whoami")
.output()
.expect("whoami Command execution failed");
if whoami_output.status.success() {
let username = String::from_utf8_lossy(&whoami_output.stdout);
println!("[Command] Current User: {}", username.trim());
} else {
let err = String::from_utf8_lossy(&whoami_output.stderr);
println!("[Command] whoami Failure: {}", err);
}
// Example C: Check whether the command was successful (status Pattern)
let status = Command::new("cmd")
.args(["/C", "dir", "./"])
.status()
.expect("dir Command execution failed");
if status.success() {
println!("[Command] dir The command was executed successfully (exit code: {})", status.code().unwrap_or(-1));
} else {
println!("[Command] dir Command execution failed (exit code: {:?})", status.code());
}
// --- 3. Combined Use: Build Command Based on Path ---
println!("\n--- Simulate the Backup Process ---");
let source = Path::new("./data/documents");
let dest = Path::new("./backup/documents_backup.tar.gz");
println!("Backup Source: {}", source.display());
println!("Backup Destination: {}", dest.display());
// Simulation tar Command (This will not actually be executed, just demonstrating command construction)
let _mock_cmd = Command::new("tar")
.arg("-czf")
.arg(dest)
.arg(source)
.status();
// Actually executing a harmless display command
let show_cmd = Command::new("echo")
.arg(format!(
"Would execute: tar -czf {} {}",
dest.display(),
source.display()
))
.output()
.unwrap();
println!("Simulation Commands: {}",
String::from_utf8_lossy(&show_cmd.stdout).trim());
println!("\n=== End of Presentation ===");
}
Resultado:
=== Demonstration of Path Operations and External Commands ===
--- Path Operations ---
[PathBuf] Initial Path: data\backups
[PathBuf] Archived Files: data\backups\database.tar.gz
[Path] File Path: C:/Users/Alice/Documents/report.pdf
[Path] File Name: Some("report.pdf")
[Path] File extension: Some("pdf")
[Path] Parent directory: Some("C:/Users/Alice/Documents")
[Path] Does it exist?: false
[Path] Path Concatenation: docs\rust\guide.md
--- Executing External Commands ---
[Command] echo Output: Hello from Rust! Backup process started.
[Command] Current User: DESKTOP-ABC123\Administrator
[Command] dir The command was executed successfully (exit code: 0)
--- Simulate the Backup Process ---
Backup Source: ./data/documents
Backup Destination: ./backup/documents_backup.tar.gz
Simulation Commands: Would execute: tar -czf ./backup/documents_backup.tar.gz ./data/documents
=== End of Presentation ===
Command::new("program name")cria um novo comando; os parâmetros são adicionados usandoargeargs.output()captura a saída padrão (stdout) e a saída de erro (stderr) (adequado para cenários que exigem processamento da saída), enquantostatus()verifica apenas o código de saída (adequado para cenários em que a saída não é necessária).Path::display()exibe caminhos de maneira multiplataforma.PathBufé uma versão mutável dePathque suporta operações de modificação, comopush,popeset_extension.path.join(...)retorna um novoPathBuf.
▶ Exemplo 4: Exercício abrangente — Ferramenta CLI: Visualizador de informações de arquivos (Dificuldade ⭐⭐⭐)
// ============================================
// Comprehensive Example: std::fs + std::path + std::time
// ============================================
use std::env;
use std::fs;
use std::path::Path;
use std::time::SystemTime;
fn format_size(size: u64) -> String {
const KB: u64 = 1024;
const MB: u64 = 1024 * KB;
const GB: u64 = 1024 * MB;
if size >= GB { format!("{:.2} GB", size as f64 / GB as f64) }
else if size >= MB { format!("{:.2} MB", size as f64 / MB as f64) }
else if size >= KB { format!("{:.2} KB", size as f64 / KB as f64) }
else { format!("{} B", size) }
}
fn format_time(systime: SystemTime) -> String {
let duration = systime.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_default();
let secs = duration.as_secs();
let days = secs / 86400;
let hours = (secs % 86400) / 3600;
let minutes = (secs % 3600) / 60;
format!("{} days {:02}:{:02} UTC", days, hours, minutes)
}
fn inspect_file(path_str: &str) -> Result<(), Box<dyn std::error::Error>> {
let path = Path::new(path_str);
if !path.exists() {
println!("The path does not exist: {}", path.display());
return Ok(());
}
println!("=== File Information ===");
println!("Path: {}", path.display());
println!("File Name: {:?}", path.file_name());
println!("File extension: {:?}", path.extension());
println!("Parent directory: {:?}", path.parent());
if path.is_file() {
let metadata = fs::metadata(path)?;
println!("Size: {}", format_size(metadata.len()));
println!("Read-only: {}", metadata.permissions().readonly());
println!("Last Modified: {}", format_time(metadata.modified()?));
} else if path.is_dir() {
println!("Type: Table of Contents");
let entries: Vec<_> = fs::read_dir(path)?
.filter_map(|e| e.ok())
.collect();
println!("Number of entries: {}", entries.len());
for entry in entries.iter().take(10) {
let name = entry.file_name().to_string_lossy().to_string();
let tag = if entry.path().is_dir() { "DIR" } else { "FILE" };
println!(" [{}] {}", tag, name);
}
if entries.len() > 10 {
println!(" ... And also {} entries", entries.len() - 10);
}
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
let target = if args.len() > 1 { &args[1] } else { "." };
inspect_file(target)
}
Saída (execução cargo run -- src/main.rs):
=== File Information ===
Path: src/main.rs
File Name: Some("main.rs")
File extension: Some("rs")
Parent directory: Some("src")
Size: 1.23 KB
Read-only: false
Last Modified: 20504 days 08:30 UTC
Este exemplo combina o uso de
std::fs(metadados do arquivo),std::path(manipulação de caminho),std::time(formatação de hora) estd::env(argumentos da linha de comando).format_sizeexibe o tamanho do arquivo em um formato fácil de entender, eformat_timeconverteSystemTimeem um formato de hora legível.
▶ Exemplo 5: Exercício abrangente — Temporizador simples e informações do sistema (Dificuldade ⭐⭐)
// ============================================
// Comprehensive Example: std::time + std::env + std::process
// ============================================
use std::env;
use std::process::Command;
use std::time::{Duration, Instant};
struct Timer {
start: Instant,
label: String,
}
impl Timer {
fn new(label: &str) -> Self {
println!("[{}] The timer starts", label);
Timer { start: Instant::now(), label: label.to_string() }
}
fn elapsed(&self) -> Duration {
self.start.elapsed()
}
fn stop(self) -> Duration {
let elapsed = self.elapsed();
println!("[{}] Time's up: {:.3}s", self.label, elapsed.as_secs_f64());
elapsed
}
}
fn main() {
println!("=== System Information ===");
println!("Current Directory: {:?}", env::current_dir().unwrap_or_default());
println!("Operating System: {}", env::consts::OS);
println!("Architecture: {}", env::consts::ARCH);
println!("\n=== Environment Variables ===");
for key in &["HOME", "PATH", "USER", "LANG"] {
match env::var(key) {
Ok(val) => println!("{}: {} Character", key, val.len()),
Err(_) => println!("{}: (Not set)", key),
}
}
println!("\n=== Timed Demonstration ===");
let t1 = Timer::new("Calculating the Fibonacci Sequence");
let mut fib: Vec<u64> = vec![0, 1];
for _ in 0..45 {
let next = fib[fib.len()-1] + fib[fib.len()-2];
fib.push(next);
}
t1.stop();
println!("fib(45) = {}", fib[45]);
let t2 = Timer::new("String Operations");
let mut s = String::new();
for i in 0..10_000 {
s.push_str(&format!("item{} ", i));
}
let len = s.len();
t2.stop();
println!("String Length: {} Character", len);
println!("\n=== Process Exit Code ===");
let status = Command::new("cmd")
.args(&["/C", "echo", "hello"])
.status();
match status {
Ok(s) => println!("Exit Code: {}", s.code().unwrap_or(-1)),
Err(e) => println!("Execution Failed: {}", e),
}
}
Resultado:
=== System Information ===
Current Directory: "G:\\..."
Operating System: windows
Architecture: x86_64
=== Environment Variables ===
HOME: 20 Character
PATH: 500 Character
...
=== Timed Demonstration ===
[Calculating the Fibonacci Sequence] The timer starts
[Calculating the Fibonacci Sequence] Time's up: X.XXXs
fib(45) = 1134903170
[String Operations] The timer starts
[String Operations] Time's up: X.XXXs
String Length: 88889 Character
=== Process Exit Code ===
Exit Code: 0
Timercontrola automaticamente o tempo usando o padrão RAII doInstant;env::constsobtém informações sobre a plataforma;env::varlê variáveis de ambiente;Commandexecuta comandos externos e obtém o código de saída.
❓ Perguntas Frequentes
P: Qual é a diferença entre
InstanteSystemTime? Quando cada um deve ser usado? R:Instanté um temporizador que aumenta monotonamente, enquantoSystemTimelê o relógio do sistema. UseInstantpara medir o tempo de execução do código — ele não é afetado por ajustes na hora do sistema (nem a sincronização NTP nem alterações manuais na hora alterarão o ritmo deInstant). UseSystemTimepara recuperar a data e a hora atuais (por exemplo, para registrar carimbos de data e hora).Instantnão pode ser convertido diretamente para um formato de hora legível por humanos.
P: Qual é a codificação das cadeias de caracteres retornadas por
env::vareenv::args? R: Ambas são codificadas em UTF-8String. A biblioteca padrão do Rust pressupõe que todos os argumentos da linha de comando e variáveis de ambiente sejam válidos em UTF-8. Se as variáveis de ambiente do sistema contiverem dados que não estejam em UTF-8,env::varretornaráErr(NotUnicode). Isso ocorre ocasionalmente no Windows e muito raramente no Linux. Se for necessário lidar com valores que não estejam em UTF-8, você pode usarenv::var_ospara retornarOption<OsString>.
P: Qual é a diferença entre
Command::output()eCommand::status()? R:output()captura a saída padrão (stdout) e a saída de erro (stderr), enquantostatus()verifica apenas o código de saída. Se você precisar processar a saída do comando (como analisar os dados retornados pelo comando), useoutput(). Se você estiver interessado apenas em saber se o comando foi executado com sucesso (como no caso demkdir,rmetc.),status()é mais eficiente — ele não requer a alocação de um buffer para armazenar a saída.
P: O Path e o PathBuf se comportam da mesma maneira no Windows e no Linux? R:
PathePathBufsão multiplataforma e utilizam internamente separadores de caminho específicos de cada plataforma. No Windows, tantoPath::new("C:\\foo\\bar")quantoPath::new("C:/foo/bar")são analisados corretamente. O métododisplay()usa o separador nativo da plataforma (\no Windows e/no Linux). O métodojoininsere automaticamente o separador correto quando necessário.
P: Ao executar um comando usando
Command, a variável de ambiente PATH é pesquisada automaticamente? R: Sim,Command::new("program name")pesquisa a variável de ambiente PATH. Se você não especificar um caminho completo,Commandprocurará o arquivo executável na lista de diretóriosPATH, assim como um shell do sistema operacional. Se o programa não estiver no PATH (ou se você precisar de controle preciso), é possível passar o caminho completo, comoCommand::new("/usr/local/bin/myapp"). No Windows, o diretório de trabalho atual também é pesquisado automaticamente.
📖 Resumo
Durationrepresenta um intervalo de tempo (segundos, milissegundos, microssegundos) e suporta operações de adição, subtração e comparação;Instanté um temporizador monotônico, adequado para medir o tempo decorrido;SystemTimelê o relógio do sistema e é adequado para obter carimbos de data e horaenv::args()Retorna um iterador de argumentos da linha de comando; o primeiro elemento é o caminho do programa;env::var(name)Lê as variáveis de ambiente e retornaResult<String, VarError>env::set_varDefine uma variável de ambiente (válida apenas para o processo atual); use com cautela em ambiente de produção;env::vars()Percorre todas as variáveis de ambienteCommand::newExecutar um comando externo;arg/argsadicionar parâmetros;output()capturar a saída;status()verificar o código de saídaPathBufé um caminho variável com propriedade (semelhante aString) que permite modificações comopush,pop,set_extensione assim por diante.Pathé uma fatia de caminho imutável emprestada (semelhante a&str) que suporta operações somente de leitura, comoexists,parent,joinefile_name.
📝 Exercícios
- Dificuldade ⭐: Escreva um programa que utilize
Instantpara medir o tempo de execução de um loop (contando de 1 a 1.000.000) e exiba o tempo decorrido em milissegundos (ms) e microssegundos (µs), respectivamente. Além disso, useSystemTimepara recuperar o timestamp do Unix no momento em que o programa for iniciado e imprima-o. - Dificuldade ⭐⭐: Implemente um “visualizador de variáveis de ambiente”. O programa deve ler e exibir o valor de uma variável de ambiente especificada por meio de um argumento da linha de comando. Se a variável não existir, exiba uma mensagem amigável. Recurso adicional: se nenhum argumento for fornecido, liste todas as variáveis de ambiente que começam com
MY_ouRUST_, juntamente com seus valores. - Dificuldade ⭐⭐⭐: Implemente uma “ferramenta simples de backup”. Use
PathBufpara definir o diretório de origem e o caminho do arquivo de destino. Leia a configuração por meio das variáveis de ambienteBACKUP_SOURCEeBACKUP_DEST(se não estiverem definidas, use os valores padrão./datae./backup/archive.tar.gz). UseCommandpara executar o comandoechoe simular o processo de backup — exiba “Fazendo backup de [origem] para [destino]”. UseInstantpara registrar e exibir o tempo total decorrido no início e no final. Você deve usarPatheexists()para verificar se o diretório de origem existe.