cd /news/developer-tools/goish-ph-rtranaithmkh-ng-go-thangtaw… · home topics developer-tools article
[ARTICLE · art-97593] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Goish: พอร์ตรันไทม์ของ Go ทั้งตัวลงใน no_std Rust

Chanwit Kaewkasi, an engineer from Thailand, has released Goish, a Rust runtime that ports Go 1.25's standard library and runtime to no_std Rust, eliminating the garbage collector and relying on Rust's ownership for memory management. The project aims to provide provenance at the function level, addressing compliance requirements like the EU Cyber Resilience Act and FIPS 140-2, by annotating each ported function with its source location in the Go tree and verifying it via CI.

read4 min views1 publishedAug 15, 2026

📅 เขียนเมื่อ: สิงหาคม 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

── more in #developer-tools 4 stories · sorted by recency
── more on @chanwit kaewkasi 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/goish-ph-rtranaithmk…] indexed:0 read:4min 2026-08-15 ·