จาก course Practical Go นั้นหนึ่งในเรื่องที่น่าสนใจอีกแล้ว
คือ Project structure นั่นเอง
เนื่องจากเป็นเรื่องที่มีการพูดคุยใน community เยอะมาก ๆ
ที่สำคัญมีหลากหลายแนวทางมาก ๆ อยู่ที่ว่าใครจะมองและวางออกมา
มาดูว่า มีคำแนะนำอะไรดี ๆ กันบ้าง

ปล. สิ่งสำคัญมาก ๆ ที่ได้เข้าใจมากขึ้นคือ  ความเข้าใจของคนในทีมนั่นเอง

หลังจากที่อธิบายเรื่องของการออกแบบ package ไปแล้ว
แต่ระบบงานของเราจะมี package จำนวนมากทำงานร่วมกัน ซึ่ง code มักจะอยู่ใน repository เดียวกัน

ปล. ในอนาคต community ของ Go นั้น
นักพัฒนาอาจจะพูดคำว่า module หรือ project ก็ได้
ซึ่งมีความหมายเดียวกัน จากการมาของ Go module นั่นเอง

สิ่งหนึ่งที่ยังจำได้คือ

การออกแบบ package นั้นจะต้องมีชื่และหน้าที่รับผิดชอบที่ชัดเจน
มาถึง project ก็เช่นกัน ควรมีหน้าที่ชัดเจน ควรมีเป้าหมายชัดเจน
ยกตัวอย่างเช่น project ที่สร้างเป็น library
ก็ต้องระบุให้ชัดเจนว่า library นั้นทำอะไร เช่น json parser, logging เป็นต้น

แน่นอนว่า ต้องระวังเรื่องการทำงานหลาย ๆ เรื่องใน library เดียวกัน
อาจจะทำให้เกิด common library ขึ้นมาอีกก็เป็นได้ !!
ก่อให้เกิดปัญหามากมาย ทั้งการผูกมัดที่มากเกินไป
ทั้งผลกระทบจากการแก้ไขอีกต่างหาก

ต่อมาคือเรื่องของจำนวน package

หนึ่งในปัญหาที่พบเจอมาก ๆ จากนักพัฒนาที่มาจากภาษาอื่น ๆ เช่น java และ C#
คือ การใช้หรือสร้าง package เยอะจนเกินไป
แน่นอนว่า การแบ่งกลุ่มการทำงานเป็นสิ่งที่ดี
แต่ถ้าเริ่มต้นแบบนี้ในภาษา Go เป็นการเริ่มต้นที่ไม่ค่อยถูกนัก
เพราะว่าตามแนวทางของภาษาคือ 
จะเริ่มจากเล็ก ๆ แล้วค่อย ๆ สร้างและขยายไปเรื่อย ๆ
ทำให้บางครั้งจะขัดใจของใครหลาย ๆ คน
แต่มันคือธรรมชาติและความป้าหมายของภาษานั่นเอง

อีกอย่างหนึ่งในภาษา Go
จะมี visibility เพียง public และ private เท่านั้น
ต่างจากภาษาอื่น ๆ เช่น Java มีทั้ง public, protected, default และ private
ดังนั้นถ้ามี package จำนวนมาก ๆ
อาจจะก่อให้เกิดปัญหาในการจัดการก็เป็นไปได้

คำถามที่น่าสนใจคือ แล้ว project เราควรมีโครงสร้างอย่างไรบ้าง ?

จากใน course แนะนำไว้ดังนี้ ในแต่ละ package ใน project นั้น
ให้เริ่มจากไฟล์เดียวที่ชื่อเหมือนกับ package
เช่น http package จะมีไฟล์ชื่อว่า http.go
ถ้า package มีการทำงานมากขึ้น
ให้ทำการสร้างไฟล์ตามหน้าที่ความรับผิดชอบ เช่น

  • message.go สำหรับโครงสร้างข้อมูลของ request และ response
  • client.go สำหรับการทำงานฝั่ง client
  • server.go สำหรับการทำงานฝั่ง server

สิ่งที่เพิ่งรู้คือ

การ compile ของภาษา Go นั้น จะทำการ compile แบบ parallel กัน
ไปตามแต่ละ package นั่นหมายความว่า
ถ้าเราทำงาน refactor ใน package เดียวกันแล้ว
ผลที่ได้คือ ไม่ได้ช่วยให้ compile เร็วขึ้นนะ

และอีกอย่างคือ package net/http นั้น ไม่ได้เป็น sub-package ของ net package
มันคนละ package กันนะ
เป็นเรื่องที่ต่างจากภาษาอื่น ๆ เช่น java และ c# 

มีคำแนะนำในการใช้งาน package ใน project ไว้ดังนี้

  • cmd สำหรับเก็บ package main
  • internal สำหรับลด scope ของ public API ใน package หนึ่ง ๆ ให้ใช้ได้จาก base package เท่านั้น ไม่สามารถใช้ได้จาก package อื่น ๆ ซึ่งตรงนี้ทำให้จัดการ scope ของ package ได้ดียิ่งขึ้น

อีกสิ่งหนึ่งที่แนะนำอย่างแรงคือ package main ให้เล็กที่สุด

ใน package นี้คือ จุดเริ่มต้นของการทำงาน ทำงานเพียงครั้งเดียว
ดังนั้นมี code เท่าที่จำเป็นก็พอ เช่น

  • การ parsing parameter ต่าง ๆ
  • การ initial ข้อมูลจากไฟล์
  • การ initial logger
  • การสร้าง connection ไปยัง database

จากคำแนะนำต่าง ๆ ก็พบว่ามี project ตัวอย่างที่น่าสนใจตัวหนึ่งคือ

Starter code for writing web service in Go
น่าจะใช้เป็นตัวอย่างและแนวทางในการออกแบบได้เลย