📅 เขียนเมื่อ: สิงหาคม 2026 | Goish (goish.cogentica.ai)
⚠️ โปรเจกต์เพิ่งเปิดตัว — รายละเอียด/เวอร์ชันอาจเปลี่ยนแปลง ตรวจสอบจาก GitHub ก่อนใช้งาน
ถ้าคุณเขียน Go มาสักพัก คุณน่าจะเคยอยากได้สองอย่างพร้อมกัน — concurrency model ของ Go (goroutine, channel, select
) กับ ความปลอดภัยด้าน memory ของ Rust (ownership, ไม่มี GC) ปกติแล้วสองอย่างนี้อยู่คนละโลก: Go ให้ runtime มาให้แต่มี garbage collector, Rust ให้ ownership มาแต่ concurrency ต้องประกอบเองจาก async/futures
มีคนพยายามเชื่อมสองโลกนี้เข้าด้วยกันแล้ว — ชื่อโปรเจกต์ว่า Goish ผลงานของ Chanwit Kaewkasi (@chanwit) วิศวกรชาวไทยจากโคราช ภายใต้บริษัท Cogentica AI
นิยามสั้น ๆ ที่เจ้าตัวเขียนไว้ในหน้าแรก: "A Rust runtime for Go people" — รันไทม์ของ Go สำหรับคนที่เขียน Go
ถ้าขยายให้ละเอียด: Goish คือการพอร์ต standard library และ runtime ของ Go 1.25 ลงไปใน Rust แบบ no_std — ไม่พึ่ง glibc, ไม่พึ่ง std ของ Rust, ไม่พึ่ง Tokio, ไม่มี garbage collector มัน ship ทุกอย่างมาเองตั้งแต่
_start
, page allocator, size-class heap, M:N scheduler, channel, select!
, sync primitives, ไปจนถึง net/http
และ crypto/tls
ผลลัพธ์คือ binary ไฟล์เดียวแบบ static เหมือน Go — ldd
รันแล้วบอกว่า "not a dynamic executable"
แต่สิ่งที่ทำให้ Goish ต่างจากโปรเจกต์ "เขียน Go ให้เป็น Rust" ทั่วไป คือวิธีที่มันให้เครดิตกับต้นทาง — เรื่องนี้แหละคือหัวใจของที่มาที่ไป
แรงจูงใจหลักไม่ใช่ "อยากให้ Rust เขียนง่ายเหมือน Go" ธรรมดา ๆ แต่เป็นเรื่องของ compliance และ provenance
ลองนึกภาพ: ทีมคุณเขียน Go อยู่ แล้วต้องย้ายไป Rust (ด้วยเหตุผลเรื่อง memory safety หรือนโยบายบริษัท) ระหว่างทางคุณต้อง "พอร์ต" โค้ด — เอาโค้ดจาก Go มาเขียนใหม่เป็น Rust แล้วคำถามสำคัญก็ผุดขึ้น:
AES-GCM ใน binary ตัวนี้ เป็น implementation ที่ Go review แล้ว หรือเป็นของที่เราเขียนประมาณเอา?
เครื่องมือ supply-chain ยุคปัจจุบันอย่าง SLSA provenance หรือ SBOM ตอบคำถามนี้ไม่ได้ — มันอธิบายแค่ว่า binary ถูก build มาจากไหน (builder ไหน, commit อะไร, digest อะไร) แต่อธิบายไม่ได้ว่าโค้ดข้างในถูก port มาอย่างซื่อสัตย์แค่ไหน SBOM จะบันทึกว่า "goish 0.1.0" แล้วจบ — มันแยกไม่ออกว่า crypto ในนั้นคือของจริงหรือของก๊อป
Goish แก้ด้วยการบันทึกที่มาเป็นฟังก์ชันต่อฟังก์ชัน:
// go: sdk 1.25.5 crypto/internal/fips140/aes/gcm/gcm.go:31-46 newGCM
บรรทัดนี้เขียนไว้เหนือ port แต่ละตัว — บอกว่าโค้ดตรงนี้ port มาจากไฟล์ไหน บรรทัดไหน ใน Go 1.25.5 และมี CI ที่เปิด Go tree ขึ้นมาเช็คทุก commit ว่าตำแหน่งที่อ้างยังถูกต้องอยู่
ทำไมเรื่องนี้ถึงสำคัญตอนนี้? เพราะเส้นตายทางกฎหมายกำลังมา:
| วันที่ | เกิดอะไรขึ้น |
|---|---|
| 11 ก.ย. 2026 | |
| EU CRA (Cyber Resilience Act) บังคับใช้ภาระการรายงาน — แจ้งเตือน 24 ชม. / แจ้งเต็ม 72 ชม. เมื่อเจอช่องโหว่ที่ถูกโจมตีจริง | |
| 21 ก.ย. 2026 | |
| ใบรับรอง FIPS 140-2 ย้ายเข้า "Historical List" — ใช้ต่อได้แต่ justify การจัดซื้อภาครัฐใหม่ไม่ได้ | |
| 1 ม.ค. 2027 | |
| CNSA 2.0 กลายเป็นค่าเริ่มต้นสำหรับงาน NSS ของสหรัฐฯ | |
| 11 ธ.ค. 2027 | |
| ข้อกำหนดสำคัญของ CRA รวมถึง mandate เรื่อง machine-readable SBOM |
พูดง่าย ๆ: ถ้าสินค้าคุณต้องผ่าน compliance พวกนี้ คุณต้องพิสูจน์ได้ว่าโค้ดทุกบรรทัดมาจากไหน — และสำหรับโค้ดที่ "แปล" มาจากที่อื่น การพิสูจน์นั้นต้องลงถึงระดับฟังก์ชัน ไม่ใช่ระดับ build
นี่คือเหตุผลที่ Goish เกิด
ส่วนนี้คือความเจ๋งทางวิศวกรรม — ถ้าไม่อยากอ่านเชิงลึก ข้ามไปหัวข้อถัดไปได้เลย
runtime/proc.go
Goish ไม่ได้ "เขียน scheduler ใหม่ให้คล้าย Go" — มันแปล runtime/proc.go ของ Go 1.25 มาทีละบรรทัด:
runqgrab
/ runqsteal
/ stealOrder
)sysmon
ตัวจัดการ timer heap + force-preemptGoish เอาโครงสร้าง allocator ของ Go (mheap → mcentral → per-P mcache, 67 size classes) มาใช้ แต่ตัด garbage collector ออก — ให้ Rust ownership เป็นคน reclaim แทน
สำหรับ stack ของ goroutine มันใช้วิธีฉลาด: goroutine หนึ่งตัวได้ virtual reservation 1 MiB แบบ lazy-commit (kernel ค่อย commit หน้า 4 KiB เมื่อถูกแตะจริง) — แปลว่า goroutine ที่ทำงานตื้น ๆ เสีย memory จริงแค่ประมาณหนึ่ง page และถ้าอยากได้ความหนาแน่นสุดขีด ก็ใช้ go!(stack(2*KB), …)
เพื่อขอ stack ขนาด 2 KiB จาก stack pool
ผลลัพธ์ตาม demo:
ts vmsize_kb vmrss_kb vmpeak_kb vmhwm_kb threads
0s 1105148 44800 1108444 49024 13 ← baseline
2s 3069660 2406528 3069660 2406528 13 ← 1M parked
30s 3069660 2406528 3069660 2406528 13 ← steady-state
goroutine หนึ่งล้านตัว บน OS thread แค่ 13 เธรด — ~2.4 KiB RSS ต่อ goroutine
จุดเด่นที่สุดสำหรับคนเขียน Go — public API ใช้ type ตัวพิมพ์เล็กแบบ Go แทน type ของ Rust:
fn get(url: string) -> (int, string, string) {
let (mut resp, err) = http::Get(url.clone());
if err != nil {
return (-1, fmt::Sprintf!("get %s: %v", url, err), string(""));
}
let (body, _) = io::ReadAll(&mut resp.Body);
let _ = io::Closer::Close(&mut resp.Body);
return (resp.StatusCode, string(body), resp.Header.Get("Content-Type"));
}
string
, int
, multi-return, if err != nil
— ทั้งหมดคือ Rust จริง ๆ ที่ rustc
compile ได้ แต่อ่านแล้วแทบไม่ต่างจาก Go และ Vec<u8>
กับ &str
ไม่โผล่ใน signature สาธารณะเลย
นี่คือ philosophy หลัก: "Port first, get idiomatic later" — พอร์ตโค้ด Go มาแบบเกือบ line-by-line ก่อน แล้วค่อย ๆ ปรับเป็น Rust idiom ทีละ module เมื่อทีมพร้อม
ส่วนที่ภาคภูมิใจที่สุดคือ crypto/
— ครบ 1722/1722 declarations (100%) ทั้ง 66 packages รวมถึง crypto/internal/fips140*
ทั้ง 35 packages ที่เป็น code path ของ FIPS validation และ net/http
ครบ 639/639 functions (100%)
TLS 1.3 ที่รันจริงคือ crypto/tls
ที่ port มา verbatim — ไม่ใช่ implementation ใหม่ที่เขียนเลียนแบบ
scratch
/distroless container, confidential VM, appliance imageต้องการแค่ Rust 1.79+ และ Linux x86_64 (single-target ณ ตอนนี้)
git clone https://github.com/cogentica-ai/goish
cd goish
cargo build --target x86_64-unknown-linux-gnu --release
cargo build --target x86_64-unknown-linux-gnu --release --example spawn_million
./examples/spawn_million.sh
cargo build --target x86_64-unknown-linux-gnu --release --example goginx
โค้ด "Hello" แบบ Goish หน้าตาประมาณนี้:
use goish::{fmt, go};
#[goish::main]
fn main() {
go!(move || {
fmt::Println!("hello from a goroutine");
});
}
.go
crypto/
กับ net/http
เสร็จแล้ว แต่ net
, encoding
, os
ยังบางส่วนGoish ไม่ได้เป็นแค่ "Go runtime ใน Rust" — มันเป็นความพยายามตอบคำถามที่ใหญ่กว่านั้น: เมื่อเราต้องย้ายภาษาในโลกที่มีกฎหมายบังคับเรื่องที่มาของโค้ด เราจะพิสูจน์ได้ยังไงว่าโค้ดทุกบรรทัดไว้ใจได้
คำตอบของ Chanwit คือการพอร์ต Go แบบมี "ใบเสร็จ" ทุกบรรทัด แล้วเอา ownership ของ Rust มาแทน GC — ได้ทั้งความคุ้นเคยของ Go, ความปลอดภัยของ Rust, และหลักฐาน compliance ที่ตรวจซ้ำได้
โปรเจกต์นี้เพิ่งเปิด (สิงหาคม 2026) และยังพัฒนาอย่างต่อเนื่อง ถ้าสนใจเข้าไปดูได้ที่:
เครดิต: บทความนี้อ้างอิงข้อมูลจากเว็บไซต์ goish.cogentica.ai และ README ของ github.com/cogentica-ai/goish — โปรเจกต์โดย Chanwit Kaewkasi (@chanwit) ภายใต้ Cogentica AI (ประเทศไทย)
⚠️ Goish ไม่เกี่ยวข้องกับ Google หรือ Go project — "Go" เป็นเครื่องหมายการค้าของ Google LLC