แม้ว่าคำตอบที่ยอมรับจะยังคงถูกต้องเกี่ยวกับการต้องจับคู่ไดเรกทอรีกับชื่อแพ็กเกจ แต่คุณจำเป็นต้องย้ายไปใช้โมดูล Go แทนการใช้ GOPATH ผู้ใช้ใหม่ที่พบปัญหานี้อาจสับสนเกี่ยวกับการกล่าวถึงการใช้ GOPATH (เหมือนเดิม) ซึ่งตอนนี้ล้าสมัยแล้ว ดังนั้นฉันจะพยายามเคลียร์ปัญหานี้และให้คำแนะนำที่เกี่ยวข้องกับการป้องกันปัญหานี้เมื่อใช้โมดูล Go
หากคุณคุ้นเคยกับโมดูล Go อยู่แล้วและกำลังประสบปัญหานี้ให้ข้ามไปที่หัวข้อเฉพาะของฉันที่ด้านล่างซึ่งครอบคลุมอนุสัญญา Go บางส่วนที่ง่ายต่อการมองข้ามหรือลืม
คู่มือนี้สอนเกี่ยวกับโมดูล Go: https://golang.org/doc/code.html
การจัดโครงการด้วยโมดูล Go
เมื่อคุณย้ายไปที่โมดูล Go ตามที่กล่าวไว้ในบทความนั้นให้จัดระเบียบรหัสโครงการตามที่อธิบายไว้:
ที่เก็บประกอบด้วยหนึ่งโมดูลหรือมากกว่า โมดูลคือชุดของแพ็คเกจ Go ที่เกี่ยวข้องซึ่งเปิดตัวพร้อมกัน โดยทั่วไปที่เก็บ Go จะมีเพียงโมดูลเดียวซึ่งอยู่ที่รูทของที่เก็บ ไฟล์ชื่อ go.mod มีการประกาศเส้นทางโมดูล: คำนำหน้าพา ธ การนำเข้าสำหรับแพ็กเกจทั้งหมดภายในโมดูล โมดูลประกอบด้วยแพ็กเกจในไดเร็กทอรีที่มีไฟล์ go.mod ตลอดจนไดเร็กทอรีย่อยของไดเร็กทอรีนั้นจนถึงไดเร็กทอรีย่อยถัดไปที่มีไฟล์ go.mod อื่น (ถ้ามี)
เส้นทางของแต่ละโมดูลไม่เพียง แต่ทำหน้าที่เป็นคำนำหน้าพา ธ นำเข้าสำหรับแพ็กเกจเท่านั้น แต่ยังระบุตำแหน่งที่คำสั่ง go ควรค้นหาเพื่อดาวน์โหลด ตัวอย่างเช่นในการดาวน์โหลดโมดูล golang.org/x/tools คำสั่ง go จะดูที่เก็บข้อมูลที่ระบุโดยhttps://golang.org/x/tools (อธิบายเพิ่มเติมที่นี่)
เส้นทางการนำเข้าคือสตริงที่ใช้ในการนำเข้าแพ็กเกจ พา ธ การนำเข้าของแพ็กเกจคือพา ธ โมดูลที่เชื่อมต่อกับไดเร็กทอรีย่อยภายในโมดูล ตัวอย่างเช่นโมดูล github.com/google/go-cmp มีแพ็คเกจในไดเร็กทอรี cmp / เส้นทางการนำเข้าของแพ็กเกจนั้นคือ github.com/google/go-cmp/cmp แพ็กเกจในไลบรารีมาตรฐานไม่มีคำนำหน้าพา ธ โมดูล
คุณสามารถเริ่มต้นโมดูลของคุณได้ดังนี้:
$ go mod init github.com/mitchell/foo-app
รหัสของคุณไม่จำเป็นต้องอยู่บน github.com เพื่อสร้าง อย่างไรก็ตามเป็นแนวทางปฏิบัติที่ดีที่สุดในการจัดโครงสร้างโมดูลของคุณราวกับว่าจะมีการเผยแพร่ในที่สุด
ทำความเข้าใจกับสิ่งที่เกิดขึ้นเมื่อพยายามรับแพ็คเกจ
มีบทความดีๆที่พูดถึงสิ่งที่เกิดขึ้นเมื่อคุณพยายามรับแพ็คเกจหรือโมดูล: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
โดยจะกล่าวถึงตำแหน่งที่จัดเก็บแพ็คเกจและจะ ช่วยให้คุณเข้าใจว่าเหตุใดคุณจึงอาจได้รับข้อผิดพลาดนี้หากคุณใช้โมดูล Go อยู่แล้ว
ตรวจสอบว่าได้ส่งออกฟังก์ชันที่นำเข้าแล้ว
โปรดทราบว่าหากคุณมีปัญหาในการเข้าถึงฟังก์ชันจากไฟล์อื่นคุณต้องตรวจสอบให้แน่ใจว่าคุณได้ส่งออกฟังก์ชันของคุณแล้ว ตามที่อธิบายไว้ในลิงค์แรกที่ฉันให้ไว้ฟังก์ชันต้องขึ้นต้นด้วยตัวอักษรตัวพิมพ์ใหญ่เพื่อส่งออกและทำให้พร้อมใช้งานสำหรับการนำเข้าในแพ็คเกจอื่น
ชื่อไดเรกทอรี
รายละเอียดที่สำคัญอีกประการหนึ่ง (ตามที่กล่าวไว้ในคำตอบที่ยอมรับ) คือชื่อของไดเร็กทอรีคือสิ่งที่กำหนดชื่อแพ็กเกจของคุณ (ชื่อแพ็กเกจของคุณต้องตรงกับชื่อไดเร็กทอรี) คุณสามารถดูตัวอย่างได้ที่นี่: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc
ด้วย ที่กล่าวว่าไฟล์ที่มีmain
เมธอดของคุณ(เช่นจุดเริ่มต้นของแอปพลิเคชันของคุณ) ได้รับการยกเว้นจากข้อกำหนดนี้
ตัวอย่างเช่นฉันมีปัญหากับการนำเข้าเมื่อใช้โครงสร้างเช่นนี้:
/my-app
├── go.mod
├── /src
├── main.go
└── /utils
└── utils.go
ฉันไม่สามารถนำเข้ารหัสในแพ็คเกจutils
ของฉันmain
ได้
อย่างไรก็ตามเมื่อฉันใส่main.go
ไดเร็กทอรีย่อยของตัวเองดังที่แสดงด้านล่างการนำเข้าของฉันก็ใช้ได้ดี:
/my-app
├── go.mod
├── /src
├── /app
| └── main.go
└── /utils
└── utils.go
ในตัวอย่างนั้นไฟล์ go.mod ของฉันมีลักษณะดังนี้:
module git.mydomain.com/path/to/repo/my-app
go 1.14
เมื่อฉันบันทึก main.go หลังจากเพิ่มการอ้างอิงutils.MyFunction()
IDE ของฉันจะดึงการอ้างอิงไปยังแพ็คเกจของฉันโดยอัตโนมัติดังนี้:
import "git.mydomain.com/path/to/repo/my-app/src/my-app"
(ฉันใช้ VS Code กับนามสกุล Golang)
สังเกตว่าพา ธ อิมพอร์ตรวมไดเร็กทอรีย่อยไปยังแพ็กเกจ
การจัดการกับ repo ส่วนตัว
หากรหัสเป็นส่วนหนึ่งของ repo ส่วนตัวคุณต้องเรียกใช้คำสั่ง git เพื่อเปิดใช้งานการเข้าถึง มิฉะนั้นคุณอาจพบข้อผิดพลาดอื่น ๆ บทความนี้กล่าวถึงวิธีการทำเช่นนั้นสำหรับ Github ส่วนตัว BitBucket และ GitLab repos: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4
ยังมีการพูดถึงปัญหานี้ที่นี่: วิธีใดที่เหมาะสมในการ "รับ" ที่เก็บส่วนตัว?