गोपाथ के बिना स्थानीय पैकेज कैसे आयात करें


171

मैंने उपयोग किया है GOPATHलेकिन इस मौजूदा मुद्दे के लिए मैं इसका सामना कर रहा हूं इससे कोई मदद नहीं मिलती। मैं ऐसे पैकेज बनाना चाहता हूं जो किसी परियोजना के लिए विशिष्ट हों:

myproject/
├── binary1.go
├── binary2.go
├── package1.go
└── package2.go

मैंने कई तरीके आज़माए लेकिन मुझे package1.goकाम करने के तरीके में binary1.goया binary2.goऔर कैसे मिलता है ?

उदाहरण के लिए; मैं सक्षम होना चाहता हूं import "package1"और फिर चलाने में सक्षम हो सकता हूं और go build binary1.goत्रुटि के बिना सब कुछ ठीक काम करता है जिसे पैकेज पर नहीं पाया जा सकता है GOROOTया नहीं GOPATH। बड़े पैमाने पर परियोजनाओं के लिए मुझे इस तरह की कार्यक्षमता की आवश्यकता है; मैं कई अन्य पैकेजों को संदर्भित करना या उन्हें एक बड़ी फ़ाइल में रखना नहीं चाहता।


2
आपको प्रत्येक बाइनरी के लिए स्रोत फ़ाइलों को अपनी निर्देशिका में रखना चाहिए।
फ़ूज

.goएक ही निर्देशिका की सभी फाइलें एक ही पैकेज का हिस्सा हैं, और आपको importएक ही पैकेज (यानी एक ही निर्देशिका) में फाइलों की जरूरत नहीं है । आपने GOPATH के बाहर काम करने का उल्लेख किया है, जो नए Go मॉड्यूल सिस्टम की क्षमताओं में से एक है। यह उत्तर मॉड्यूल संरचना को कवर करता है, स्थानीय पैकेजों को आयात करता है, एक मॉड्यूल के भीतर पैकेजों की व्यवस्था करता है, चाहे एकल रिपॉजिटरी आदि में कई मॉड्यूल हों या न हों
ठेठ 182

3
और यह व्यवहार सभी के साथ ठीक है? जब तक आप पूरे git/repo/to/my/projectपथ को निर्दिष्ट नहीं करते हैं तब तक आप मूल रूप से अपने स्थानीय उप-पैकेजों को आयात नहीं कर सकते हैं । मैं सिर्फ यही कारण नहीं देखता कि कोई भी इस व्यवहार को क्यों चाहेगा। क्या होगा यदि आप अपनी परियोजना को किसी अन्य स्थान (यानी डॉकर छवि) में स्थानांतरित करते हैं, आपको फिर से सभी रास्तों को बदलने की आवश्यकता है? मैं जवाब की तलाश कर रहा हूं कि यह इतना जटिल क्यों है।
मिल्स

@milosmns मेरा उत्तर देखें stackoverflow.com/a/60915633/175071
टिमो हुओवेंन

जवाबों:


176

निर्भरता प्रबंधन सारांश जाओ:

  • vgo यदि आपका जाना संस्करण है: x >= go 1.11
  • depया vendorयदि आपका जाना संस्करण है:go 1.6 >= x < go 1.11
  • मैन्युअल रूप से यदि आपका गो संस्करण है: x < go 1.6

एडिट 3: गो 1.11 में एक फीचर है vgoजो रिप्लेस करेगा dep

उपयोग करने के लिए vgo, मॉड्यूल प्रलेखन देखें । नीचे TLDR:

export GO111MODULE=on
go mod init
go mod vendor # if you have vendor/ folder, will automatically integrate
go build

यह विधि go.modआपके प्रोजेक्ट निर्देशिका में नामक एक फ़ाइल बनाता है । तब आप अपने प्रोजेक्ट का निर्माण कर सकते हैं go build। यदि GO111MODULE=autoसेट किया गया है, तो आपका प्रोजेक्ट अंदर नहीं हो सकता $GOPATH


संपादित करें 2: प्रतिशोधी विधि अभी भी मान्य है और समस्या के बिना काम करती है। vendorमोटे तौर पर एक मैनुअल प्रक्रिया है, इस वजह से depऔर vgoबनाई गई।


