diff --git a/astro.config.mjs b/astro.config.mjs
index 1af6e79..dd93fc0 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -28,7 +28,10 @@ export default defineConfig({
'./src/components/content/GitCommand.astro',
'./src/components/content/Image.astro',
'./src/components/content/InfoBox.astro',
+ './src/components/content/NarrativeSection.astro',
'./src/components/content/ProsCons.astro',
+ './src/components/content/PullQuote.astro',
+ './src/components/content/SideNote.astro',
'./src/components/content/Table.astro',
'./src/components/content/YouTube.astro',
diff --git a/src/components/content/NarrativeSection.astro b/src/components/content/NarrativeSection.astro
new file mode 100644
index 0000000..c39bc49
--- /dev/null
+++ b/src/components/content/NarrativeSection.astro
@@ -0,0 +1,90 @@
+---
+/**
+ * NarrativeSection - Wrapper for flowing prose content
+ * Enhanced typography for comfortable reading experience
+ */
+---
+
+
+
+
diff --git a/src/components/content/PullQuote.astro b/src/components/content/PullQuote.astro
new file mode 100644
index 0000000..43a9dc1
--- /dev/null
+++ b/src/components/content/PullQuote.astro
@@ -0,0 +1,96 @@
+---
+/**
+ * PullQuote - Highlights key statements or memorable quotes
+ * Centered, prominent typography for emphasis
+ */
+---
+
+
+
+
+
+
diff --git a/src/components/content/SideNote.astro b/src/components/content/SideNote.astro
new file mode 100644
index 0000000..8b2a141
--- /dev/null
+++ b/src/components/content/SideNote.astro
@@ -0,0 +1,117 @@
+---
+/**
+ * SideNote - Insight Block (Redesigned Iteration 2)
+ * Style: "Insight Block" - Minimalist, Inline, Premium
+ * No floats, no heavy boxes. Focus on typography and clean separation.
+ */
+import { Icon } from 'astro-icon/components';
+
+type Props = {
+ type?: 'note' | 'tip' | 'warning';
+};
+
+const { type = 'note' } = Astro.props;
+
+const icons = {
+ note: 'heroicons:information-circle',
+ tip: 'heroicons:light-bulb',
+ warning: 'heroicons:exclamation-triangle',
+};
+---
+
+
+
+
diff --git a/src/content/blog/rust-ownership-memory-management/index.mdx b/src/content/blog/rust-ownership-memory-management/index.mdx
index ba35051..206a111 100644
--- a/src/content/blog/rust-ownership-memory-management/index.mdx
+++ b/src/content/blog/rust-ownership-memory-management/index.mdx
@@ -8,40 +8,43 @@ tags: ['Rust', 'Memory Management', 'Ownership', 'Systems Programming', 'Backend
featured: true
---
-ในโลกของการจัดการหน่วยความจำ เรามักถูกบีบให้เลือกสองทางสายหลัก: ทางแรกคือความรวดเร็วแต่เสี่ยงภัยแบบ Manual Allocation ใน C/C++ และทางที่สองคือความปลอดภัยแต่แลกด้วย Runtime Overhead ของ Garbage Collector (GC) ทว่า Rust เลือกที่จะบุกเบิก **"ทางที่สาม"** นั่นคือ **Ownership System** ซึ่งเป็นชุดกฎที่คอมไพเลอร์ใช้ตรวจสอบความปลอดภัยของหน่วยความจำโดยไม่มีค่าใช้จ่ายในขณะโปรแกรมทำงาน (Zero-cost abstraction)
+
----
+ในโลกของการเขียนโปรแกรมระดับ Systems Programming เรามักจะถูกบีบให้เลือกเพียงหนึ่งในสองทางที่ดูเหมือนตรงข้ามกันโดยสิ้นเชิง ทางแรกคือโลกของ C และ C++ ที่มอบความเร็วและอำนาจควบคุมเบ็ดเสร็จ แต่แลกมาด้วยความเสี่ยงของ memory leaks, dangling pointers และ buffer overflows ที่อาจกลายเป็นฝันร้ายในวันที่โปรแกรมของคุณไป production ส่วนทางที่สองคือโลกของ Garbage Collector ใน Java หรือ Go ที่ช่วยจัดการหน่วยความจำให้โดยอัตโนมัติ แต่ต้องแลกกับ runtime overhead และ latency ที่คาดเดาไม่ได้
-## จุดเริ่มต้นของตรรกะ: เมื่อ Stack และ Heap กำหนดพฤติกรรมของภาษา
+
+Zero-cost abstraction หมายความว่าคุณไม่ต้องจ่ายค่าใช้จ่ายใดๆ ในขณะ runtime สำหรับ safety features ที่คอมไพเลอร์มอบให้
+
-ความเข้าใจใน Ownership ต้องเริ่มจากความต่างของ **Stack** และ **Heap** ในเชิงลึก
+Rust ปฏิเสธที่จะเลือก มันบุกเบิก **"ทางที่สาม"** ขึ้นมาเอง นั่นคือสิ่งที่เรียกว่า **Ownership System** ซึ่งเป็นชุดกฎที่คอมไพเลอร์ใช้ตรวจสอบความปลอดภัยของหน่วยความจำตั้งแต่ขั้นตอน compile time โดยไม่มีค่าใช้จ่ายใดๆ ในขณะที่โปรแกรมทำงาน
-
-
- ข้อมูลบน Stack มีข้อกำหนดตายตัวคือต้องทราบขนาดที่แน่นอน ณ Compile-time การทำงานแบบ LIFO (Last In, First Out) ทำให้การจองพื้นที่นั้นรวดเร็วและมีประสิทธิภาพสูงในระดับ Processor Cache
-
-
- ถูกออกแบบมาเพื่อความยืดหยุ่นสำหรับข้อมูลที่ขนาดเปลี่ยนแปลงได้ เช่น String แต่ความยืดหยุ่นนี้มาพร้อมกับ Cost ของการทำ Allocation และ Pointer Chasing ที่ส่งผลต่อ Latency ของระบบ
-
-
+## Stack และ Heap: รากฐานของทุกสิ่ง
-**Ownership จึงถูกสร้างมาเพื่อทำหน้าที่สำคัญที่สุด:** การจัดการข้อมูลบน Heap อย่างเป็นระบบโดยที่โปรแกรมเมอร์ไม่ต้องสั่ง `free` เองแม้แต่บรรทัดเดียว
+การจะเข้าใจ Ownership อย่างแท้จริง เราต้องย้อนกลับไปดูพื้นฐานที่สำคัญที่สุดเสียก่อน นั่นคือความแตกต่างระหว่าง **Stack** และ **Heap**
----
+ลองนึกภาพว่า Stack เป็นเหมือนกองจานในร้านอาหาร คุณวางจานใหม่ลงด้านบน และหยิบจานออกก็จากด้านบนเช่นกัน เป็นระบบ LIFO (Last In, First Out) ที่เรียบง่ายและรวดเร็ว ข้อมูลบน Stack ต้องมีขนาดที่แน่นอน ณ เวลาที่คอมไพล์ ไม่ว่าจะเป็น `i32`, `bool`, หรือ `char` ทุกอย่างรู้ขนาดล่วงหน้าทั้งหมด ความเรียบง่ายนี้ทำให้ Stack ทำงานได้เร็วมาก เพราะ CPU สามารถเข้าถึงได้โดยตรงผ่าน stack pointer
+
+
+Heap ต้องทำ allocation ซึ่งหมายถึงการขอพื้นที่จาก OS และการทำ pointer chasing ที่ส่งผลต่อ cache performance
+
+
+ในทางตรงกันข้าม Heap ถูกออกแบบมาเพื่อรองรับความยืดหยุ่น เมื่อคุณสร้าง `String` ที่ความยาวอาจเปลี่ยนแปลงได้ตลอดเวลา หรือ `Vec` ที่ไม่รู้ว่าจะมีกี่ element Heap คือคำตอบ แต่ความยืดหยุ่นนี้มาพร้อมกับราคา การจองพื้นที่บน Heap ช้ากว่า Stack และการเข้าถึงข้อมูลต้องผ่าน pointer ทุกครั้ง
+
+นี่คือเหตุผลว่าทำไม Ownership จึงถูกสร้างมา — เพื่อจัดการข้อมูลบน Heap อย่างเป็นระบบโดยที่คุณไม่ต้องเรียก `malloc` และ `free` เองแม้แต่บรรทัดเดียว
-## Move Semantics: ทางออกของ Double Free ในระดับโครงสร้างหน่วยความจำ
+## กฎเหล็กสามข้อ
-หัวใจสำคัญของ Ownership สรุปได้ด้วย **กฎเหล็ก** เพียงไม่กี่ข้อ:
+หัวใจของ Ownership สรุปได้ด้วยกฎเพียงสามข้อ ข้อแรก ทุก value ใน Rust ต้องมี **owner เพียงหนึ่งเดียวเท่านั้น** ไม่มีข้อยกเว้น ไม่มีการแชร์ ownership ข้อที่สอง เมื่อ owner หลุดออกจาก scope ข้อมูลนั้นจะ **ถูกทำลายทันที** โดยอัตโนมัติ ไม่ต้องรอ garbage collector มาเก็บ และข้อสุดท้าย ณ เวลาใดๆ จะมีได้เพียง **หนึ่ง mutable reference** หรือ **หลาย immutable references** เท่านั้น ไม่มีทางมีทั้งสองอย่างพร้อมกัน
-
- 1. ทุก Value ต้องมี **Owner เพียงหนึ่งเดียว**
- 2. เมื่อ Owner หลุดออกจาก Scope ข้อมูลนั้นจะ **ถูกทำลายทันที** (RAII - Resource Acquisition Is Initialization)
- 3. ณ เวลาใดๆ จะมีได้เพียง **หนึ่ง mutable reference** หรือ **หลาย immutable references** เท่านั้น
-
+
+ทุก value ต้องมี owner เพียงหนึ่งเดียว และเมื่อ owner หลุดจาก scope ข้อมูลจะถูกทำลายทันที
+
-### โครงสร้างของ `String` ใน Memory
+กฎเหล่านี้อาจฟังดูเข้มงวด แต่มันคือรากฐานที่ทำให้ Rust สามารถรับประกัน memory safety ได้โดยไม่ต้องพึ่ง garbage collector
-เพื่อให้เห็นภาพชัดเจน เราต้องพิจารณาโครงสร้างของ `String` ซึ่งประกอบด้วย **3 ส่วนบน Stack**:
+## โครงสร้างของ String และปัญหา Double Free
+
+เพื่อให้เห็นภาพชัดเจนยิ่งขึ้น มาดูกันว่า `String` ใน Rust มีโครงสร้างอย่างไร เมื่อคุณสร้าง `String::from("hello")` สิ่งที่เกิดขึ้นจริงๆ คือมีข้อมูลสามส่วนถูกเก็บบน Stack ได้แก่ **pointer** ที่ชี้ไปยังข้อมูลจริงบน Heap, **length** ที่บอกความยาวปัจจุบัน และ **capacity** ที่บอกพื้นที่ที่จองไว้
```
Stack Heap
@@ -54,29 +57,26 @@ Stack Heap
└─────────────────┘
```
-- **Pointer**: ชี้ไปยังข้อมูลจริงบน Heap
-- **Length**: ความยาวของข้อมูลปัจจุบัน
-- **Capacity**: พื้นที่ที่จองไว้บน Heap
-
-### ปัญหา Double Free และวิธีแก้ด้วย Move
+ทีนี้ลองนึกดูว่าถ้าเราทำแบบนี้ในภาษาที่ไม่มี Ownership:
-
```rust
-fn main() {
- let s1 = String::from("hello");
- let s2 = s1; // ในภาษาอื่นอาจเป็น Shallow Copy
-
- // ถ้า s1 และ s2 ชี้ไปที่ Heap เดียวกัน
- // เมื่อทั้งคู่หลุดจาก scope จะเกิด Double Free!
-}
+let s1 = String::from("hello");
+let s2 = s1; // ในภาษาอื่นอาจเป็น Shallow Copy
+
+// ถ้า s1 และ s2 ชี้ไปที่ Heap เดียวกัน
+// เมื่อทั้งคู่หลุดจาก scope จะเกิด Double Free!
```
-
-เมื่อเราทำ Assignment เช่น `let s2 = s1;` ในภาษาทั่วไปอาจเป็นการทำ **Shallow Copy** (คัดลอกเฉพาะ Pointer) ซึ่งจะนำไปสู่หายนะที่เรียกว่า **Double Free Error** เมื่อทั้ง `s1` และ `s2` พยายามคืนหน่วยความจำที่จุดเดียวกันเมื่อจบ Scope
+
+Double Free คือหายนะ เพราะการคืนหน่วยความจำที่ถูกคืนไปแล้ว อาจทำให้เกิด memory corruption หรือ security vulnerabilities
+
+
+ในภาษาทั่วไปที่ทำ shallow copy ทั้ง `s1` และ `s2` จะชี้ไปที่ข้อมูลเดียวกันบน Heap และเมื่อทั้งสองตัวหลุดจาก scope พร้อมกัน ทั้งคู่จะพยายามคืนหน่วยความจำที่จุดเดียวกัน นี่คือ **Double Free Error** ที่อาจนำไปสู่ crash หรือแย่กว่านั้นคือ security vulnerabilities
-แต่ Rust แก้ปัญหานี้ด้วยการ **"Move"**:
+## Move Semantics: วิธีแก้ปัญหาอย่างสง่างาม
+
+Rust แก้ปัญหานี้ด้วยวิธีที่เรียบง่ายแต่ทรงพลัง — มันใช้ **Move Semantics** แทนที่จะ copy pointer ทั้งสองตัว Rust จะ "ย้าย" ownership จาก `s1` ไป `s2` และทำให้ `s1` ใช้งานไม่ได้อีกต่อไป
-
```rust
fn main() {
let s1 = String::from("hello");
@@ -86,13 +86,13 @@ fn main() {
println!("{}", s2); // ✅ OK: s2 เป็น owner ตัวเดียวแล้ว
}
```
-
-การที่คอมไพเลอร์ **ปฏิเสธไม่ให้เราเข้าถึง `s1` ได้อีก** เป็นการการันตี Memory Safety ในระดับทฤษฎีโดยไม่ต้องเสีย Runtime ในการทำ Deep Copy
+การที่คอมไพเลอร์ **ปฏิเสธไม่ให้เราเข้าถึง `s1` ได้อีก** อาจรู้สึกเหมือนข้อจำกัด แต่มันคือการป้องกัน Double Free ในระดับทฤษฎี โดยไม่ต้องเสีย runtime ในการตรวจสอบหรือทำ deep copy
+
+## เมื่อคุณต้องการสำเนาจริงๆ
-### เลือก Clone เมื่อต้องการสำเนาจริงๆ
+แน่นอนว่ามีบางครั้งที่คุณต้องการสำเนาข้อมูลจริงๆ ไม่ใช่แค่ย้าย ownership ในกรณีนี้ Rust มี method `.clone()` ให้ใช้
-
```rust
fn main() {
let s1 = String::from("hello");
@@ -102,32 +102,26 @@ fn main() {
println!("s2 = {}", s2); // ✅ OK: s2 เป็น owner ของ copy ใหม่
}
```
-
-
- การเรียก .clone() หมายความว่าเรายอมแลก Performance เพื่อแลกกับข้อมูลชุดใหม่บน Heap ใช้เมื่อจำเป็นจริงๆ เท่านั้น
-
+
+การเรียก `.clone()` หมายความว่าคุณยอมแลก performance เพื่อข้อมูลชุดใหม่บน Heap ใช้เมื่อจำเป็นจริงๆ เท่านั้น
+
----
+สิ่งสำคัญคือ `.clone()` เป็น **explicit** คุณต้องเขียนมันออกมาอย่างชัดเจน ทำให้โค้ดบอกได้ทันทีว่า "ตรงนี้มี performance cost" ไม่ใช่ซ่อนไว้เหมือนภาษาอื่นที่ทำ deep copy โดยอัตโนมัติ
-## Deep Dive: Drop และ Copy Trait
+## Drop และ Copy: สองด้านของเหรียญเดียวกัน
-Rust ใช้รูปแบบที่คล้ายกับ **RAII** ใน C++ ผ่านฟังก์ชันพิเศษที่ชื่อว่า `drop` ซึ่งจะถูกเรียกโดยอัตโนมัติที่ closing curly bracket (`}`) ของ Scope นั้นๆ
+Rust ใช้รูปแบบที่คล้ายกับ RAII ใน C++ ผ่านฟังก์ชันพิเศษที่ชื่อว่า `drop` ซึ่งจะถูกเรียกโดยอัตโนมัติที่ closing curly bracket ของ scope นั้นๆ นี่คือวิธีที่ Rust ทำให้การจัดการหน่วยความจำเป็นเรื่องที่คาดเดาได้ (deterministic)
-
```rust
fn main() {
let s = String::from("hello");
// ใช้งาน s ที่นี่...
} // <- ณ จุดนี้ drop() ถูกเรียกโดยอัตโนมัติ หน่วยความจำถูกคืน
```
-
-
-### Copy Trait: ข้อยกเว้นสำหรับ Stack-only Data
-ไม่ใช่ทุก Type ที่จะใช้พฤติกรรม Move เสมอไป ข้อมูลที่เป็น **Scalar Values** ที่ทราบขนาดแน่นอนบน Stack จะถูกจัดการผ่าน **Copy Trait**:
+แต่ไม่ใช่ทุก type ที่จะใช้พฤติกรรม Move เหมือน String สำหรับข้อมูลที่เป็น scalar values ที่อยู่บน Stack อย่าง integers, floats, booleans และ chars Rust ใช้ **Copy Trait** แทน
-
```rust
fn main() {
let x: i32 = 5;
@@ -137,43 +131,17 @@ fn main() {
println!("y = {}", y); // ✅ OK
}
```
-
-
-Types ที่ implement `Copy` Trait:
-
-
-
- i8, i16, i32, i64, i128, isize
- u8, u16, u32, u64, u128, usize
-
-
- f32, f64
-
-
- bool (true / false)
- char (Unicode scalar value)
-
-
- Tuples ที่ทุก element เป็น Copy
- เช่น (i32, bool) แต่ไม่ใช่ (i32, String)
-
-
-
-### กฎที่สำคัญ: Drop และ Copy ไม่สามารถอยู่ร่วมกันได้
-
-
- Rust จะไม่อนุญาตให้ Type ใดๆ ที่มีส่วนประกอบของ Drop (เช่น String) มา Implement Copy Trait ได้ เพราะนั่นจะทำให้เกิดความขัดแย้งในตรรกะการจัดการ Heap ทันที
-
-
-นี่คือการใช้ **Type System** เข้ามาบังคับใช้กฎของ Ownership ให้มีความเข้มงวดและคาดเดาผลลัพธ์ได้ (Deterministic)
----
+
+Stack-only types ใช้ Copy, Heap types ใช้ Move + Drop — ทั้งสองไม่มีทาง overlap กันได้
+
+
+ที่น่าสนใจคือ Rust **ไม่อนุญาตให้ type ใดๆ ที่มี Drop** มา implement Copy Trait ได้ เพราะนั่นจะสร้างความขัดแย้งในตรรกะการจัดการ Heap นี่คือการใช้ Type System เข้ามาบังคับใช้กฎของ Ownership อย่างเข้มงวด
-## Ownership ใน Function Boundaries
+## Ownership ข้าม Function Boundaries
-การส่งค่าผ่าน Function call ก็เปรียบเสมือนการทำ Assignment:
+การส่งค่าผ่าน function call ก็เปรียบเสมือนการทำ assignment เช่นกัน เมื่อคุณส่ง `String` เข้าไปใน function ownership จะถูก move เข้าไปด้วย
-
```rust
fn main() {
let s = String::from("hello");
@@ -194,37 +162,13 @@ fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
}
```
-
-### Pattern ที่ไม่สะดวก: Return Ownership กลับ
+ถ้า function ไม่ส่งคืน ownership กลับมา ข้อมูลนั้นจะถูก `drop` ทันทีที่ function ทำงานเสร็จ แม้ว่ากลไกนี้จะช่วยป้องกัน memory leak ได้อย่างเด็ดขาด แต่การต้องมานั่ง return ค่ากลับคืนในรูปแบบ tuple ตลอดเวลานั้นก็เทอะทะเกินไป
-หากฟังก์ชันนั้นไม่ส่งคืน Ownership กลับมา (Return) ข้อมูลนั้นจะถูก `drop` ทันทีที่ฟังก์ชันทำงานเสร็จ
+## References และ Borrowing: ทางออกที่สง่างาม
-
-```rust
-fn main() {
- let s1 = String::from("hello");
- let (s2, len) = calculate_length(s1);
-
- println!("'{}' มีความยาว {} ตัวอักษร", s2, len);
-}
+ความท้าทายข้างต้นนำไปสู่ feature ที่เรียกว่า **References & Borrowing** เพื่อให้เราสามารถเข้าถึงข้อมูลได้โดยไม่ต้องถือครอง ownership
-fn calculate_length(s: String) -> (String, usize) {
- let length = s.len();
- (s, length) // คืน ownership กลับพร้อม result
-}
-```
-
-
-แม้ว่ากลไกนี้จะช่วยป้องกัน Memory Leak ได้อย่างเด็ดขาด แต่ในเชิงปฏิบัติการต้องมานั่ง Return ค่ากลับคืนในรูปแบบ Tuple ตลอดเวลานั้นเป็นเรื่องที่ **เทอะทะและมีพิธีรีตองเกินไป**
-
----
-
-## จุดกำเนิดของ References & Borrowing
-
-ความท้าทายข้างต้นนำไปสู่ฟีเจอร์ที่เรียกว่า **References & Borrowing** เพื่อให้เราสามารถเข้าถึงข้อมูลได้โดยไม่ต้องถือครอง Ownership
-
-
```rust
fn main() {
let s1 = String::from("hello");
@@ -238,32 +182,9 @@ fn calculate_length(s: &String) -> usize { // รับ reference
s.len()
} // s หลุดจาก scope แต่เพราะไม่ได้เป็น owner จึงไม่มีอะไรถูก drop
```
-
-
-### กฎของ References
-
-
-
- | ชนิด |
- Syntax |
- สามารถแก้ไขได้? |
- จำนวนที่มีได้พร้อมกัน |
-
-
- | Immutable Reference |
- &T |
- ❌ ไม่ได้ |
- ไม่จำกัด |
-
-
- | Mutable Reference |
- &mut T |
- ✅ ได้ |
- 1 อันเท่านั้น |
-
-
-
-
+
+การ "ยืม" (borrowing) มาในสองรูปแบบ **Immutable reference** (`&T`) ยืมมาอ่านได้อย่างเดียว แต่ยืมได้หลายคนพร้อมกัน ส่วน **Mutable reference** (`&mut T`) ยืมมาแก้ไขได้ แต่ต้องยืมคนเดียวเท่านั้น
+
```rust
fn main() {
let mut s = String::from("hello");
@@ -275,35 +196,23 @@ fn change(some_string: &mut String) {
some_string.push_str(", world");
}
```
-
----
-
-## บทสรุปสำหรับ Senior Dev
+
+กฎของ References ถูกออกแบบมาเพื่อป้องกัน Data Race ตั้งแต่ compile time
+
-
- Ownership ไม่ใช่แค่เรื่องของการจัดการหน่วยความจำ แต่มันคือการสร้าง "สัญญา" ระหว่าง Code แต่ละส่วน ว่าใครมีสิทธิ์ทำลายหรือใครมีสิทธิ์ใช้ข้อมูล
-
+## บทสรุป
-### Key Takeaways
+Ownership ไม่ใช่แค่เรื่องของการจัดการหน่วยความจำ แต่มันคือการสร้าง **"สัญญา"** ระหว่าง code แต่ละส่วน ว่าใครมีสิทธิ์ทำลายหรือใครมีสิทธิ์ใช้ข้อมูล
-
-
- Memory safety ถูกตรวจสอบ ณ compile-time ไม่มี runtime overhead เหมือน GC
-
-
- การ assign หรือส่งค่าใน function = การโอนย้าย ownership ป้องกัน double free
-
-
- Stack-only types ใช้ Copy, Heap types ใช้ Move + Drop ไม่มีทาง overlap กัน
-
-
- References ช่วยให้เข้าถึงข้อมูลโดยไม่ต้องโอน ownership ลด overhead ของการ clone
-
-
+
+Ownership คือ contract ระหว่าง Code — ใครมีสิทธิ์ทำลาย ใครมีสิทธิ์ใช้ ทุกอย่างถูกกำหนดไว้ชัดเจน ณ compile time
+
-การทำความเข้าใจ **Move Semantics** และ **Scope** อย่างถ่องแท้ จะทำให้เราเขียนโปรแกรมที่ปราศจาก **Data Race** และ **Memory Corruption** ได้อย่างมั่นใจ ซึ่งเป็นสิ่งที่ภาษาอื่นทำได้ยากหากไม่มีระบบ Ownership เข้ามาควบคุมตั้งแต่ระดับรากฐาน
+สิ่งที่ควรจดจำคือ memory safety ถูกตรวจสอบ ณ compile-time ไม่มี runtime overhead เหมือน GC การ assign หรือส่งค่าใน function คือการโอนย้าย ownership ซึ่งป้องกัน double free ได้โดยธรรมชาติ Stack-only types ใช้ Copy ส่วน Heap types ใช้ Move + Drop โดยไม่มีทาง overlap กัน และ References ช่วยให้เข้าถึงข้อมูลโดยไม่ต้องโอน ownership ลด overhead ของการ clone
----
+การทำความเข้าใจ Move Semantics และ Scope อย่างถ่องแท้ จะทำให้เราเขียนโปรแกรมที่ปราศจาก Data Race และ Memory Corruption ได้อย่างมั่นใจ ซึ่งเป็นสิ่งที่ภาษาอื่นทำได้ยากหากไม่มีระบบ Ownership เข้ามาควบคุมตั้งแต่ระดับรากฐาน
ในบทความถัดไป เราจะเจาะลึกเรื่อง **Lifetimes** ซึ่งเป็นอีกหนึ่งกลไกสำคัญที่ทำให้ Rust สามารถรับประกันความปลอดภัยของ References ได้อย่างสมบูรณ์แบบ
+
+
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro
index 46a378a..035a079 100644
--- a/src/layouts/BaseLayout.astro
+++ b/src/layouts/BaseLayout.astro
@@ -2,14 +2,19 @@
import Navbar from '@/components/layout/Navbar.astro';
import ProgressBar from '@/components/ui/ProgressBar.astro';
import '@/styles/global.css';
+import '@/styles/terminal.css';
type Props = {
title: string;
description?: string;
};
-const { title, description = 'A developer\'s living knowledge base, curated by a pharmacist turned programmer.' } = Astro.props;
+const {
+ title,
+ description = 'A developer\'s living knowledge base, curated by a pharmacist turned programmer.',
+} = Astro.props;
const currentYear = new Date().getFullYear();
---
+
@@ -31,12 +36,21 @@ const currentYear = new Date().getFullYear();