marvin
By Marvin Desmond
Posted 29th March 2023

Go Multimodule

Let's use go.work to configure for multimodule workspace in Go project created here
At the moment, the directory structure for the root file fourier, is as below
            $ ls *
go.mod  main.go

hello:
go.mod          hello.go
$
          
The file contents are as below, in the file hello/hello.go in the folder hello
package hello

import (
    "fmt"
    "runtime"	
)

func SayArch() string {
    arch := fmt.Sprintf("Architecture: %s", runtime.GOOS)
    return arch
}
In the root file, main.go in the root folder, fourier:
package main

import (
    "fmt"
    "example.com/fourier/hello"
)

func main () {
    fmt.Println("Hello world")
    arch := hello.SayArch()
    fmt.Println(arch)
}
And the go.mod file contents in the root folder, fourier:
            $ cat go.mod 
module example.com/fourier

go 1.18
$
          
The go.mod file contents in the hello package
            $ cat hello/go.mod 
module example.com/fourier/hello

go 1.18
$
          
Initialize the workspace
Let's create the go.work file to specify a workspace with the module. go work init command tells go to create a go.work file for a workspace containing the modules in the . and the ./hello directories.

Note that trying to run it with go.work not initialized leads to the local module hello not being found
            $ go run .
main.go:5:2: no required module provides package example.com/fourier/hello; to add it:
        go get example.com/fourier/hello
$ go work init . ./hello 
$ ls
go.mod  go.work hello   main.go
$ cat go.work 
go 1.18

use (
        .
        ./hello
)
$ go run .
Hello world
Architecture: darwin
$
          
Package main from its main folder
Let's take into account the fact that main.go now exists not in root folder, fourier, but in a folder within root, main
            $ pwd
/Users/siliconSavanna/Projects/Golang/fourier 
$ mkdir main
$ mv main.go ./main
$ cd main 
$ go mod init example.com/fourier/main
go: creating new go.mod: module example.com/fourier/main
go: to add module requirements and sums:
        go mod tidy
$
          
So there are two ways to go about this:
  1. Add the main and hello directories while initializing the go.work file
                $ cd ../
    $ pwd
    /Users/siliconSavanna/Projects/Golang/fourier 
    $ rm go.work 
    $ go work init ./main ./hello 
    $ cat go.work                
    go 1.18
    
    use (
            ./hello
            ./main
    )
    $ go run main/main.go        
    Hello world
    Architecture: darwin
    $
              
  2. Use go mod edit -replace
                $ cd ../
    $ pwd
    /Users/siliconSavanna/Projects/Golang/fourier 
    $ rm go.work 
    $ cd main 
    $ go mod edit -replace example.com/fourier/hello=../hello
    $ go mod tidy
    go: found example.com/fourier/hello in example.com/fourier/hello v0.0.0-00010101000000-000000000000
    $ go run .
    Hello world
    Architecture: darwin
    $
              
  3. For the latter, the state of the go.mod file in main folder becomes
                $ cat go.mod 
    module example.com/fourier/main
    
    go 1.18
    
    replace example.com/fourier/hello => ../hello
    
    require example.com/fourier/hello v0.0.0-00010101000000-000000000000
    $
              
To Go and Beyond!