Home > Blog > tech

Rust คืออะไร? สอน Rust Programming ภาษาที่เร็วและปลอดภัยที่สุด สำหรับ Developer 2026

rust programming guide
Rust Programming Guide 2026
2026-04-08 | tech | 3500 words

ในยุคที่ซอฟต์แวร์ต้องรองรับความเร็วระดับ Millisecond และต้องปลอดภัยจากช่องโหว่ด้าน Memory อย่าง Buffer Overflow, Use-After-Free และ Data Race ภาษา Rust ได้กลายเป็นคำตอบที่โลกเทคโนโลยีรอคอย ด้วยระบบ Ownership ที่ไม่เหมือนใคร Rust ให้ทั้งความเร็วระดับ C/C++ และความปลอดภัยด้าน Memory โดยไม่ต้องพึ่ง Garbage Collector ทำให้เป็นภาษาที่ได้รับความนิยมสูงสุดติดต่อกันหลายปีซ้อนบน Stack Overflow Survey

บทความนี้จะสอน Rust ตั้งแต่พื้นฐานจนถึงระดับที่ใช้งานจริงได้ ครอบคลุมทุกแนวคิดหลักที่ทำให้ Rust แตกต่างจากภาษาอื่น ไม่ว่าจะเป็น Ownership, Borrowing, Lifetimes, Traits, Pattern Matching และ Concurrency รวมถึงการสร้าง Web Application ด้วย Rust Framework ยอดนิยม

Rust คืออะไร?

Rust คือภาษาโปรแกรมมิ่งระดับ System ที่พัฒนาโดย Mozilla Research เริ่มต้นในปี 2010 โดย Graydon Hoare และเปิดตัวเวอร์ชัน 1.0 ในปี 2015 ปัจจุบันดูแลโดย Rust Foundation ซึ่งมีบริษัทใหญ่อย่าง Google, Microsoft, Amazon, Meta และ Huawei เป็นสมาชิก

Rust ถูกออกแบบมาเพื่อแก้ปัญหาที่ C/C++ ทำไม่ได้ นั่นคือการให้ Memory Safety โดยไม่ต้องใช้ Garbage Collector ผ่านระบบ Ownership ที่ตรวจสอบ ณ เวลา Compile ทำให้โปรแกรมที่ผ่านการ Compile จะปราศจากปัญหา Memory ที่พบบ่อยในภาษา C/C++

ทำไมต้อง Rust?

ใครใช้ Rust?

ติดตั้ง Rust ด้วย Rustup

Rustup คือ Official Toolchain Manager ของ Rust ใช้จัดการเวอร์ชัน Rust Compiler (rustc), Package Manager (Cargo) และ Component ต่างๆ

# ติดตั้ง Rustup (Linux/Mac)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Windows — ดาวน์โหลด rustup-init.exe จาก rustup.rs

# ตรวจสอบการติดตั้ง
rustc --version        # Rust compiler
cargo --version        # Package manager
rustup --version       # Toolchain manager

# อัพเดท Rust
rustup update

# ติดตั้ง Component เพิ่มเติม
rustup component add clippy      # Linter
rustup component add rustfmt     # Formatter
rustup component add rust-src    # Source code (สำหรับ IDE)

Cargo — Package Manager ของ Rust

Cargo เป็นมากกว่าแค่ Package Manager มันคือ Build System, Test Runner, Documentation Generator และ Package Publisher รวมอยู่ในเครื่องมือเดียว

# สร้างโปรเจกต์ใหม่
cargo new my_project        # สร้าง Binary project
cargo new my_lib --lib      # สร้าง Library project

# โครงสร้างโปรเจกต์ที่ได้:
# my_project/
# ├── Cargo.toml             # ไฟล์ Config (คล้าย package.json)
# ├── src/
# │   └── main.rs            # Entry point
# └── .gitignore

