How to use local go modules with golang with examples
go·@howo·
0.000 HBDHow to use local go modules with golang with examples
<img src="https://res.cloudinary.com/cpress/image/upload/w_1280,e_sharpen:60/rp1osul9qflgxvec52fo.jpg" alt="Image result for golang modules""/>
<p>When coding I like to put everything inside of folders depending on what they do. I almost always got specific directories for utils, parser, etc. So here's a complete guide on how to use local go modules with golang </p>
<p> When I started using go modules I was migrating a project from dep which followed this architecture. I had an utils directory, and another directory which handled all parsing for my data input into structs. But then I ended up needing functions from the utils directory. I was stuck and couldn't find how to make directories importable everywhere in the project (like dep used to). Because relative imports are a nightmare with go modules (removing the gopath has a toll after all). </p>
<p>So after quite a bit of fuming and searching all of the web for a solution that is elegant and not something like some crazy relative imports, I found this solution and since I struggled so much to find the solution I figured that I would share it with you all.</p>
<h2>The example project</h2>
<p>Here's our example project directory structure : <br> ├── go.mod<br> ├── hello<br> │ ├── go.mod<br> │ └── hello.go<br> ├── main.go<br> ├── README.md<br> └── utils<br> ├── go.mod<br> └── multigreet.go</p>
<p>You can also see the example code on my github repository here : <a href="https://github.com/drov0/GolangLocalModulesExample">https://github.com/drov0/GolangLocalModulesExample</a></p>
<p>The code is relatively straightforward : I have two directories, <strong>hello</strong> and <strong>utils</strong> that I want to import from the <strong>main.go</strong> file. And when things get a little tricky is that I want to import the <strong>hello</strong> directory inside of the <strong>utils</strong> directory. </p>
<p>The code for the hello.go file that we want to import is this super complicated function : </p>
<pre class="wp-block-preformatted">package hello
func Hello(name string) string {
return "hello " + name
}</pre>
<p>The code for the addAndGreet.go file is a bit more complex : </p>
<pre class="wp-block-preformatted">package utils<br><br>import (<br> "example.org/hello"<br> "strconv"<br>)<br><br>func AddAndGreet(name string, a, b int) string {<br> return hello.Hello(name) + " " + strconv.Itoa(a + b)<br>}<br></pre>
<p>Notice how we are importing <code>"example.org/hello"</code>. </p>
<p>Finally here's the main.go file : </p>
<pre class="wp-block-preformatted">package main<br><br>import (<br> "example.org/hello"<br> "example.org/utils"<br> "fmt"<br>)<br><br>func main() {<br> fmt.Println(hello.Hello("martin"))<br> fmt.Println(utils.AddAndGreet("martin", 2, 3))<br>}<br></pre>
<p>Obviously the modules <code>example.org/hello</code> or <code>example.org/utils </code> do not exist so these imports make zero sense to our compiler so let's help him out a bit </p>
<h2>Importing local modules in main.go</h2>
<p>So first we simply have to convert all of our directories into go modules. For that we need to add a go.mod at the root of every directories. <br>Then inside of that go.mod give them whatever name that we want as module name. but bear in mind that it has to be an url. In my example I put this:</p>
<p><code>module example.org/hello</code> in the go.mod for the hello directory <br><code>module example.org/utils</code> in the go.mod for the utils directory </p>
<p>The import makes a bit more sense now huh ? but we are not done yet. </p>
<h2>The replace keyword</h2>
<p>This is where the magic happens, go.mod files have a few keywords that can be very useful, one of them is <strong>replace</strong> what replace does is that it takes a module path (eg : example.org/hello) and replaces it with a direct or relative path.</p>
<p>here's the syntax for the replace keyword : </p>
<pre class="wp-block-preformatted">replace url.com/of/the/module => /direct/path/to/files</pre>
<p>Note that replace also works with relative paths. </p>
<h2>The main go.mod </h2>
<pre class="wp-block-preformatted">module example.com/localmodexample<br><br>go 1.13<br><br>require (<br> example.org/hello v0.0.0<br> example.org/utils v0.0.0<br><br>)<br><br>replace (<br> example.org/hello => ./hello<br> example.org/utils => ./utils<br>)<br></pre>
<p>Usuall go module dependencies work with versions, so to use local go modules with golang you have to set v0.0.0</p>
<p>Finally after the require, I just tell the compiler that those urls are local and can be found in the same directory under <code>./hello</code> and <code>./utils</code>. The great thing about this main go.mod file is that now even the <strong>utils</strong> module will know where to find the <strong>hello</strong> module because the url have been replaced. </p>
<h2>Conclusion</h2>
<p>And that's all you need to know to use local go modules with golang. Hopefully this will save you all the hours I put into it. Keep in mind that you can find the complete code on my github : <a href="https://github.com/drov0/GolangLocalModulesExample">https://github.com/drov0/GolangLocalModulesExample</a><br><br>I know it's been a while since my last <a href="https://brokencode.io/building-a-time-tracker-using-arduino-and-blockchain-tangletime-part-2/">post</a> but I got quite busy. But now I should be able to make posts more often on this blog. </p>
<br /> <center><hr/><em>Posted from my blog with <a href='https://wordpress.org/plugins/steempress/'>SteemPress</a> : https://brokencode.io/how-to-use-local-go-modules-with-golang-with-examples/ </em><hr/></center>👍 scholaris, reward.tier5, davidamsterdam, mustard-seed, petrvl, jaydih, kimseun, kanadaramagi123, loveecho, angelslake, wordit, sj-jeong, wondumyungga, aquawink, ringit, coreabeforekorea, talkative-bk, whatdidshewear, sjgod4018, perrymine, jaykayw, belahejna, kryptoformator, friendlystranger, smallpusher, stevoperon, ribary, razer7, arhitekto, tarazkp, trezorblue, littlehope, viktorv, superjohn, yangganga, babytarazkp, miti, freepress, mosquito76, webdeals, singing.beauty, bigbot, raiseup, dalz, mehta, stupid, unpopular, ritxi, boosta, msg768, swiftbot, alexsandr, cryptopie, kingscrown, kevinwong, magicmonk, lemouth, markkujantunen, itchyfeetdonica, portugalcoin, feedmytwi, roamingsparrow, kimzwarch, omstavan, upboater, steemfriends, steemonboarder, chromebook, trafalgar, likwid, raindrop, traf, the-reef, promobot, kgsupport, sock, josephcraig289, kingsmind, pboc, kunschj, salma.ali, tuoficinavirtual, spacecadet1, potplucker, quicksnake, onepracticalcat, rbriyad2, superledger, jiangzemin, shahabudin, praditya, cryptorunway, juneiker, cryptocurator, spurisna, sbi7, tubcat, debtfreein2, skylinebuds, techken, shaka, smon-joa, vannour, steemperor, steempire, mothership, sirjaxxy, ilyasismail, obvious, youraverageguy, cj3000, kiwi-crypto, justasperm, laissez-faire, wajahatsardar, sonbulut, igl00, bigdaddy, magicinvesting, bleuxwolf, king-oghie, boatymcboatface, theshell, amrumk, evanpetzer, howo, hone.heke, mindstabber, dan-bn, jdevora, rayshiuimages, botante, plainoldme, taverngames, silversteem, darthnava, doodleman, tetrahedron96, rokhani, corsica, the.circle, meq, jchappe, ammar0344, chris.geese, rokyupjung, jamzed, newtech-adopter, queenmountain, slh84, cryptomeeks, cryptofuwealth, ranggayusuf, ambercookie, goodcontentbot, insiders, chatitsimo, amariwest, milarose, saqibnazir, drsensor, rubenalexander, acidyo, rahul.stan, steeminator3000, ikibaru-san, mister-meeseeks, bilpcoinpower, agromeror, seajai, kork75, wwwfernand, tdogvoid, rosepac, kafupraise, warrensteem, jesusj1, goumao, walterjay, wf9877, incomepal, adrianbucks, erikkun28, aburashed, balticbadger, perepilichnyy, juliocaraballo, amin-ove, dream.trip, meedo, paullifefit, kingnosa, wishmaiden, hizen, conormingregor, santoninoatocha, lolol13, superhardness, marlui, oo7harv, breelikeatree, cunigarro, bewarecenterbase, steamsteem, selfvotejustice, pedrohmc23, bue, greenman, teenovision, accountsale, cinefilm, geoffrey, shannonsalter334, adityajainxds, mastersa, bala41288, rocksg, paresh10p, rahar, tongchat27, waqasrizvi, judasp, marian0, fredrikaa, sarakey, peeterxnjoroge, sujaytechnicals, feelx, arrixion, marki99, rieku, pequef, drorion, disguarpe, dniceguy, jingdol, jungch98, macchiata, ewi5000, tanversaadakash, paul3080, sammycakes, joanawatts, robertchr, traciyork, theycallmedan, briggsy, argentsilver, bpcvoter2, bpcvoter3, and2300, sniper555, georgecri80, jamesbattler, yangyanje, stef1, ezedende, cpufronz, leomoji, sharkthelion, ronpurteetv, art-venture,