ภาพรวม
นี่คือเค้าโครงพื้นฐานสำหรับโปรเจกต์แอปพลิเคชัน Go มัน ไม่ใช่มาตรฐานที่ถูกกำหนดอย่างเป็นทางการโดยทีมพัฒนาของ Go
; มันคือโครงสร้างไดเร็กทอรี่ที่ใช้กันอย่างแพร่หลายสำหรับโปรเจกต์ Go ของชุมชน
ถ้าคุณกำลังเรียนรู้ Go หรือกำลังสร้าง proof of concept (PoC) หรือโปรเจกต์ส่วนตัวที่เรียบง่ายโปรเจกต์
นี้ เป็นซับซ้อนเกินไป แทนที่นั้น คุณควรเริ่มต้นด้วยโครงสร้างที่แท้จริงและเรียบง่าย (เพียงแค่ไฟล์ main.go
และ go.mod
พอ) เมื่อโปรเจกต์ของคุณเติบโต ให้ตรวจสอบว่าโค้ดโครงสร้างของคุณดีพอ ไม่งั้นคุณจะได้รับโค้ดที่ยุ่งเหยิงซึ่งมีความขึ้นอยู่กับการตรึงเชิงและสถานะโกลบอล เมื่อมีผู้คนมาเข้ามามีส่วนร่วมในโปรเจกต์ คุณจำเป็นต้องมีวิธีที่มีโครงสร้างมากขึ้น ในกรณีนี้มันสำคัญที่จะนำเสนอวิธีการจัดการแพ็คเกจ/ไลบรารีที่สามารถใช้งานร่วมกัน เมื่อคุณมีโปรเจกต์โอเพ่นซอร์สหรือทราบว่าโปรเจกต์โอนอื่นนำโค้ดมาจากที่เก็บโค้ดโปรเจกต์ของคุณมีการเก็บแพ็คเกจผสม (เรียกว่า internal
) และโค้ดจึงสำคัญ โคลนที่เก็บโค้ดไว้เก็บส่วนที่คุณต้องการ และลบสิ่งที่ทั้งหมด! แค่เพราะมันมีอยู่แล้วไม่จำเป็นที่คุณจะต้องใช้มันทั้งหมด ไม่มีรูปแบบทั้งหมดถูกใช้ในทุกโปรเจกต์ แม้แต่รูปแบบ vendor
ก็ไม่ได้เป็นที่ยอมรับทั้งหมด
โครงสร้างโปรเจกต์นี้ถูกออกแบบโดยประมาณเพื่อที่จะเป็นทางทั่วไปและไม่แสวงหาที่จะบังคับโครงสร้างแพ็คเกจของ Go ที่กำหนดเองเป็นทางเฉพาะ
การระบุโครงสร้างโปรเจกต์ Go
ด้านล่างนี้คือการระบุโครงสร้างไดเร็กทอรีของโปรเจกต์ Go ที่แนะนำ
.
├── go.mod
├── api
├── assets
├── build
├── cmd
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── go.mod
├── init
├── internal
├── pkg
├── scripts
├── test
├── third_party
├── tools
├── vendor
├── web
└── website
ความหมายของแต่ละไดเร็กทอรีถูกนำเสนอดังต่อไปนี้
/cmd
แอปพลิเคชันหลักของโปรเจกต์ ก็คือจุดเข้าสู่โปรแกรม เป็นไฟล์ Go ในไดเร็กทอรีนี้ที่ปกติจะสร้างไฟล์ที่เป็นไฟล์ทำงานได้. การใช้งานของแต่ละไฟล์ในไดเร็กทอรีต้องตรงกับชื่อของไฟล์สำหรับการทำงานได้ที่คุณต้องการ (เช่น /cmd/myapp
).
อย่าใส่โค้ดมากเกินไปในไดเร็กทอรีแอปพลิเคชัน หากคุณคิดว่าโค้ดสามารถนำเข้าและใช้ในโปรเจกต์อื่นได้ให้วางไว้ในไดเร็กทอรี /pkg
หากโค้ดไม่สามารถนำไปใช้ใหมดหรือคุณไม่ต้องการให้คนอื่นนำไปใช้ ให้วางโค้ดไว้ในไดเร็กทอรี /internal
คุณจะตกใจกับพฤติกรรมของคนอื่น ดังนั้นแสดงความตั้งใจของคุณได้ชัดเจน!
มักจะมีฟังก์ชันหลักที่เล็กน้อยที่นำเข้าและเรียกโค้ดจากไดเร็กทอรี /internal
และ /pkg
และไม่มีอะไรมาก
/internal
โค้ดแอปพลิเคชันและไลบรารีส่วนตัวนี้คือโค้ดที่คุณไม่ต้องการให้ผู้อื่นนำไปนำเข้าไปในแอปพลิเคชันหรือไลบรารีของพวกเขา โปรดทราบว่าเกริ่นนี้ได้ถูกบังคับโดยตัวคอมไพเลอร์ Go เอง สำหรับข้อมูลเพิ่มเติมโปรดอ้างถึง release notes สำหรับ Go 1.4 ทราบว่ามันไม่จำกัดที่จะต้องเป็นไดเร็กทอรี internal
ในระดับบนสุดได้ คุณสามารถมีไดเร็กทอรี internal
หลายตัวในทุกระดับของต้นไม้ของโปรเจกต์
คุณสามารถเลือกที่จะเพิ่มโครงสร้างเพิกเก็จเสริมสำหรับแพ็คเกจส่วนที่เป็นแบ่งแยกระหว่างโค้ดแบ่งปันและโค้ดในตัวนี้ นี้ไม่จำเป็น (โดยเฉพาะสำหรับโปรเจกต์ขนาดเล็ก) แสดงให้เห็นว่าวิธีการใช้แพ็คเกจเหมาะสม
/pkg
โค้ดไลบรารีซึ่งสามารถนำไปใช้โดยแอปพลิเคชันภายนอก (เช่น /pkg/mypubliclib
) โปรเจกต์โดยอื่นๆ จะนำไลบรารีเหล่านี้นำเข้าและคาดหวังว่ามันจะทำงานอย่างถูกต้องดังนั้นกรุณาคิดอย่างรอบคอบก่อนที่จะวางเนื้อหาที่นี่ :-) เกริ่นนี้ไดเร็กทอรี internal
เป็นวิธีที่ดีกว่าในการให้แน่ใจว่าแพ็คเกจส่วนตัวไม่สามารถนำเข้าได้ เพราะมันถูกบังคับจาก Go เอง ไดเร็กทอรี /pkg
ก็ยังเป็นทางที่ดีในการแสดงอย่างชัดเจนว่าโค้ดในไดเร็กทอรีนี้สามารถใช้งานได้
หากโปรเจกต์แอปพลิเคชันของคุณมีขนาดเล็กมากและไม่มีการซ้อนซ้อนที่มีประโยชน์มาก ๆ ก็ไม่เป็นไรที่จะไม่ใช้มัน (นอกจากคุณจะต้องการใช้มันแน่ๆ) ขณะที่โปรเจกต์กลายเป็นใหญ่พอและไดเร็กทอรีรากกลายเป็นที่วุ่งวายมากมาย ผลิตการใช้มัน (โดยเฉพาะหากคุณมีส่วนประกอบของแอปพลิเคชันที่ไม่ใช่ Go มากมาย)
/vendor
ความขึ้นต้นของแอปพลิเคชัน (ที่จัดการโดยคนหรือใช้เครื่องมือการจัดการความขึ้นด้วยลักษณะของ Go Modules
ที่มาในตัว). คำสั่ง go mod vendor
จะสร้างไดเร็กทอรี /vendor
ของคุณ. โปรดทราบว่าหากคุณไม่ได้ใช้รุ่นเริ่มต้นที่เปิดใช้งานอยู่ของ Go 1.14 คุณอาจจำเป็นต้องเพิ่มธง -mod=vendor
และให้กับคำสั่ง go build
.
หากคุณกำลังสร้างไลบรารี โปรดอย่าคอมมิตอะพลิเคชันของคุณที่เป็นตัวลูกของคุณ.
ไดเร็กทอรีแอปพลิเคชันบริการ
/api
สเปกิเฟิเคชัน OpenAPI/Swagger ไฟล์ JSON schema, ไดเร็กทอรีของการกำหนดโปรโตคอล และโปรโตคอล API.
ไดเร็กทอรีแอปพลิเคชันเว็บ
/web
คอมโพเนนต์ที่เฉพาะเจาะจงสำหรับแอปพลิเคชันเว็บ: คุณสมบัติเว็บไซต์สแตติก, เทมเพลตเซิร์ฟเวอร์, และ single-page applications (SPAs).
ไดเร็กทอรีแอปพลิเคชันทั่วไป
/configs
ไฟล์กำหนดค่าเทมเพลต หรือการกำหนดค่าเริ่มต้น.
วางไฟล์เท็มเพลต confd
หรือ consul-template
ที่นี่.
/init
เริ่มต้นระบบ (systemd, upstart, sysv) และการกำหนดค่าผู้จัดการกระบวนการ/daemon (runit, supervisord).
/scripts
สคริปต์สำหรับการสร้าง, การติดตั้ง, การวิเคราะห์ และปฏิบัติการอื่น ๆ.
/build
การแพกเกจและการอินทิกระบวนการต่อเนื่อง.
วางการกำหนดแพ็คเกจในคลาวด์ (AMI), คอนเทนเนอร์ (Docker), ระบบปฏิบัติการ (deb, rpm, pkg) และสคริปต์ในไดเร็กทอรี /build/package
.
วางการกำหนดและสคริปต์ของกระบวนการต่อเนื่อง (travis, circle, drone) ในไดเร็กทอรี /build/ci
. โปรดทราบว่าเครื่องมือกระบวนการต่อเนื่องบางอย่าง (เช่น Travis CI) สามารถระบุสถานที่ของไฟล์กำหนดค่าได้อย่างเฉพาะเจาะจง พยายามจัดที่ไฟล์กำหนดค่าในไดเร็กทอรี /build/ci
และใช้ลิงค์เชื่อมต่อไปยังสถานที่ที่เครื่องมือกระบวนการต่อเนื่องต้องการ (หากเป็นไปได้).
/deployments
การกำหนดค่าการดีพลอยและเทมเพลตสำหรับ IaaS, PaaS, ระบบ, และ Container Orchestration (docker-compose, kubernetes/helm, terraform). โปรดทราบว่าในบางส่วนคลังข้อมูล (โดยเฉพาะสำหรับแอพพลิเคชันที่ดีพลอยโดยใช้ Kubernetes) ไดเร็กทอรีนี้ถูกเรียกว่า /deploy
.
/test
แอพพลิเคชันการทดสอบภายนอกและข้อมูลการทดสอบอื่น ๆ. กรุณาองค์รายไดเร็กทอรี /test
อย่างไรก็ได้ตามที่เหมาะกับความต้องการของคุณ. สำหรับโปรเจกต์ขนาดใหญ่การจัดกลุ่มข้อมูลเข้าไดเร็กทอรีย่อยเป็นสิ่งที่เหมาะสม. ตัวอย่างเช่น คุณสามารถสร้างไดเร็กทอรี /test/data
หรือ /test/testdata
ภายในไดเร็กทอรี /test
เพื่อให้ Go ละเว้นเนื้อหา. โปรดทราบว่า Go ยังจะละเว้นไดเร็กทอรีหรือไฟล์ที่ขึ้นต้นด้วย "." หรือ "_" ซึ่งช่วยเสริมความยืดหยุ่นในการตั้งชื่อไดเร็กทอรียข้อมูลทดสอบ.
ไดร์ไร็กทอรีอื่น ๆ
/docs
เอกสารการออกแบบและผู้ใช้ (นอกเหนือจากเอกสาร godoc ที่คุณสร้าง).
/tools
เครื่องมือที่สนับสนุนสำหรับโปรเจกต์นี้. โปรดทราบว่าเครื่องมือเหล่านี้สามารถนำเข้าโค้ดจากไดเร็กทอรี /pkg
และ /internal
.
/examples
ตัวอย่างสำหรับแอพพลิเคชัน และ/หรือห้องสมุดสาธารณะ.
/third_party
เครื่องมือช่วยแอ็ดจัตเตอร์ภายนอก โค้ดที่ fork และเครื่องมือประโยชน์จากบุคคลที่สาม (เช่น Swagger UI).
/githooks
Git hooks.
/assets
ทรัพยากรเพิ่มเติม (รูปภาพ, โลโก้, ฯลฯ) ที่ให้ไว้ในคลังข้อมูล.
/website
ตำแหน่งสำหรับเก็บข้อมูลเว็บไซต์โปรเจกต์หากคุณไม่ได้ใช้ GitHub Pages.
/src
โปรเจกต์ Go บางตัวอาจมีไดเร็กทอรี src
, แต่นี้มักเป็นเพราะนักพัฒนามาจากโลกของ Java ที่เป็นแบบแบรน แต่หากเป็นไปได้โปรดพยายามหลีกเลี่ยงแบบแบรนแบบนี้เหมือนภาษา Java:-) คุณจริงๆ ไม่ต้องการให้โค้ดหรือโปรเจกต์ของคุณดูเหมือน Java:-)
โปรดอย่าสับสนไดเร็กทอรีระดับโปรเจกต์ /src
กับไดเร็กทอรี /src
ที่ใช้สำหรับช่องทำงาน Go ตามที่อธิบายไว้ใน How to Write Go Code
. ตัวแปรสภาพแวดล้อม $GOPATH
ชี้ไปยังที่ทำงาน (ปัจจุบัน) ของคุณ (โดยปกติบนระบบที่ไม่ใช่ Windows มันชี้ไปที่ไดเร็กทอรี $HOME/go
). ที่ทำงานนี้ประกอบด้วยไดเร็กทอรีระดับบนสุด /pkg
, /bin
, และ /src
. โปรเจกต์จริงของคุณจะเป็นไดเร็กทอรีย่อยภายใต้ไดเร็กทอรี /src
ดังนั้นหากโปรเจกต์ของคุณมีไดเร็กทอรี /src
เส้นทางโปรเจกต์จะมีลักษณะดังนี้: /some/path/to/workspace/src/your_project/src/your_code.go
. โปรดทราบว่าตั้งแต่ Go 1.11 เป็นต้นไปโปรเจกต์ของคุณสามารถอยู่นอก GOPATH
แต่นั้นไม่ได้หมายความว่าใช้แบบแบรนแบบนี้คือไอเดียที่ดี