# คำสั่ง Cargo ที่ใช้บ่อย
cargo build                  # Compile (Debug mode)
cargo build --release        # Compile (Release mode, optimized)
cargo run                    # Compile + Run
cargo test                   # Run tests
cargo check                  # ตรวจสอบ syntax โดยไม่ compile (เร็วมาก)
cargo clippy                 # Lint code
cargo fmt                    # Format code
cargo doc --open             # Generate + เปิด documentation

Cargo.toml — ไฟล์ Config ของโปรเจกต์

[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <you@example.com>"]
description = "My awesome Rust project"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
reqwest = "0.12"

[dev-dependencies]
criterion = "0.5"

[profile.release]
opt-level = 3
lto = true

Syntax พื้นฐานของ Rust

ตัวแปรและ Mutability

ใน Rust ตัวแปรเป็น Immutable (เปลี่ยนค่าไม่ได้) โดยค่าเริ่มต้น ต้องใช้ mut เพื่อทำให้เปลี่ยนค่าได้

fn main() {
    // Immutable — เปลี่ยนค่าไม่ได้
    let x = 5;
    // x = 6;  // Error! cannot assign twice to immutable variable

    // Mutable — เปลี่ยนค่าได้
    let mut y = 10;
    y = 20;    // OK

    // Shadowing — ประกาศใหม่ซ้ำชื่อได้
    let z = 5;
    let z = z + 1;      // z = 6
    let z = z * 2;      // z = 12

    // Constants — ค่าคงที่ (ต้องระบุ Type)
    const MAX_POINTS: u32 = 100_000;
}

Data Types

// Integer types
let a: i8 = -128;           // -128 ถึง 127
let b: u8 = 255;            // 0 ถึง 255
let c: i32 = 2_147_483_647; // Default integer type
let d: i64 = 9_223_372_036_854_775_807;
let e: usize = 100;         // Platform-dependent (32/64-bit)

// Float types
let f: f32 = 3.14;
let g: f64 = 2.718281828;   // Default float type

// Boolean
let is_active: bool = true;

// Character (4 bytes, Unicode)
let ch: char = 'ก';         // รองรับภาษาไทย!

// String types
let s1: &str = "Hello";           // String slice (borrowed)
let s2: String = String::from("Hello"); // Owned String
let s3 = "Hello".to_string();    // เหมือนกัน

// Tuple
let tup: (i32, f64, char) = (42, 6.28, 'A');
let (x, y, z) = tup;        // Destructuring
let first = tup.0;          // Access by index

// Array (Fixed size)
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 10];        // [0, 0, 0, ..., 0] (10 ตัว)

Functions

// Function พื้นฐาน
fn greet(name: &str) {
    println!("Hello, {}!", name);
}

// Function ที่ Return ค่า
fn add(a: i32, b: i32) -> i32 {
    a + b    // ไม่ต้องใส่ semicolon = return expression
}

// Function หลาย Parameters
fn calculate_bmi(weight: f64, height: f64) -> f64 {
    weight / (height * height)
}

// Generic Function
fn largest<T: PartialOrd>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

fn main() {
    greet("Rust");
    let sum = add(3, 5);
    println!("Sum: {}", sum);        // Sum: 8
    println!("Max: {}", largest(10, 20)); // Max: 20
}

Control Flow

// if-else (เป็น expression ได้)
let number = 7;
let result = if number > 5 { "big" } else { "small" };

// loop
let mut count = 0;
let value = loop {
    count += 1;
    if count == 10 {
        break count * 2;  // Return ค่าจาก loop ได้
    }
};

// while
let mut n = 3;
while n > 0 {
    println!("{}", n);
    n -= 1;
}

// for (ใช้บ่อยที่สุด)
for i in 0..5 {
    println!("{}", i);     // 0, 1, 2, 3, 4
}

for i in 0..=5 {
    println!("{}", i);     // 0, 1, 2, 3, 4, 5 (inclusive)
}

