GoCasts آموزش Go به زبان ساده

بیش از ۱۰۰۰ شرکت‌کننده یادگیری Go و Backend رو از امروز شروع کن
ثبت‌نام دوره + تیم‌سازی

گولنگ در مقابل Rust - مقایسه Go و Rust

Go (گولنگ) و Rust هر دو زبان‌های مدرن و سریع هستند که اغلب با هم مقایسه می‌شوند. اما فلسفه طراحی متفاوتی دارند. در این مقاله، گولنگ و Rust را از جنبه‌های مختلف مقایسه می‌کنیم.

نگاه کلی

ویژگی Go Rust
سال معرفی 2009 2010 (1.0 در 2015)
طراح Google Mozilla
مدیریت حافظه Garbage Collector Ownership System
کاربرد اصلی Backend، DevOps، Cloud Systems، Embedded، WebAssembly
شعار “سادگی” “امنیت بدون سازش”

فلسفه طراحی

گولنگ - سادگی و Productivity

“Less is more” - Rob Pike

گولنگ برای سرعت توسعه طراحی شده:

  • یادگیری آسان
  • کد خوانا و یکدست
  • کامپایل سریع
  • Garbage Collection خودکار

Rust - امنیت و Performance

“Fearless concurrency” - Rust motto

Rust برای کنترل کامل طراحی شده:

  • امنیت حافظه در زمان کامپایل
  • بدون Garbage Collector
  • Zero-cost abstractions
  • کنترل کامل روی حافظه

سینتکس و خوانایی

گولنگ - ساده و صریح

package main

import "fmt"

type User struct {
    Name string
    Age  int
}

func (u *User) Greet() string {
    return fmt.Sprintf("سلام، من %s هستم", u.Name)
}

func main() {
    users := []User{
        {Name: "علی", Age: 25},
        {Name: "سارا", Age: 30},
    }

    for _, user := range users {
        fmt.Println(user.Greet())
    }
}

Rust - قدرتمند و پیچیده‌تر

struct User {
    name: String,
    age: u32,
}

impl User {
    fn greet(&self) -> String {
        format!("سلام، من {} هستم", self.name)
    }
}

fn main() {
    let users = vec![
        User { name: String::from("علی"), age: 25 },
        User { name: String::from("سارا"), age: 30 },
    ];

    for user in &users {
        println!("{}", user.greet());
    }
}

مقایسه اولیه:

  • گولنگ: کد ساده‌تر، کمتر نیاز به فکر کردن درباره ownership
  • Rust: باید به &, String vs &str, ownership توجه کنید

مدیریت حافظه

گولنگ - Garbage Collector

func createUsers() []*User {
    users := make([]*User, 1000)
    for i := range users {
        users[i] = &User{Name: fmt.Sprintf("User%d", i)}
    }
    return users
    // GC خودکار حافظه را مدیریت می‌کند
}

func main() {
    users := createUsers()
    // استفاده از users
    // GC وقتی نیاز نباشد، حافظه را آزاد می‌کند
}

مزایای GC در گولنگ:

  • نیاز نیست به حافظه فکر کنید
  • بدون memory leak (معمولاً)
  • کد ساده‌تر

معایب GC:

  • GC Pause (معمولاً <1ms در Go)
  • مصرف حافظه بیشتر
  • غیرقابل پیش‌بینی بودن timing

Rust - Ownership System

fn create_users() -> Vec<User> {
    let mut users = Vec::with_capacity(1000);
    for i in 0..1000 {
        users.push(User { name: format!("User{}", i), age: 20 });
    }
    users
    // ownership به caller منتقل می‌شود
}

fn main() {
    let users = create_users();  // users صاحب داده است

    process_users(&users);       // borrow (قرض دادن)

    // users اینجا drop می‌شود و حافظه آزاد می‌شود
}

fn process_users(users: &[User]) {
    // فقط خواندن، ownership ندارد
    for user in users {
        println!("{}", user.name);
    }
}

مزایای Ownership:

  • بدون GC Pause
  • مصرف حافظه بهینه
  • Memory safety بدون runtime cost
  • Deterministic cleanup

معایب:

  • یادگیری سخت
  • Borrow checker گاهی سخت‌گیر است
  • کد verbose‌تر

مثال: Data Race Prevention

use std::thread;

