ไปสร้าง:“ ไม่พบแพ็คเกจ” (แม้ว่าจะตั้งค่า GOPATH ไว้ก็ตาม)


139

แม้ว่าฉันจะGOPATHตั้งค่าอย่างถูกต้อง แต่ฉันก็ยังไม่สามารถ "go build" หรือ "go run" เพื่อค้นหาแพ็กเกจของตัวเองได้ ผมทำอะไรผิดหรือเปล่า?

$ echo $GOROOT
/usr/local/go

$ echo $GOPATH
/home/mitchell/go

$ cat ~/main.go
package main
import "foobar"
func main() { }

$ cat /home/mitchell/go/src/foobar.go
package foobar

$ go build main.go
main.go:3:8: import "foobar": cannot find package

ฉันพบปัญหาเดียวกันเมื่อไปรับgithub.com/adonovan/gopl.io/tree/master/ch1/helloworld เหตุผลก็คือไม่มีไฟล์ชื่อ helloworld.go เริ่มทำงานโดยจับคู่ชื่อแพ็คเกจและชื่อไฟล์
keniee van

อาจเป็นไปได้ว่าคุณต้องอัปเกรด Go ฉันมีปัญหาคล้ายกันที่ฉันมีโค้ดที่มีอยู่โดยใช้ go.mod เพื่อกำหนดโมดูล ในเครื่องทดสอบฉันดาวน์โหลดโค้ดและพยายามรวบรวม แต่ Go ให้ข้อผิดพลาดทุกประเภทเกี่ยวกับ GOPATH และไม่พบโมดูล มันคือ Go เวอร์ชัน 1.7 ทันทีที่ฉันอัปเกรด Go มันก็ใช้งานได้โดยไม่มีปัญหา
KyferEz

พิมพ์นี้เป็นเทอร์มินัลสำหรับคำอธิบายที่ทันสมัย$ go help gopath
A1rPun

คำตอบ:


163

มันไม่ทำงานเพราะคุณแฟ้มแหล่งที่มาไม่ได้อยู่ในไดเรกทอรีที่เรียกว่าfoobar.go และพยายามจับคู่ไดเรกทอรีไม่ใช่ไฟล์ต้นฉบับfoobargo buildgo install

  1. ตั้งค่า$GOPATHเป็นไดเร็กทอรีที่ถูกต้องเช่นexport GOPATH="$HOME/go"
  2. ย้ายfoobar.goไป$GOPATH/src/foobar/foobar.goและอาคารควรใช้งานได้ดี

ขั้นตอนที่แนะนำเพิ่มเติม:

  1. เพิ่ม$GOPATH/binไปของคุณ$PATHโดย:PATH="$GOPATH/bin:$PATH"
  2. ย้ายmain.goไปยังโฟลเดอร์ย่อยของ$GOPATH/srcเช่น$GOPATH/src/test
  3. go install testตอนนี้ควรสร้างไฟล์ปฏิบัติการ$GOPATH/binที่สามารถเรียกได้โดยพิมพ์testลงในเทอร์มินัลของคุณ

1
นี่ไม่ใช่บั๊ก? ฉันGOPATH=/usr/local/go-pkgsจึงมีลักษณะไปใน/usr/local/go-pkgs/src/<package-name>แหล่งที่มา แต่ทำให้มันอยู่ในgo get /usr/local/go-pkgs/src/gopkg.in/<package-name>เหตุใดฉันจึงต้องย้ายแพ็คเกจทั้งหมดด้วยตนเองหลังจากติดตั้งแล้ว? นั่นเป็นเรื่องโง่
โยสิยาห์

3
go getโดยปกติจะใส่แพ็กเกจลงไป$GOPATH/src/ดังนั้นหากคุณเรียกgo get domain.com/path/to/packageมันจะจบลง$GOPATH/src/domain.com/path/to/packageด้วย ฉันเดาว่าคุณพยายามดึงแพ็คเกจจากgopkg.in? หากเป็นเช่นนั้นเป็นพฤติกรรมที่ตั้งใจอย่างแท้จริงและคุณควรนำเข้าด้วยชื่อเต็มของพวกเขา เช่นimport "gopkg.in/yaml.v1"เป็นยังอธิบายไว้ในเอกสาร
fasmat

1
Ahhhh ฉันเห็น ขอบคุณที่ปัดเป่าความไม่รู้ของฉัน
โยสิยาห์

10

แก้ไข: เนื่องจากคุณหมายถึง GOPATH ดูคำตอบของfasmat (โหวตแล้ว)

ดังกล่าวใน " ฉันจะให้ไปพบแพคเกจของฉันได้อย่างไร " คุณจะต้องใส่แพคเกจในไดเรกทอรีxxxxxx

ดูข้อกำหนดภาษา Go :