let names = vec!["Alice", "Bob", "Charlie"];
for name in &names {
    println!("{}", name);
}

Ownership System — หัวใจของ Rust

Ownership คือแนวคิดที่ทำให้ Rust แตกต่างจากภาษาอื่นทั้งหมด มันคือระบบที่ Compiler ใช้จัดการ Memory โดยไม่ต้องมี Garbage Collector ถ้าเข้าใจ Ownership ก็ถือว่าเข้าใจ Rust ไปครึ่งหนึ่งแล้ว

กฎ 3 ข้อของ Ownership

  1. ทุกค่า (value) มีเจ้าของ (owner) ได้แค่ หนึ่งเดียว ในเวลาเดียวกัน
  2. เมื่อ owner ออกจาก scope ค่านั้นจะถูก drop (ลบออกจาก memory) อัตโนมัติ
  3. เมื่อกำหนดค่าให้ตัวแปรใหม่ ownership จะ move ไปที่ตัวแปรใหม่ (ตัวเดิมใช้ไม่ได้อีก)
fn main() {
    // Move semantics
    let s1 = String::from("hello");
    let s2 = s1;              // s1 ถูก "move" ไปที่ s2
    // println!("{}", s1);  // Error! s1 ถูก move ไปแล้ว ใช้ไม่ได้
    println!("{}", s2);     // OK: "hello"

    // Clone — คัดลอกจริงๆ (Deep copy)
    let s3 = String::from("world");
    let s4 = s3.clone();     // คัดลอก Data ใหม่
    println!("{}, {}", s3, s4); // ทั้งคู่ใช้ได้

    // Copy types (ชนิดที่อยู่บน Stack: i32, f64, bool, char)
    let x = 42;
    let y = x;                // Copy (ไม่ใช่ Move)
    println!("{}, {}", x, y); // ทั้งคู่ใช้ได้

    // Ownership กับ Function
    let name = String::from("Rust");
    take_ownership(name);     // name ถูก move เข้า function
    // println!("{}", name); // Error! name ถูก move ไปแล้ว
}

fn take_ownership(s: String) {
    println!("Got: {}", s);
} // s ถูก drop ตรงนี้

Borrowing (References)

เนื่องจาก Move ทำให้ตัวแปรเดิมใช้ไม่ได้ Rust จึงมีระบบ Borrowing ให้ "ยืม" ค่าไปใช้โดยไม่ต้องโอน Ownership

fn main() {
    let s = String::from("hello");

    // Immutable Borrow (&) — ยืมแบบอ่านอย่างเดียว
    let len = calculate_length(&s);   // ยืม s ไป
    println!("'{}' has length {}", s, len); // s ยังใช้ได้!

    // Mutable Borrow (&mut) — ยืมแบบแก้ไขได้
    let mut text = String::from("hello");
    change(&mut text);
    println!("{}", text);   // "hello, world"
}

fn calculate_length(s: &String) -> usize {
    s.len()
} // s เป็นแค่ reference ไม่ถูก drop

fn change(s: &mut String) {
    s.push_str(", world");
}

// กฎของ Borrowing:
// 1. มี &mut ได้แค่ 1 ตัวในเวลาเดียวกัน (ป้องกัน Data Race)
// 2. มี & ได้หลายตัว (อ่านพร้อมกันได้)
// 3. ไม่มี & กับ &mut พร้อมกันได้ (อ่านกับเขียนพร้อมกันไม่ได้)

Lifetimes

Lifetime บอก Compiler ว่า Reference มีอายุนานเท่าไหร่ เพื่อป้องกัน Dangling Reference

// Lifetime annotation
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let string1 = String::from("long string");
    let result;
    {
        let string2 = String::from("xyz");
        result = longest(string1.as_str(), string2.as_str());
        println!("Longest: {}", result);
    }
    // result ใช้ไม่ได้ที่นี่ เพราะ string2 ถูก drop แล้ว
}