fn main() {
    let mut data = vec![1, 2, 3];

    // این کامپایل نمی‌شود! Rust از data race جلوگیری می‌کند
    // thread::spawn(|| {
    //     data.push(4);  // Error: cannot borrow as mutable
    // });

    // راه درست با Arc و Mutex
    use std::sync::{Arc, Mutex};

    let data = Arc::new(Mutex::new(vec![1, 2, 3]));
    let data_clone = Arc::clone(&data);

    thread::spawn(move || {
        let mut d = data_clone.lock().unwrap();
        d.push(4);
    });
}

سرعت اجرا

بنچمارک مقایسه‌ای

تست Go Rust تفاوت
Binary Trees 5.2s 3.1s Rust 40% سریع‌تر
N-Body 7.5s 4.8s Rust 35% سریع‌تر
Regex Redux 2.8s 2.2s Rust 20% سریع‌تر
HTTP Server 150K RPS 170K RPS Rust 10% سریع‌تر

نتیجه: Rust به طور کلی ۱۰-۴۰٪ سریع‌تر از گولنگ است.

چرا Rust سریع‌تر است؟

  1. بدون GC - بدون pause، بدون overhead
  2. Zero-cost abstractions - abstraction بدون هزینه runtime
  3. LLVM optimization - بهینه‌سازی‌های پیشرفته
  4. کنترل دقیق حافظه - cache-friendly layouts

ولی گولنگ هم سریع است!

  • کافی برای ۹۹٪ کارها
  • سرعت توسعه مهم‌تر است در بیشتر پروژه‌ها
  • GC مدرن گولنگ بسیار بهینه شده (Pause <1ms)

برنده سرعت: Rust - ولی تفاوت در اکثر کاربردها محسوس نیست

همزمانی (Concurrency)

گولنگ - Goroutines و Channels

package main

import (
    "fmt"
    "sync"
)

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        results <- j * 2
    }
}

func main() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)

    // شروع 3 worker
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    // ارسال 9 job
    for j := 1; j <= 9; j++ {
        jobs <- j
    }
    close(jobs)

    // دریافت نتایج
    for a := 1; a <= 9; a++ {
        fmt.Println(<-results)
    }
}

مزایای گولنگ:

  • سینتکس ساده (go keyword)
  • Channels برای ارتباط امن
  • CSP model (Communicating Sequential Processes)

Rust - Fearless Concurrency

use std::sync::mpsc;
use std::thread;

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

    // شروع 3 thread
    for id in 0..3 {
        let tx = tx.clone();
        thread::spawn(move || {
            for j in 0..3 {
                tx.send((id, j * 2)).unwrap();
            }
        });
    }

    drop(tx);  // بستن sender اصلی

    // دریافت نتایج
    for received in rx {
        println!("{:?}", received);
    }
}

مزایای Rust:

  • کامپایلر Data Race را prevent می‌کند
  • امنیت در زمان کامپایل
  • انتخاب بین async و threads

مقایسه مدل‌ها

ویژگی گولنگ Rust
شروع کار بسیار آسان نیاز به یادگیری
Data Race Runtime panic Compile error
Async Goroutines (همیشه) async/await (انتخابی)
حافظه per thread از 2KB 2-8KB
کنترل کمتر بیشتر

برنده Concurrency: بستگی دارد

  • گولنگ برای سرعت توسعه و سادگی
  • Rust برای امنیت و کنترل

یادگیری

منحنی یادگیری

مرحله گولنگ Rust
Hello World 1 روز 1 روز
مفاهیم پایه 1 هفته 2-3 هفته
پروژه ساده 2-3 هفته 1-2 ماه
Production ready 1-2 ماه 3-6 ماه
تسلط کامل 6 ماه 1-2 سال

چالش‌های یادگیری Rust

  1. Ownership & Borrowing - مفهوم جدید برای اکثر برنامه‌نویسان
  2. Lifetimes - زمانی که borrow checker کافی نیست
  3. مفاهیم زیاد - Traits، Generics، Macros، async
  4. پیام‌های خطا - طولانی (ولی مفید)

چرا Go آسان‌تر است؟

  1. ۲۵ کلمه کلیدی - زبان کوچک
  2. بدون مفاهیم پیچیده - بدون ownership، lifetimes
  3. یک راه درست - نه ده راه مختلف
  4. مستندات عالی - Tour of Go

برنده یادگیری: گولنگ - به طرز چشمگیری آسان‌تر