package math

ชุดไฟล์ที่ใช้ร่วมกันในPackageNameรูปแบบเดียวกันกับการใช้งานแพคเกจ
การนำไปใช้งานอาจต้องการให้ซอร์สไฟล์ทั้งหมดสำหรับแพ็กเกจอยู่ในไดเร็กทอรีเดียวกัน

องค์กรรหัสกล่าวถึง:

เมื่อสร้างโปรแกรมที่นำเข้าแพ็กเกจ " widget" goคำสั่งจะค้นหาsrc/pkg/widgetภายใน Go root จากนั้นหากไม่พบแหล่งที่มาของแพ็กเกจที่นั่นจะค้นหาsrc/widgetภายในแต่ละพื้นที่ทำงานตามลำดับ

("พื้นที่ทำงาน" คือรายการเส้นทางในของคุณGOPATH: ตัวแปรนั้นสามารถอ้างอิงได้หลายเส้นทางเพื่อให้ "" ของคุณsrc, bin, pkgเป็น)


(คำตอบเดิม)

คุณควรตั้งค่าGOPATHเป็น ~ / go ไม่ใช่GOROOTตามที่แสดงใน " How to Write Go Code "

เส้นทาง Go ใช้เพื่อแก้ไขคำสั่งการนำเข้า ดำเนินการโดยและบันทึกไว้ในแพ็คเกจ go / build

GOPATHตำแหน่งรายการตัวแปรสภาพแวดล้อมที่จะมองหารหัสไป
ใน Unix ค่าคือสตริงที่คั่นด้วยโคลอน
ใน Windows ค่านี้คือสตริงที่คั่นด้วยอัฒภาค
ในแผน 9 ค่าคือรายการ

ที่แตกต่างจากGOROOT:

การแจกแจงไบนารี Go จะถือว่าพวกเขาจะถูกติดตั้งใน/usr/local/go(หรือc:\Goภายใต้ Windows) แต่สามารถติดตั้งในตำแหน่งอื่นได้
หากคุณทำเช่นนี้คุณจะต้องตั้งค่าGOROOTตัวแปรสภาพแวดล้อมเป็นไดเร็กทอรีนั้นเมื่อใช้เครื่องมือ Go


4
นอกจากนี้ยังมีวิดีโอแนะนำสั้น ๆ เกี่ยวกับการตั้งค่า GOPATH
Ulf Holm Nielsen

1
ขออภัยฉันแก้ไขคำถามเดิมแล้ว ทุกที่ที่ฉันพูดว่า GOROOT ฉันหมายถึง GOPATH
MitchellSalad

3

TL; DR:ปฏิบัติตามอนุสัญญา Go! (บทเรียนที่ได้เรียนรู้วิธีที่ยาก) ตรวจสอบรุ่นไปเก่าและลบพวกเขา ติดตั้งล่าสุด

สำหรับฉันแล้ววิธีแก้ปัญหาก็แตกต่างออกไป ฉันทำงานบนเซิร์ฟเวอร์ Linux ที่ใช้ร่วมกันและหลังจากตรวจสอบGOPATHตัวแปรสภาพแวดล้อมของฉันและอื่น ๆ หลายครั้งก็ยังไม่ทำงาน ฉันพบข้อผิดพลาดหลายประการรวมถึง 'ไม่พบแพ็คเกจ' และ 'เส้นทางการนำเข้าที่ไม่รู้จัก' หลังจากพยายามติดตั้งใหม่ด้วยโซลูชันนี้ตามคำแนะนำในgolang.org (รวมถึงส่วนการถอนการติดตั้ง ) ยังคงพบปัญหา

ใช้เวลาพอสมควรในการตระหนักว่ายังมีเวอร์ชันเก่าที่ยังไม่ได้ถอนการติดตั้ง (ทำงานgo versionแล้วwhich goอีกครั้ง ... DAHH) ซึ่งทำให้ฉันได้รับคำถามนี้และได้รับการแก้ไขในที่สุด


2

แม้ว่าคำตอบที่ยอมรับจะยังคงถูกต้องเกี่ยวกับการต้องจับคู่ไดเรกทอรีกับชื่อแพ็กเกจ แต่คุณจำเป็นต้องย้ายไปใช้โมดูล 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 ยังมีการพูดถึงปัญหานี้ที่นี่: วิธีใดที่เหมาะสมในการ "รับ" ที่เก็บส่วนตัว?


-6

คุณได้ลองเพิ่มไดเร็กทอรีที่สมบูรณ์ของgo ไปที่ 'path' ของคุณแล้วหรือยัง?

export PATH=$PATH:/directory/to/go/

$ PATH ไม่มีส่วนเกี่ยวข้องกับแพ็กเกจ path for go ของคุณ
csgeek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.