// Lifetime ใน Struct
struct Excerpt<'a> {
    part: &'a str,
}

impl<'a> Excerpt<'a> {
    fn level(&self) -> i32 {
        3
    }
}
Lifetime Elision: ในหลายกรณี Rust Compiler สามารถอนุมาน Lifetime ได้เอง ไม่ต้องเขียนทุกครั้ง เช่น fn first_word(s: &str) -> &str Compiler รู้ว่า Output lifetime = Input lifetime

Structs และ Enums

Structs

// กำหนด Struct
struct User {
    username: String,
    email: String,
    age: u32,
    active: bool,
}

impl User {
    // Associated function (constructor)
    fn new(username: String, email: String, age: u32) -> Self {
        Self {
            username,
            email,
            age,
            active: true,
        }
    }

    // Method (ใช้ &self)
    fn display(&self) {
        println!("{} ({}), age {}", self.username, self.email, self.age);
    }

    // Method ที่แก้ไขค่า (ใช้ &mut self)
    fn deactivate(&mut self) {
        self.active = false;
    }
}

fn main() {
    let mut user = User::new(
        "alice".to_string(),
        "alice@example.com".to_string(),
        30,
    );
    user.display();
    user.deactivate();
}

Enums และ Pattern Matching

// Enum พื้นฐาน
enum Direction {
    North,
    South,
    East,
    West,
}

// Enum กับ Data (ทรงพลังมาก!)
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    Color(u8, u8, u8),
}

// Pattern Matching ด้วย match
fn process_message(msg: Message) {
    match msg {
        Message::Quit => println!("Quit!"),
        Message::Move { x, y } => println!("Move to ({}, {})", x, y),
        Message::Write(text) => println!("Write: {}", text),
        Message::Color(r, g, b) => println!("Color: ({}, {}, {})", r, g, b),
    }
}

// match ต้อง Exhaustive (ครอบคลุมทุกกรณี)
fn describe_number(n: i32) -> &'static str {
    match n {
        1 => "one",
        2 => "two",
        3..=9 => "several",
        10..=99 => "many",
        _ => "a lot",    // _ = catch-all
    }
}

Error Handling — Result และ Option

Rust ไม่มี Exception! แต่ใช้ Type System (Result และ Option) ในการจัดการ Error ทำให้ Compiler บังคับให้คุณจัดการทุก Error Case

Option — ค่าที่อาจมีหรือไม่มี

// Option<T> = Some(T) | None
fn find_user(id: u32) -> Option<String> {
    if id == 1 {
        Some("Alice".to_string())
    } else {
        None
    }
}

fn main() {
    // Pattern matching
    match find_user(1) {
        Some(name) => println!("Found: {}", name),
        None => println!("Not found"),
    }

    // if let (สั้นกว่า)
    if let Some(name) = find_user(1) {
        println!("Found: {}", name);
    }

    // unwrap_or — ค่า Default
    let name = find_user(99).unwrap_or("Unknown".to_string());

    // map — แปลงค่าข้างใน
    let upper = find_user(1).map(|n| n.to_uppercase());
}

Result — สำเร็จหรือผิดพลาด

use std::fs;
use std::io;

// Result<T, E> = Ok(T) | Err(E)
fn read_file(path: &str) -> Result<String, io::Error> {
    fs::read_to_string(path)
}

fn main() {
    // Pattern matching
    match read_file("config.txt") {
        Ok(content) => println!("Content: {}", content),
        Err(e) => println!("Error: {}", e),
    }

    // ? Operator — ส่ง Error ต่อ (ใช้ใน function ที่ return Result)
    // ถ้า Ok → แกะค่า, ถ้า Err → return Err ทันที
}

fn process_config() -> Result<(), Box<dyn std::error::Error>> {
    let content = fs::read_to_string("config.txt")?;  // ? แทน match
    let value: i32 = content.trim().parse()?;
    println!("Value: {}", value);
    Ok(())
}