اکوسیستم

Go

  • Web: Gin, Echo, Fiber
  • DevOps: Docker, Kubernetes, Terraform
  • Database: GORM, sqlx
  • CLI: Cobra

Rust

  • Web: Actix, Axum, Rocket
  • Systems: Tokio, async-std
  • WebAssembly: wasm-bindgen, Yew
  • CLI: clap

پروژه‌های معروف

گولنگ:

  • Docker
  • Kubernetes
  • Terraform
  • Hugo
  • Prometheus

Rust:

  • Firefox (components)
  • Dropbox (sync engine)
  • Discord (services)
  • Cloudflare (edge computing)
  • Linux kernel (drivers)

موارد استفاده

گولنگ بهترین انتخاب است برای:

میکروسرویس‌ها - سادگی و سرعت توسعه

ابزارهای DevOps - کامپایل آسان، باینری ساده

API‌های Web - Gin/Echo عالی هستند

CLI Tools - سرعت استارت، cross-compilation

Network Services - همزمانی قوی

Rust بهترین انتخاب است برای:

Systems Programming - جایگزین C/C++

Embedded Systems - بدون GC، کنترل کامل

WebAssembly - بهترین پشتیبانی

Game Engines - عملکرد بالا، بدون GC pause

Browsers/OS - امنیت حافظه حیاتی

Crypto/Blockchain - امنیت و سرعت

جدول تصمیم‌گیری

گولنگ را انتخاب کنید اگر:

شرط  
سرعت توسعه مهم‌تر است
تیم با تجربه کمتر دارید
Backend/API می‌سازید
پروژه Cloud-native دارید
GC قابل قبول است

Rust را انتخاب کنید اگر:

شرط  
عملکرد حداکثری نیاز است
Memory safety حیاتی است
GC قابل قبول نیست
WebAssembly می‌سازید
جایگزین C/C++ می‌خواهید
زمان یادگیری دارید

مقایسه کد: HTTP Server

Go

package main

import (
    "encoding/json"
    "net/http"
)

type Message struct {
    Text string `json:"text"`
}

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        msg := Message{Text: "سلام از Go!"}
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(msg)
    })

    http.ListenAndServe(":8080", nil)
}

Rust با Axum

use axum::{routing::get, Json, Router};
use serde::Serialize;

#[derive(Serialize)]
struct Message {
    text: String,
}

async fn handler() -> Json<Message> {
    Json(Message {
        text: String::from("سلام از Rust!"),
    })
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(handler));

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

کدام را انتخاب کنم؟

سوالاتی که باید بپرسید:

  1. آیا به عملکرد حداکثری نیاز دارید؟
    • بله → Rust
    • “کافی” کافی است → Go
  2. GC pause قابل قبول است؟
    • بله → Go
    • خیر (real-time، embedded) → Rust
  3. چقدر زمان برای یادگیری دارید؟
    • کم → Go
    • زیاد → هر دو!
  4. نوع پروژه؟
    • Web/API/DevOps → Go
    • Systems/Embedded/WASM → Rust

توصیه من:

اگر مطمئن نیستید، با Go شروع کنید:

  • سریع‌تر یاد می‌گیرید
  • سریع‌تر productive می‌شوید
  • بعداً می‌توانید Rust هم یاد بگیرید

اگر به Rust علاقه‌مند شدید:

  • یادگیری‌اش ارزشمند است
  • دید جدیدی به برنامه‌نویسی می‌دهد
  • برای کارهای خاص بی‌نظیر است

نتیجه‌گیری

جنبه برنده
سرعت یادگیری گولنگ
سرعت توسعه گولنگ
سرعت اجرا Rust
امنیت حافظه Rust
همزمانی ساده گولنگ
کنترل سطح پایین Rust
اکوسیستم Cloud گولنگ
WebAssembly Rust

خلاصه:

  • گولنگ: برای ۹۰٪ کارهای backend و DevOps بهترین انتخاب است
  • Rust: برای کارهایی که به عملکرد حداکثری یا کنترل دقیق نیاز دارند

هر دو زبان عالی هستند و یادگیری هر کدام ارزشمند است!


شروع یادگیری Go

مقایسه‌های مرتبط

منابع

بیش از ۱۰۰۰ شرکت‌کننده یادگیری Go و Backend رو از امروز شروع کن
ثبت‌نام دوره + تیم‌سازی