Bagaimana cara mengimpor paket lokal di go?

90

Saya baru memulai dan mengerjakan kode contoh yang ingin saya lokalkan.

Dalam main.gopernyataan impor asli itu adalah:

 import (
    "log"
    "net/http"
    "github.com/foo/bar/myapp/common"
    "github.com/foo/bar/myapp/routers"
)

Sekarang saya memiliki commondan routersmengemas/home/me/go/src/myapp

Jadi saya mengonversi pernyataan impor menjadi:

import (
    "log"
    "net/http"
    "./common"
    "./routers"
)

Tetapi ketika saya menjalankan go install myappsaya mendapatkan kesalahan ini:

can't load package: /home/me/go/src/myapp/main.go:7:3: local import "./common" in non-local package

Juga, ketika saya menggunakan commondan routersbukannya ./commondan ./routersdalam pernyataan impor, saya mendapatkan:

myapp/main.go:7:3: cannot find package "common" in any of:
    /usr/local/go/src/common (from $GOROOT)
    /home/me/go/src/common (from $GOPATH)
myapp/main.go:8:2: cannot find package "routers" in any of:
    /usr/local/go/src/routers (from $GOROOT)
    /home/me/go/src/routers (from $GOPATH)

Bagaimana cara memperbaikinya?

Karlom
sumber
5
Semua impor bersifat "lokal", apa pun jalur impornya. Lihat "Cara Menulis Kode Go" untuk penjelasan rinci.
JimB
21
@JimB mengesampingkan perdebatan filosofis, yang menjadi perhatian saya adalah bagaimana menyelesaikan masalah tersebut di atas.
Karlom
3
Saya tidak mencoba membuat pernyataan filosofis, secara harfiah saya mengatakan semua impor terjadi di sistem file lokal Anda; tidak pernah ada perbedaan apakah mereka berasal dari repo jarak jauh atau tidak. Jangan mencoba menggunakan jalur relatif (terkadang berfungsi, tetapi tidak disarankan), dan baca dokumen "Cara Menulis Kode Go", khususnya bagian "Organisasi Kode" .
JimB

Jawaban:

63

Nah, saya menemukan masalahnya. Pada dasarnya jalan mulai untuk impor adalah$HOME/go/src

Jadi saya hanya perlu menambahkan myappdi depan nama paket, yaitu impornya harus:

import (
    "log"
    "net/http"
    "myapp/common"
    "myapp/routers"
)
Karlom
sumber
3
menggunakan nama proyek seperti itu myappadalah ide yang buruk, misalnya jika Anda mengubah nama proyek, semua impor akan gagal
TomSawyer
7
Apa alternatifnya? Go tidak menyarankan Anda menggunakan impor relatif.
Sam Holmes
11
Tentu saja semua impor akan gagal jika Anda mengubah nama proyek. Nama proyek jarang berubah.
Damien Roche
21
Nah, mulai go1.11 Anda dapat menggunakan sistem modul baru. go mod init <module_name>dan kemudian adil import "<module_name>/<pkg_name>".
berteriak
Bagaimana kita bisa mengimpor github.com/dgrijalva/jwt-go di file .go kita? Folder jwt-go saya ada di dalam src / github.com / dgrijalva
Manik Thakur
30

Jika Anda menggunakan Go 1.5 di atas, Anda dapat mencoba menggunakan fitur vending . Ini memungkinkan Anda untuk meletakkan paket lokal Anda di bawah folder vendor dan mengimpornya dengan jalur yang lebih pendek. Dalam kasus Anda, Anda dapat meletakkan folder umum dan router Anda di dalam folder vendor sehingga akan seperti itu

myapp/
--vendor/
----common/
----routers/
------middleware/
--main.go

dan impor seperti ini

import (
    "common"
    "routers"
    "routers/middleware"
)

Ini akan berhasil karena Go akan mencoba mencari paket Anda mulai dari direktori vendor proyek Anda (jika memiliki setidaknya satu file .go), bukan $ GOPATH / src.

FYI: Anda dapat melakukan lebih banyak dengan vendor, karena fitur ini memungkinkan Anda untuk meletakkan "semua kode dependensi Anda" untuk sebuah paket di dalam direktori proyek Anda sendiri sehingga akan selalu bisa mendapatkan versi dependensi yang sama untuk semua build. Ini seperti npm atau pip di python, tetapi Anda perlu menyalin dependensi Anda secara manual ke proyek Anda, atau jika Anda ingin membuatnya mudah, cobalah untuk mencari govendor oleh Daniel Theophanes

Untuk mempelajari lebih lanjut tentang fitur ini, coba cari di sini

Memahami dan Menggunakan Folder Vendor oleh Daniel Theophanes

Memahami Manajemen Ketergantungan Go oleh Lucas Fernandes da Costa

Saya harap Anda atau orang lain merasa terbantu

arimaulana
sumber
18

Jalur impor berhubungan dengan variabel Anda $GOPATHdan $GOROOTlingkungan. Misalnya, dengan yang berikut ini $GOPATH:

GOPATH=/home/me/go

Paket terletak di /home/me/go/src/lib/commondan /home/me/go/src/lib/routersdiimpor masing-masing sebagai:

import (
    "lib/common"
    "lib/routers"
)
wlredeye.dll
sumber
Ya, contoh pertama adalah kesalahanku.
wlredeye
Apa yang Anda maksud dengan jalur relatif tidak didukung oleh perkakas?
wlredeye
2
Anda tidak dapat go installmengemas yang menggunakan impor relatif.
JimB
Saya pikir kesalahpahaman di sini. Maksud saya relatif terhadap GOPATH. Bukan hanya relatif seperti "../../mypackage"
wlredeye
Itu mengacu pada bagian yang Anda perbaiki tentang pengimporan relatif terhadap direktori saat ini. Ya, semua impor pengguna relatif terhadap $GOPATH/src.
JimB
5

Paket lokal adalah masalah yang mengganggu saat bepergian.

Untuk beberapa proyek di perusahaan kami, kami memutuskan untuk tidak menggunakan sub paket sama sekali.

  • $ glide install
  • $ go get
  • $ go install

Semua pekerjaan.

Untuk beberapa proyek kami menggunakan sub paket, dan mengimpor paket lokal dengan jalur lengkap:

import "xxxx.gitlab.xx/xxgroup/xxproject/xxsubpackage

Tetapi jika kita melakukan fork pada proyek ini, maka subpaket masih mengacu pada yang asli.

tangxinfa.dll
sumber