// Custom Error
#[derive(Debug)]
enum AppError {
    NotFound(String),
    ParseError(String),
    DatabaseError(String),
}

impl std::fmt::Display for AppError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
            AppError::ParseError(msg) => write!(f, "Parse error: {}", msg),
            AppError::DatabaseError(msg) => write!(f, "DB error: {}", msg),
        }
    }
}
กฎ Error Handling: อย่าใช้ .unwrap() ใน Production Code เพราะจะ Panic (Crash) ถ้าเป็น None/Err ให้ใช้ ? operator, unwrap_or, unwrap_or_else, หรือ match แทน

Traits และ Generics

Trait คือสิ่งที่คล้ายกับ Interface ในภาษาอื่น ใช้กำหนดพฤติกรรมร่วมกันระหว่าง Type ต่างๆ ส่วน Generics ช่วยให้เขียน Code ที่ทำงานกับหลาย Type ได้

// กำหนด Trait
trait Summary {
    fn summarize(&self) -> String;

    // Default implementation
    fn read_more(&self) -> String {
        format!("Read more about {}...", self.summarize())
    }
}

struct Article {
    title: String,
    author: String,
    content: String,
}

struct Tweet {
    username: String,
    content: String,
}

// Implement Trait
impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{} by {}", self.title, self.author)
    }
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("@{}: {}", self.username, self.content)
    }
}

// Trait bound ใน function
fn notify(item: &impl Summary) {
    println!("Breaking: {}", item.summarize());
}

// หรือเขียนแบบเต็ม
fn notify_full<T: Summary + std::fmt::Display>(item: &T) {
    println!("News: {}", item.summarize());
}

// where clause (อ่านง่ายกว่าเมื่อมีหลาย bounds)
fn process<T, U>(t: &T, u: &U) -> String
where
    T: Summary + Clone,
    U: Summary + std::fmt::Debug,
{
    format!("{} and {}", t.summarize(), u.summarize())
}

Derive Macros — Implement Trait อัตโนมัติ

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Point {
    x: i32,
    y: i32,
}

// สามารถ derive ได้:
// Debug     — println!("{:?}", point)
// Clone     — point.clone()
// Copy      — implicit copy (stack types)
// PartialEq — point1 == point2
// Eq        — full equality
// Hash      — ใช้เป็น key ใน HashMap
// Default   — Point::default()
// Serialize/Deserialize (จาก serde) — JSON/YAML etc.

Collections — Vec, HashMap, HashSet

use std::collections::HashMap;
use std::collections::HashSet;

fn main() {
    // Vec — Dynamic Array
    let mut numbers: Vec<i32> = Vec::new();
    numbers.push(1);
    numbers.push(2);
    numbers.push(3);

    // หรือใช้ macro
    let names = vec!["Alice", "Bob", "Charlie"];

    // Access
    let first = &numbers[0];        // อาจ panic ถ้า out of bounds
    let safe = numbers.get(10);      // Return Option<&i32>

    // Iterate
    for n in &numbers {
        println!("{}", n);
    }

    // Functional style
    let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
    let evens: Vec<&i32> = numbers.iter().filter(|x| *x % 2 == 0).collect();
    let sum: i32 = numbers.iter().sum();

    // HashMap — Key-Value
    let mut scores: HashMap<String, i32> = HashMap::new();
    scores.insert("Alice".to_string(), 95);
    scores.insert("Bob".to_string(), 87);

    // Access
    if let Some(score) = scores.get("Alice") {
        println!("Alice: {}", score);
    }

    // Entry API — Insert if not exists
    scores.entry("Charlie".to_string()).or_insert(70);

    // Word frequency count
    let text = "hello world hello rust hello";
    let mut freq: HashMap<&str, u32> = HashMap::new();
    for word in text.split_whitespace() {
        *freq.entry(word).or_insert(0) += 1;
    }

    // HashSet — Unique values
    let mut tags: HashSet<String> = HashSet::new();
    tags.insert("rust".to_string());
    tags.insert("programming".to_string());
    tags.insert("rust".to_string()); // ซ้ำ ไม่เพิ่ม
    println!("Tags count: {}", tags.len()); // 2
}

