7 คะแนน โดย GN⁺ 2026-02-18 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ใน Go 1.26 ได้มีการนำคำสั่ง go fix ที่เขียนขึ้นใหม่ทั้งหมด มาใช้ เพื่อปรับปรุงโค้ดโดยอัตโนมัติให้ใช้ความสามารถล่าสุดของภาษาและไลบรารีได้
  • เครื่องมือนี้ใช้ analyzer หลายสิบตัว เพื่อตรวจจับแพตเทิร์นของโค้ด และใช้ modernizer หลากหลายแบบ เช่น minmax, rangeint, stringscut เพื่อแปลงโค้ดที่ซ้ำซากหรือล้าสมัยให้เป็นรูปแบบสมัยใหม่
  • มีการเพิ่ม analyzer newexpr เพื่อรองรับฟีเจอร์ใหม่ new(expr) ทำให้สามารถย่อ helper function อย่าง newInt ได้โดยอัตโนมัติ
  • go fix ให้ ผลแบบเสริมกันเมื่อรันหลายครั้ง โดย analyzer ต่าง ๆ สามารถเสนอการปรับปรุงต่อเนื่องกันได้ และยังมีการรวมการแก้ไขอัตโนมัติเมื่อเกิดการชนกัน รวมถึงการลบ import ที่ไม่จำเป็น
  • ทีม Go มีแผนขยายต่อไปด้วยพาราไดม์ Self-service เพื่อให้นักพัฒนาสามารถกำหนดและแจกจ่าย modernizer สำหรับ API ของตนเองได้

ภาพรวมของคำสั่ง go fix

  • ใน Go 1.26 go fix ถูก พัฒนาใหม่ทั้งหมด เพื่อให้สามารถแปลงโค้ดเบสเป็นสไตล์ Go สมัยใหม่ได้โดยอัตโนมัติ
    • ใช้คำสั่ง go fix ./... เพื่อแก้ไขทุกแพ็กเกจภายใต้ไดเรกทอรีปัจจุบัน
    • ใช้ตัวเลือก -diff เพื่อดูการเปลี่ยนแปลงล่วงหน้า
  • สามารถดูรายการ analyzer ที่ลงทะเบียนไว้ได้ด้วย go tool fix help ซึ่งมีทั้ง any, forvar, mapsloop, minmax และกฎการแปลงอื่น ๆ
  • หากต้องการรันเฉพาะ analyzer บางตัว ให้ใช้แฟลกอย่าง -any และหากต้องการยกเว้นให้ระบุ -any=false
  • สามารถรันหลายรอบตามชุด GOOS, GOARCH เพื่อคำนึงถึงความแตกต่างของโค้ดในแต่ละแพลตฟอร์ม

Modernizers — เครื่องมือทำโค้ดให้ทันสมัย

  • หลังจาก Go 1.18 ที่มีการนำ generics มาใช้ ก็ยิ่งเปิดโอกาสให้ทำโค้ดให้เรียบง่ายขึ้นได้มาก
    • ตัวอย่าง: ใช้ maps.Keys เพื่อรวบรวมคีย์ของ map, ใช้ strings.Cut เพื่อแยกสตริง
  • มีการเน้นย้ำถึงความจำเป็นในการอัปเดตโอเพนซอร์สโค้ดให้สะท้อน สำนวน Go ยุคใหม่ เพื่อแก้ปัญหาที่เครื่องมือสร้างโค้ดด้วย LLM มักยังคงใช้แพตเทิร์นแบบเก่า
  • modernizer ที่รวมอยู่ใน go fix และ gopls ช่วยเพิ่มทั้งความอ่านง่ายของโค้ดและผลด้านการเรียนรู้
  • ตัวอย่าง modernizer:
    • minmax: แทนที่ if statement ด้วยฟังก์ชัน min/max
    • rangeint: แปลงลูป for แบบ 3 ส่วนให้เป็น range-over-int
    • stringscut: ย่อโค้ดที่อิง strings.Index ให้เป็น strings.Cut