संपादित करें 1: जबकि मेरा पुराना तरीका काम करता है, यह करने के लिए "सही" तरीका नहीं है। आपको विक्रेता क्षमताओं का उपयोग करना चाहिए vgo, या dep(अभी के लिए) जो कि गो 1.6 में डिफ़ॉल्ट रूप से सक्षम हैं; देखते हैं । आप मूल रूप से एक vendorनिर्देशिका में अपने "बाहरी" या "आश्रित" पैकेज जोड़ते हैं ; संकलन करने पर संकलनकर्ता पहले इन पैकेजों का उपयोग करेगा।


मिल गया। मैं साथ में सक्षम आयात स्थानीय पैकेज था GOPATHका एक सबफ़ोल्डर बनाने के द्वारा package1और फिर साथ आयात करने import "./package1"में binary1.goऔर binary2.goइस तरह स्क्रिप्ट:

binary1.go

...
import (
        "./package1"
      )
...

तो मेरी वर्तमान निर्देशिका संरचना इस तरह दिखती है:

myproject/
├── binary1.go
├── binary2.go
├── package1/
   └── package1.go
└── package2.go

मुझे यह भी ध्यान देना चाहिए कि रिश्तेदार पथ (कम से कम 1.5 में) भी काम करते हैं; उदाहरण के लिए:

import "../packageX"

4
यह ठीक काम करता है जब तक कि आपके पास दो सबफ़ोल्डर्स न हों एक के साथ दूसरे का जिक्र। उदाहरण के लिए, अगर package2 भी एक सबफ़ोल्डर था और इसे package1 की आवश्यकता थी, तो सिस्टम टूट जाता है।
कार्ल

7
import "../package1"
फेलिक्स राबे

12
सापेक्ष आयात पथ एक बुरा विचार है
डेव सी

1
अगर # गोलंग 'नाम स्थान' प्रदान करता है, तो मैं आपसे सहमत हो सकता हूं कि 'सापेक्ष आयात पथ' या 'उप-पैकेज' एक बुरे विचार हैं '।
मिशन.लिओ

1
समारोह का नाम Capitilized कीवर्ड से शुरू होना चाहिए
kokemomuke

71

"स्थानीय पैकेज" जैसी कोई चीज नहीं है। एक डिस्क पर संकुल का संगठन संकुल के किसी भी अभिभावक / बाल संबंधों के लिए रूढ़िवादी है। संकुल द्वारा गठित एकमात्र वास्तविक पदानुक्रम निर्भरता वृक्ष है, जो सामान्य स्थिति में निर्देशिका वृक्ष को प्रतिबिंबित नहीं करता है।

महज प्रयोग करें

import "myproject/packageN"

और बिना किसी अच्छे कारण के बिल्ड सिस्टम से न लड़ें। किसी भी गैर तुच्छ कार्यक्रम में प्रति आयात एक दर्जन पात्रों को सहेजना एक अच्छा कारण नहीं है, क्योंकि, उदाहरण के लिए, रिश्तेदार आयात पथ वाले प्रोजेक्ट गो-गेटटेबल नहीं हैं।

आयात रास्तों की अवधारणा में कुछ महत्वपूर्ण गुण हैं:

  • आयात पथ विश्व स्तर पर अद्वितीय हो सकते हैं।
  • GOPATH के संयोजन में, आयात पथ को एक निर्देशिका पथ के लिए स्पष्ट रूप से अनुवादित किया जा सकता है।
  • GOPATH के तहत किसी भी निर्देशिका पथ को आयात पथ में स्पष्ट रूप से अनुवादित किया जा सकता है।

उपरोक्त सभी रिश्तेदार आयात पथ का उपयोग करके बर्बाद हो गए हैं। ऐसा मत करो।

पुनश्च: गो संकलक परीक्षणों में विरासत कोड में कुछ स्थान हैं जो सापेक्ष आयात का उपयोग करते हैं। एटीएम, यही एकमात्र कारण है कि सापेक्ष आयात का समर्थन किया जाता है।


2
मैं पैकेज और GOPATH की बेहतर समझ के लिए इस परिचय वीडियो पर एक नज़र डालने की सलाह देता हूंyoutube.com/watch?v=XCsL89YtqCs
जोशुआ पिंटर