Modules และ Crates

Rust ใช้ระบบ Module เพื่อจัดระเบียบ Code และ Crate คือหน่วยของ Compilation (Library หรือ Binary)

// src/lib.rs หรือ src/main.rs

// กำหนด Module
mod database {
    pub struct Connection {
        pub host: String,
        port: u16,  // private
    }

    impl Connection {
        pub fn new(host: &str, port: u16) -> Self {
            Self {
                host: host.to_string(),
                port,
            }
        }

        pub fn connect(&self) {
            println!("Connecting to {}:{}", self.host, self.port);
        }
    }

    pub mod queries {
        pub fn find_all() {
            println!("Finding all records...");
        }
    }
}

// ใช้งาน
use database::Connection;
use database::queries;

fn main() {
    let conn = Connection::new("localhost", 5432);
    conn.connect();
    queries::find_all();
}

// แยกไฟล์:
// src/database.rs       → mod database
// src/database/mod.rs   → mod database (แบบ directory)
// src/database/queries.rs → mod queries (sub-module)

Concurrency ใน Rust

Rust ให้ Concurrency ที่ปลอดภัยผ่าน Type System โดย Compiler จะป้องกัน Data Race ตั้งแต่ Compile Time ผ่าน Trait Send และ Sync

Threads

use std::thread;
use std::sync::{Arc, Mutex};

fn main() {
    // สร้าง Thread
    let handle = thread::spawn(|| {
        for i in 1..=5 {
            println!("Thread: {}", i);
            thread::sleep(std::time::Duration::from_millis(100));
        }
    });

    // Main thread ทำงานต่อ
    for i in 1..=3 {
        println!("Main: {}", i);
        thread::sleep(std::time::Duration::from_millis(150));
    }

    handle.join().unwrap(); // รอ thread จบ

    // แชร์ Data ข้าม Thread ด้วย Arc + Mutex
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Counter: {}", *counter.lock().unwrap()); // 10
}

Channels — ส่งข้อมูลระหว่าง Thread

use std::sync::mpsc; // Multiple Producer, Single Consumer
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    // Producer thread
    let tx1 = tx.clone();
    thread::spawn(move || {
        let messages = vec!["hello", "from", "thread 1"];
        for msg in messages {
            tx1.send(msg.to_string()).unwrap();
            thread::sleep(std::time::Duration::from_millis(100));
        }
    });

    thread::spawn(move || {
        let messages = vec!["more", "from", "thread 2"];
        for msg in messages {
            tx.send(msg.to_string()).unwrap();
            thread::sleep(std::time::Duration::from_millis(100));
        }
    });

    // Consumer (main thread)
    for received in rx {
        println!("Got: {}", received);
    }
}

Async/Await ด้วย Tokio

// Cargo.toml: tokio = { version = "1", features = ["full"] }

use tokio;

#[tokio::main]
async fn main() {
    // Async function
    let result = fetch_data("https://api.example.com/data").await;
    println!("Result: {}", result);

    // Concurrent tasks
    let (r1, r2, r3) = tokio::join!(
        fetch_data("https://api.example.com/1"),
        fetch_data("https://api.example.com/2"),
        fetch_data("https://api.example.com/3"),
    );

    // Spawn task (คล้าย thread แต่ lightweight)
    let handle = tokio::spawn(async {
        heavy_computation().await
    });
    let result = handle.await.unwrap();
}

async fn fetch_data(url: &str) -> String {
    // จำลอง HTTP request
    tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    format!("Data from {}", url)
}

async fn heavy_computation() -> i32 {
    42
}

Rust สำหรับ Web Development