ฟีเจอร์ new(expr) ใน Go 1.26

  • ฟังก์ชัน new ถูกขยายให้ รับอาร์กิวเมนต์ที่เป็นค่าได้ ทำให้สามารถกำหนดค่าเริ่มต้นในรูปแบบ new("go1.26") ได้
  • analyzer newexpr จะค้นหา helper function อย่าง newInt แล้วทำให้เรียบง่ายเป็น return new(x) และแทนที่จุดเรียกใช้เป็น new(expr)
  • จะถูกนำมาใช้เฉพาะเมื่อผ่านเงื่อนไขเวอร์ชัน Go ขั้นต่ำเท่านั้น เช่นมี directive go 1.26
  • สามารถนำไปใช้กับทั้งโค้ดเบสได้ด้วยคำสั่ง $ go fix -newexpr ./...
  • หลังใช้งานแล้ว helper function ที่ไม่จำเป็นสามารถระบุได้ด้วยเครื่องมือ deadcode

การทำงานเสริมกันและการจัดการความขัดแย้ง

  • มี ผลแบบเสริมกัน ที่การแก้ไขหนึ่งครั้งจะสร้างโอกาสให้เกิดการแก้ไขอื่นต่อได้
    • เช่น หลังใช้ minmax แล้วอาจมีข้อเสนอการแปลงเพิ่มเติม
    • หรืออาจมีการปรับให้เหมาะสมต่อเนื่องจาก stringsbuilder ไปเป็น fmt.Fprintf
  • go fix ใช้ อัลกอริทึม 3-way merge เพื่อรวมการแก้ไขที่ชนกันโดยอัตโนมัติ
    • หากชนกันในระดับไวยากรณ์ จะข้ามการแก้ไขนั้นและแสดงคำเตือน
    • หากเป็นความขัดแย้งเชิงความหมาย เช่น การลบตัวแปรหรือ import ที่ไม่ถูกใช้งาน อาจต้องปรับด้วยตนเอง
    • import ที่ไม่จำเป็นจะถูกลบออกโดยอัตโนมัติ

การผสานเข้ากับ Go analysis framework

  • go vet และ go fix ถูกผสานให้ ใช้ analysis framework ร่วมกัน
    • vet เน้นการตรวจจับข้อผิดพลาด ส่วน fix เน้นการแก้ไขอัตโนมัติที่ปลอดภัย
  • analyzer สามารถทำงานได้บนไดรเวอร์หลากหลาย เช่น unitchecker, multichecker, gopls, staticcheck, Tricorder
  • สามารถแชร์ข้อมูลข้ามแพ็กเกจได้ผ่านระบบ fact
    • เช่น อนุมานได้ว่า log.Printf เป็น wrapper ของ fmt.Printf
  • gopls มีความสามารถในการวินิจฉัยแบบเรียลไทม์และเสนอการแก้ไขอัตโนมัติ

การปรับปรุงโครงสร้างพื้นฐานด้านการวิเคราะห์

  • มีการขยาย แพ็กเกจ inspector เพื่อเพิ่มประสิทธิภาพการสำรวจ AST และรองรับการนำทางขึ้นลงซ้ายขวาด้วยชนิด Cursor
  • การทำดัชนีการเรียกฟังก์ชันผ่าน typeindex ช่วยเพิ่มความเร็วในการวิเคราะห์ได้สูงสุดถึง 1000 เท่า
  • การปรับปรุงเพิ่มเติม ได้แก่:
    • การจัดเตรียม dependency graph ของ standard library
    • รองรับ การ query เวอร์ชัน Go รายไฟล์
    • ขยาย refactoring primitive เพื่อให้แก้ไขโค้ดอย่างปลอดภัยได้ เช่น การคอมเมนต์โค้ด
  • modernizer บางตัวถูกตัดออกเนื่องจากมีการเปลี่ยนแปลงพฤติกรรมที่ละเอียดอ่อน (กรณี append([]string{}, slice...)slices.Clone(slice))
  • ในอนาคตมีแผนพัฒนา pattern matching engine, automatic test harness, และ ไลบรารีตัวดำเนินการแก้ไขที่แม่นยำ