7
मुझे लगता है कि यह बुरी सलाह है। यदि आप संस्करण के लिए gopkg.in का उपयोग कर रहे हैं, उदाहरण के लिए, आप अपने "मिनी" pakages के लिए पूर्ण आयात पथ के साथ भाग्य से बाहर हैं, जैसा कि ऊपर वर्णित है। या तो आप स्रोत रेपो को तोड़ते हैं या संस्करण एक बेकार हो जाता है।
ग्रेग

import "myproject/packageN"myprojectफ़ोल्डर का नाम क्या है जो मेरी परियोजना रखता है?
सिक्योरव्यू

यह पूरी तरह से गलत है, अब मैं इसे निजी रिपॉजिटरी के साथ कैसे उपयोग करूं?
Agilob

44

शायद आप अपने पैकेज को संशोधित करने का प्रयास कर रहे हैं। मुझे लगता है कि यह सोचते कर रहा हूँ package1और package2कर रहे हैं, एक तरह से, एक ही पैकेज का हिस्सा है, लेकिन पठनीयता आप कर रहे हैं बंटवारे से अधिक फ़ाइलों में उन लोगों के लिए।

यदि पिछला मामला आपका था, तो आप एक ही पैकेज के नाम का उपयोग उन मल्टीपल्स फ़ाइलों में कर सकते हैं और यह वैसा ही होगा जैसे कि कोई फ़ाइल थी।

यह एक उदाहरण है:

add.go

package math

func add(n1, n2 int) int {
   return n1 + n2
}

subtract.go

package math

func subtract(n1, n2 int) int {
    return n1 - n2
}

donothing.go

package math

func donothing(n1, n2 int) int {
    s := add(n1, n2)
    s = subtract(n1, n2)
    return s
}

मैं एक गो विशेषज्ञ नहीं हूं और स्टैकऑवफ्लो में यह मेरी पहली पोस्ट है, इसलिए यदि आपके पास कुछ सलाह है तो यह अच्छी तरह से प्राप्त होगी।


23

मेरे पास एक ऐसी ही समस्या है और इसका समाधान मैं वर्तमान में गो 1.11 मॉड्यूल का उपयोग कर रहा हूं। मेरे पास निम्नलिखित संरचना है

- projects
  - go.mod
  - go.sum
  - project1
    - main.go
  - project2
    - main.go
  - package1
    - lib.go
  - package2
    - lib.go

और मैं उपयोग कर project1 और project2 से package1 और package2 आयात करने में सक्षम हूं

import (
    "projects/package1"
    "projects/package2"
)