Rust มี Web Framework หลายตัวที่มีประสิทธิภาพสูงมาก ด้วยความเร็วที่เหนือกว่า Node.js, Python, Go หลายเท่า

Actix-web

// Cargo.toml: actix-web = "4"
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct User {
    id: u32,
    name: String,
    email: String,
}

#[actix_web::get("/")]
async fn index() -> impl Responder {
    HttpResponse::Ok().body("Hello from Actix-web!")
}

#[actix_web::get("/users/{id}")]
async fn get_user(path: web::Path<u32>) -> impl Responder {
    let user = User {
        id: path.into_inner(),
        name: "Alice".to_string(),
        email: "alice@example.com".to_string(),
    };
    HttpResponse::Ok().json(user)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(index)
            .service(get_user)
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}

Axum (โดย Tokio Team)

// Cargo.toml: axum = "0.7", tokio = { version = "1", features = ["full"] }
use axum::{
    routing::{get, post},
    Json, Router, extract::Path,
};
use serde::{Deserialize, Serialize};

#[derive(Serialize)]
struct User {
    id: u32,
    name: String,
}

async fn root() -> &'static str {
    "Hello from Axum!"
}

async fn get_user(Path(id): Path<u32>) -> Json<User> {
    Json(User {
        id,
        name: "Bob".to_string(),
    })
}

#[derive(Deserialize)]
struct CreateUser {
    name: String,
}

async fn create_user(Json(payload): Json<CreateUser>) -> Json<User> {
    Json(User {
        id: 1,
        name: payload.name,
    })
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(root))
        .route("/users/:id", get(get_user))
        .route("/users", post(create_user));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Rocket

// Cargo.toml: rocket = "0.5"
#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello from Rocket!"
}

#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
    format!("Hello, {}! You are {} years old.", name, age)
}

#[launch]
fn rocket() -> _ {
    rocket::build()
        .mount("/", routes![index, hello])
}

เปรียบเทียบ Rust vs C++ vs Go

FeatureRustC++Go
Memory SafetyCompile-time (Ownership)Manual (unsafe)GC (runtime)
Performanceสูงมาก (= C++)สูงมากสูง (แต่มี GC pause)
Learning Curveสูง (Ownership, Lifetimes)สูงมาก (undefined behavior)ต่ำ (เรียนง่าย)
ConcurrencyCompile-time safeManual (ง่ายผิด)Goroutines (ง่ายมาก)
Compile Speedช้าช้าเร็วมาก
Null Safetyไม่มี null (ใช้ Option)มี null pointerมี nil
Error HandlingResult/Option (type-safe)ExceptionsMultiple return values
Package ManagerCargo (ดีมาก)CMake, vcpkg (ซับซ้อน)Go Modules
Ecosystemเติบโตเร็ว (crates.io)ใหญ่มาก (เก่าแก่)ใหญ่ (cloud-native)
Use CasesSystem, WebAssembly, CLIGame, OS, EmbeddedCloud, Microservices

เมื่อไหร่ควรใช้ Rust?

เหมาะกับ Rust

อาจไม่เหมาะ

Iterators และ Closures

Rust มี Iterator Pattern ที่ทรงพลังมาก ใช้แทน Loop ได้ในหลายกรณี และ Compiler จะ Optimize ให้เร็วเท่า Loop ปกติ (Zero-Cost Abstraction)

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // Closure (anonymous function)
    let add = |a: i32, b: i32| a + b;
    println!("{}", add(3, 5)); // 8

    // Iterator chains
    let result: Vec<i32> = numbers.iter()
        .filter(|&&x| x % 2 == 0)       // เลือกเลขคู่
        .map(|&x| x * x)                // ยกกำลัง 2
        .collect();                      // รวบรวมเป็น Vec
    // result = [4, 16, 36, 64, 100]

    // fold (คล้าย reduce)
    let sum: i32 = numbers.iter().fold(0, |acc, &x| acc + x);

    // any / all
    let has_even = numbers.iter().any(|&x| x % 2 == 0);   // true
    let all_positive = numbers.iter().all(|&x| x > 0);   // true

    // enumerate
    for (i, val) in numbers.iter().enumerate() {
        println!("[{}] = {}", i, val);
    }

    // zip
    let names = vec!["Alice", "Bob", "Charlie"];
    let ages = vec![30, 25, 35];
    let people: Vec<_> = names.iter().zip(ages.iter()).collect();
    // [("Alice", 30), ("Bob", 25), ("Charlie", 35)]

    // chain
    let a = vec![1, 2, 3];
    let b = vec![4, 5, 6];
    let combined: Vec<&i32> = a.iter().chain(b.iter()).collect();
}