พาราไดม์ Self-service

  • ตั้งแต่ Go 1.26 เป็นต้นไป มีการประกาศใช้ โมเดลการวิเคราะห์แบบ Self-service
    • นักพัฒนาสามารถกำหนดและแจกจ่าย modernizer สำหรับ API ของตนเองได้
    • สามารถรันได้ในระดับโปรเจกต์โดยไม่ต้องผ่านกระบวนการอนุมัติแบบรวมศูนย์
  • ในก้าวแรก มีการรวมฟีเจอร์ annotation-driven inliner แบบพรีวิวไว้แล้ว
  • แผนในอนาคต:
    • รัน analyzer ที่ผู้ใช้กำหนดเองผ่าน dynamic loading (ภายใน go fix หรือ gopls)
    • ทำให้การตรวจสอบที่อิง control flow เป็นแบบทั่วไป เช่น ตรวจสอบเงื่อนไขคงที่อย่าง “open แล้วต้อง close”, “lock แล้วต้อง unlock”
  • เป้าหมายคือเพิ่มประสิทธิภาพในการดูแลรักษา และช่วยให้นำฟีเจอร์ใหม่ของ Go มาใช้ได้รวดเร็วยิ่งขึ้น

1 ความคิดเห็น

 
GN⁺ 2026-02-18
ความคิดเห็นจาก Hacker News
  • ช่วงปลายปี 2024 ตอนที่ผู้ช่วยเขียนโค้ด LLM แพร่หลายอย่างรวดเร็ว สิ่งที่น่าสนใจคือเครื่องมือพวกนี้มีแนวโน้มจะเลียนแบบ สไตล์โค้ด Go แบบเดิม จากข้อมูลฝึกมาแบบเดิมตามนั้น
    ต่อให้สั่งให้ใช้ไวยากรณ์ใหม่ก็มักจะเมิน หรือบางครั้งถึงขั้นบอกว่าสิ่งนั้นไม่มีอยู่จริง
    ถ้าอยากให้โมเดลในอนาคตสะท้อน แนวปฏิบัติแบบ Go 1.25 ล่าสุด โค้ดโอเพนซอร์สทั้งระบบก็คงต้องอัปเดตไปใช้สไตล์นั้นก่อน

    • ฝั่ง PHP ก็เคยมีความพยายามจะเก็บกวาด คำแนะนำเก่า บน Stack Overflow มาก่อน เช่น magic_quotes
      แต่พอ LLM ได้ข้อมูลผิดเข้าไปครั้งหนึ่งแล้ว แทบจะไม่มีทางแก้ได้เลย
      ตามรอยได้ยากว่าโมเดลสรุปออกมาจากอะไร สุดท้ายก็ได้แต่หวังว่าโมเดลรุ่นถัดไปจะดีขึ้น
    • โค้ด concurrency ของ Go ที่ LLM สร้างขึ้นนั้นอันตรายเป็นพิเศษ
      มันดูเรียบง่ายจนรีวิวผ่านได้ แต่จริง ๆ แล้วกลับขาดการจัดการ error และ edge case
      พอเอากลับเข้า LLM หลังรีวิว มันก็จะให้โค้ดที่ดูเหมือนแก้แล้วออกมา แต่ข้างในกลับมี data race หรือ deadlock แทรกอยู่
      เป็นปัญหาที่เกิดซ้ำในแทบทุกโมเดล
    • ฉันก็เจอปัญหาแบบนี้บ่อยเหมือนกัน
      Go รองรับย้อนหลังได้ดี เลยยังคอมไพล์ผ่าน แต่สไตล์โค้ดจะต่างกันมาก
      ส่วน Python จะเจอ ความเข้ากันได้พังจริง ๆ จากการเปลี่ยน API
      ถึงอย่างนั้น Go ก็ยังยอดเยี่ยมมากในฐานะ ภาษาสำหรับสร้างโค้ด เพราะตัวภาษาเสถียรและมี standard library ที่ดี
    • สุดท้ายแล้วการใช้ LLM ก็คงทำให้เกิด โค้ดที่เหมือน ๆ กันและธรรมดา ๆ เป็นจำนวนมาก
    • ฉันคิดว่าเราควรเลิกแนวคิดเรื่องการให้ LLM เขียนโค้ดไปเลย
      อย่างที่ Rob Pike เคยเตือนไว้ เทคโนโลยีแบบนี้คือ มลพิษของระบบนิเวศซอฟต์แวร์
      หลายคนต้องการ slop ในชื่อของ ‘ความสะดวก’ แต่นั่นแหละคือแก่นของปัญหา
  • เครื่องมือที่ช่วย แปลงซอร์สโค้ดไปเป็นสไตล์ล่าสุด ได้อัตโนมัตินั้นยอดเยี่ยมมาก
    ตัวอย่างเด่นคือ OpenRewrite ของ Java แต่พอนึกถึงภาษาอื่นกลับไม่ค่อยมีอะไรคล้ายกัน
    ถ้าฟีเจอร์แบบนี้ฝังมาในภาษาเหมือน Go ก็ถือว่าเพิ่ม ความเป็นผู้ใหญ่ของภาษา ได้มาก
    ต่อไปภาษารุ่นใหม่ ๆ น่าจะเอาแนวทางแบบบูรณาการของ Go ไปเป็นตัวอย่าง

    • ฝั่งภาษา C มี Coccinelle และเคยถูกแนะนำไว้ในบทความ LWN ปี 2009
      IDE ของ JetBrains สามารถ refactor โค้ดหลายล้านบรรทัดพร้อมกัน หรือแปลงไปเป็นไวยากรณ์ใหม่แบบอัตโนมัติได้
      มีฟีเจอร์อย่าง ConvertToPrimaryConstructor ด้วย
      นอกจากนี้ Structural Search and Replace ก็ทำงานในระดับ ไวยากรณ์ของภาษา ไม่ใช่แค่ข้อความธรรมดา
      ตัววิเคราะห์ Roslyn ของ .NET ก็ให้คำแนะนำการแก้โค้ดใน IDE ได้เช่นกัน
      ลิงก์ tutorial
    • clippy ของ Rust ก็แนะนำไวยากรณ์สมัยใหม่ และบางส่วนก็แก้อัตโนมัติได้ด้วย
      ทำให้โค้ดสะอาดขึ้นมาก
    • hlint ของ Haskell ก็มีมานานแล้ว
      มันช่วยเปลี่ยน concat กับ map เป็น concatMap หรือทำให้ if ที่ไม่จำเป็นง่ายลงได้
    • อยากรู้ว่ามีใครเคยแปลงโค้ดเบส TypeScript แบบนี้บ้างไหม
      เซิร์ฟเวอร์ LSP ยังมีความสามารถไม่พอ และยังไม่รองรับแม้แต่ refactor พื้นฐานอย่างการลบ argument
      เลยกำลังคิดอยู่ว่าถ้าเอา jscodeshift มาจับคู่กับ Claude จะพอทำได้ไหม
  • Go เป็นภาษาที่ยอดเยี่ยมจริง ๆ ก็เพราะมี เครื่องมือแก้อัตโนมัติ (go fix) แบบนี้
    ฟีเจอร์ใหม่อย่าง rangeint ก็มีแผนจะรองรับอัตโนมัติผ่าน go fix ด้วย เลยน่าคาดหวังมาก
    ขอชื่นชมทีม Go

    • หลายครั้งก็อยากใช้ภาษาอื่น แต่ เครื่องมือ build, test, lint ของ Go มันดีเกินจะต้าน สุดท้ายเลยกลับมาใช้ Go อยู่ดี
      ความเร็วคอมไพล์ก็เร็วแบบน่าเหลือเชื่อ
    • เมื่อก่อนฉันต้องใช้ regex หา for loop แล้วแก้เอง แต่ตอนนี้เครื่องมือนี้จัดการให้ได้อย่าง ประณีตกว่ามาก
  • ในบทความไม่ได้พูดถึง แต่ฟีเจอร์ที่ฉันชอบที่สุดคือ directive //go:fix inline
    มันจะ inline ฟังก์ชันบรรทัดเดียวเข้าไปในจุดเรียกใช้
    ทำให้คนเขียนไลบรารีสามารถ ย้ายเวอร์ชันอัตโนมัติ จากฟังก์ชันเก่าไปใหม่ได้อย่างลื่นไหล
    ต่อให้ semver เปลี่ยนก็ยังอัปเกรดอัตโนมัติได้ด้วย go fix

  • ในพอดแคสต์ของ Wes McKinney ที่เพิ่งดูมา
    เขาบอกว่า Go เหมาะกับ coding agent มาก เพราะมี วงจรคอมไพล์-รันที่เร็ว, ระบบ type ที่แข็งแรง, และ ความปลอดภัยด้านมัลติเธรด
    ฟังแล้วก็กลับมาสนใจ Go อีกครั้ง

  • ชุดเครื่องมือและธรรมเนียมปฏิบัติ ที่เป็นรูปเป็นร่างของ Go ช่วยงานพัฒนาแบบเอเจนต์ได้มาก
    ใช้ go run main.go เพื่อยกสภาพแวดล้อมพัฒนาขึ้นมาได้ทันที และยังรองรับหลาย worktree, การตั้งค่ากลาง, รวมถึงฐานข้อมูลที่ migrate แล้ว
    เครื่องมือแบบนี้ถูกแชร์ไว้ใน housecat-inc/cheetah
    ตอนนี้กำลังคิดจะเพิ่ม go fix เข้าไปในลูปที่เร็วอยู่แล้วซึ่งมี go generate, go build, go test, go vet

    • ความเร็วคอมไพล์ระดับสูงมาก เป็นข้อได้เปรียบใหญ่สำหรับการทดลองซ้ำ ๆ กับ LLM ด้วย
  • พอไปเรียน Python แล้วรู้สึกว่าวิธีทำสิ่งเดียวกันมี เยอะเกินไปและไม่ค่อยสม่ำเสมอ
    เลยกลับคิดถึงภาษาแบบ C ที่มีวิธีหลัก ๆ แค่แบบเดียว
    เลยสงสัยว่า Go ไปถึงจุดนั้นหรือยัง
    อยากรู้ว่าเป็นภาษาที่ทำตาม best practice ได้โดยไม่ต้องพึ่ง LLM หรือเปล่า

    • Go เป็นภาษาแบบ มีจุดยืนชัดเจน มาก เลยทำให้ส่วนใหญ่มีทางทำอยู่แค่แบบเดียว
      ความพยายามในการไม่ทำให้มันซับซ้อนและคงความเรียบง่ายไว้นั้นน่าประทับใจมาก
      ถ้าใครเริ่มเหนื่อยกับความสับสนของ Python ก็แนะนำเลย
  • แนวคิดเรื่อง self-service analyzer น่าสนใจมากจริง ๆ
    น่าจะถูกใช้กันอย่างจริงจังในทีมไลบรารีขนาดใหญ่หรือทีมโครงสร้างพื้นฐาน

  • พอมีเครื่องมือแบบนี้ ก็ชวนให้คิดว่าแม้แต่ ภาษาที่ไม่รองรับ backward compatibility ก็น่าจะยังพอเป็นไปได้ไหม

  • ในโลกของ TypeScript มี biome ที่ทำหน้าที่แนวนี้
    อย่างเช่นมันจะแนะนำให้ใช้ for...of แทน forEach และถ้าใช้ร่วมกับ ultracite เวิร์กโฟลว์จะลื่นขึ้นมาก
    ฉันใส่ไว้ในไฟล์ agents.md เลยว่า “หลังแก้แล้วให้รัน biome fix” ผลคือคุณภาพโค้ดถูกรักษาไว้แบบอัตโนมัติ
    เป็นประสบการณ์ที่ เบาและมีประสิทธิภาพกว่า eslint มาก