दौड़ने के बाद go mod init projects। मैं go buildProject1 और Project2 निर्देशिकाओं से उपयोग कर सकता हूं या मैं go build -o project1/exe project1/*.goप्रोजेक्ट निर्देशिका से कर सकता हूं ।

इस पद्धति का नकारात्मक पक्ष यह है कि आपकी सभी परियोजनाएं एक ही निर्भरता सूची को go.mod में साझा करती हैं। मैं अभी भी इस समस्या का हल ढूंढ रहा हूं, लेकिन ऐसा लग रहा है कि यह मौलिक हो सकता है।


9

Go.mod की शुरुआत के बाद से , मुझे लगता है कि स्थानीय और बाहरी पैकेज प्रबंधन दोनों आसान हो जाते हैं। Go.mod का उपयोग करना , बाहर भी जाने के लिए संभव है।

स्थानीय पैकेज आयात करें:

Go.mod फ़ाइल जनरेट करने के लिए एक फ़ोल्डर डिमॉप्रोजेक्ट बनाएँ और निम्न कमांड चलाएँ

go mod init demoproject

मेरे पास एक परियोजना संरचना है जैसे नीचे डेमोप्रोजेक्ट डायरेक्टरी।

├── go.mod
└── src
    ├── main.go
    └── model
        └── model.go

डेमो उद्देश्य के लिए, model.go फ़ाइल में निम्न कोड डालें ।

package model

type Employee struct {
    Id          int32
    FirstName   string
    LastName    string
    BadgeNumber int32
}

में main.go , मैं "demoproject / src / मॉडल" को संदर्भित द्वारा कर्मचारी मॉडल आयातित

package main

import (
    "demoproject/src/model"
    "fmt"
)

func main() {
    fmt.Printf("Main Function")

    var employee = model.Employee{
        Id:          1,
        FirstName:   "First name",
        LastName:    "Last Name",
        BadgeNumber: 1000,
    }
    fmt.Printf(employee.FirstName)
}

बाहरी निर्भरता आयात करें:

बस go getप्रोजेक्ट डायरेक्टरी के अंदर कमांड रन करें ।

उदाहरण के लिए:

go get -u google.golang.org/grpc

इसमें go.mod फ़ाइल में मॉड्यूल निर्भरता शामिल होनी चाहिए

module demoproject

go 1.13

require (
    golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
    golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
    golang.org/x/text v0.3.2 // indirect
    google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150 // indirect
    google.golang.org/grpc v1.26.0 // indirect
)

https://blog.golang.org/using-go-modules


can't load package: package .: no Go files in...(go.mod के फ़ोल्डर में निर्माण करें)
Sebi2020

इस तरह का प्रतिबंध लेकिन मुझे जवाब खोजने में शर्मनाक समय लगा और आपकी पोस्ट सबसे सुपाठ्य और उपयोगी थी। धन्यवाद!
हेरोल्ड कैवेंडिश

8

अपनी परियोजना में "स्थानीय" पैकेज जोड़ने के लिए, एक फ़ोल्डर जोड़ें (उदाहरण के लिए "package_name")। और अपनी कार्यान्वयन फ़ाइलों को उस फ़ोल्डर में रखें।

src/github.com/GithubUser/myproject/
 ├── main.go
 └───package_name
       └── whatever_name1.go
       └── whatever_name2.go

अपने package mainइस में:

import "github.com/GithubUser/myproject/package_name"

कहाँ पे package_nameफ़ोल्डर का नाम है और इसे जो कुछ भी है, जो कुछ भी नाम और फाइलों में उपयोग किए गए पैकेज के नाम से मेल खाना चाहिए। दूसरे शब्दों में, एक उप-निर्देशिका वाली सभी फाइलें एक ही पैकेज की होनी चाहिए।

जब तक आप आयात में मूल फ़ोल्डर में संपूर्ण पथ निर्दिष्ट करते हैं तब तक आप अधिक उपनिर्देशिकाएँ घोंसला कर सकते हैं।


2
यह एक अच्छा सुझाव है, सिवाय इसके कि किसी भी कर्नेल घबराहट के दौरान बाइनरी से डंप किया गया स्टैक ट्रेस उदाहरण के लिए github.com पथ दिखाता है, न कि हमेशा सबसे वांछनीय व्यवहार। इसे दबाने के लिए झंडे हैं, लेकिन यह केवल सरल पैकेज संगठन को प्राप्त करने के लिए आवश्यक नहीं होना चाहिए, और मैंने पाया है कि यह अवसर पर विफल होता है।
केनी पॉवर्स

package myproject/package_name is not in GOROOT (/usr/lib/go-1.14/src/myproject/package_name)
सेबी 2020

3

आप उपयोग कर सकते हैं replace

go modo init example.com/my/foo

foo / go.mod

module example.com/my/foo

go 1.14

replace example.com/my/bar => /path/to/bar

require example.com/my/bar v1.0.0

foo / main.go

package main
import "example.com/bar"

func main() {
    bar.MyFunc()
}

बार / go.mod

module github.com/my/bar

go 1.14

बार / fn.go

package github.com/my/bar

import "fmt"

func MyFunc() {
    fmt.Printf("hello")
}

एक स्थानीय पैकेज आयात करना केवल एक बाहरी पचाने को आयात करने जैसा है

Go.mod फ़ाइल के अंदर आप उस बाहरी पैकेज नाम को स्थानीय फ़ोल्डर से बदल देते हैं।

फ़ोल्डर का पथ पूर्ण या सापेक्ष हो सकता है "/ पथ / से / बार" या "../bar"

https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive https://thewebivore.com/use-replace-in-go-mod-to-point करने वाली अपनी-स्थानीय मॉड्यूल /

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.