Testing ใน Rust

// Unit Tests (ใส่ในไฟล์เดียวกัน)
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

pub fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err("Division by zero".to_string())
    } else {
        Ok(a / b)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add() {
        assert_eq!(add(2, 3), 5);
        assert_eq!(add(-1, 1), 0);
    }

    #[test]
    fn test_divide_ok() {
        assert_eq!(divide(10.0, 2.0).unwrap(), 5.0);
    }

    #[test]
    fn test_divide_by_zero() {
        assert!(divide(10.0, 0.0).is_err());
    }

    #[test]
    #[should_panic(expected = "index out of bounds")]
    fn test_panic() {
        let v = vec![1, 2, 3];
        let _ = v[99]; // panic!
    }
}
# Run tests
cargo test                     # Run ทุก test
cargo test test_add            # Run เฉพาะ test นี้
cargo test -- --nocapture      # แสดง println! output
cargo test -- --test-threads=1 # Run ทีละ test

Useful Crates ยอดนิยม

Crateหน้าที่Downloads/เดือน
serdeSerialization/Deserialization (JSON, YAML, TOML)50M+
tokioAsync Runtime30M+
reqwestHTTP Client15M+
clapCLI Argument Parser15M+
sqlxAsync SQL (Postgres, MySQL, SQLite)5M+
axumWeb Framework5M+
tracingStructured Logging20M+
anyhowError Handling (Application)20M+
thiserrorError Handling (Library)20M+
rayonData Parallelism10M+

แหล่งเรียนรู้ Rust

สรุป

Rust เป็นภาษาที่ท้าทายในการเรียนรู้ แต่ให้ผลตอบแทนที่คุ้มค่าอย่างมาก ด้วย Memory Safety ที่รับประกันโดย Compiler, Performance ระดับ C/C++ และระบบ Type System ที่ป้องกัน Bug ได้ตั้งแต่ก่อน Run โปรแกรม Rust จึงเป็นภาษาที่เหมาะสำหรับการสร้างซอฟต์แวร์ที่ต้องการทั้งความเร็วและความน่าเชื่อถือ

เริ่มต้นเรียน Rust ด้วย The Rust Book ทำแบบฝึกหัดจาก Rustlings แล้วลองสร้างโปรเจกต์จริง เช่น CLI Tool หรือ Web API ด้วย Axum เมื่อผ่านช่วง Learning Curve ของ Ownership ไปได้แล้ว คุณจะพบว่า Rust ทำให้คุณเขียน Code ที่ดีขึ้นในทุกภาษา เพราะแนวคิดเรื่อง Memory Management, Concurrency Safety และ Explicit Error Handling จะติดตัวคุณไปตลอด

ในปี 2026 Rust ไม่ใช่แค่ภาษาของ System Programmer อีกต่อไป แต่กำลังขยายไปสู่ Web Development, Cloud Infrastructure, Blockchain และ WebAssembly การลงทุนเรียน Rust วันนี้จึงเป็นการลงทุนที่คุ้มค่าสำหรับอนาคตของ Developer ทุกคน


Back to Blog | iCafe Forex | SiamLanCard | Siam2R