# workspaces

<!--{
  "Title": "Tutorial: Getting started with multi-module workspaces",
  "Breadcrumb": true
}-->

This tutorial introduces the basics of multi-module workspaces in Go.
With multi-module workspaces, you can tell the Go command that you're
writing code in multiple modules at the same time and easily build and
run code in those modules.

In this tutorial, you'll create two modules in a shared multi-module
workspace, make changes across those modules, and see the results
of those changes in a build.

<!-- TODO TOC -->

**Note:** For other tutorials, see [Tutorials](/doc/tutorial/index.html).

## Prerequisites

*   **Go.** We recommend using the latest version of Go to follow this tutorial.
    For installation instructions, see [Installing Go](/doc/install).
*   **A tool to edit your code.** Any text editor you have will work fine.
*   **A command terminal.** Go works well using any terminal on Linux and Mac,
    and on PowerShell or cmd in Windows.

## Create a module for your code {#create_folder}

To begin, create a module for the code you’ll write.

1. Open a command prompt and change to your home directory.

   On Linux or Mac:

    ```
    $ cd
    ```

   On Windows:

    ```
    C:\> cd %HOMEPATH%
    ```

   The rest of the tutorial will show a $ as the prompt. The commands you use
   will work on Windows too.

2. From the command prompt, create a directory for your code called workspace.

    ```
    $ mkdir workspace
    $ cd workspace
    ```

3. Initialize the module

   Our example will create a new module `hello` that will depend on the golang.org/x/example module.

   Create the hello module:

   ```
   $ mkdir hello
   $ cd hello
   $ go mod init example.com/hello
   go: creating new go.mod: module example.com/hello
   ```

   Add a dependency on the golang.org/x/example/hello/reverse package by using `go get`.

   ```
   $ go get golang.org/x/example/hello/reverse
   ```

   Create hello.go in the hello directory with the following contents:

   ```
   package main

   import (
       "fmt"

       "golang.org/x/example/hello/reverse"
   )

   func main() {
       fmt.Println(reverse.String("Hello"))
   }
   ```

   Now, run the hello program:

   ```
   $ go run .
   olleH
   ```

## Create the workspace

In this step, we'll create a `go.work` file to specify a workspace with the module.

#### Initialize the workspace

In the `workspace` directory, run:

   ```
   $ go work init ./hello
   ```

The `go work init` command tells `go` to create a `go.work` file
for a workspace containing the modules in the `./hello`
directory.

The `go` command produces a `go.work` file that looks like this:

   ```
   go 1.18

   use ./hello
   ```

The `go.work` file has similar syntax to `go.mod`.

The `go` directive tells Go which version of Go the file should be
interpreted with. It's similar to the `go` directive in the `go.mod`
file.

The `use` directive tells Go that the module in the `hello`
directory should be main modules when doing a build.

So in any subdirectory of `workspace` the module will be active.

#### Run the program in the workspace directory

In the `workspace` directory, run:

   ```
   $ go run ./hello
   olleH
   ```

The Go command includes all the modules in the workspace as main modules. This allows us
to refer to a package in the module, even outside the module. Running the `go run` command
outside the module or the workspace would result in an error because the `go` command
wouldn't know which modules to use.

Next, we'll add a local copy of the `golang.org/x/example/hello` module to the workspace.
That module is stored in a subdirectory of the `go.googlesource.com/example` Git repository.
We'll then add a new function to the `reverse` package that we can use instead of `String`.

## Download and modify the `golang.org/x/example/hello` module

   In this step, we'll download a copy of the Git repo containing the `golang.org/x/example/hello` module,
   add it to the workspace, and then add a new function to it that we will use from the hello program.

1. Clone the repository

   From the workspace directory, run the `git` command to clone the repository:

   ```
   $ git clone https://go.googlesource.com/example
   Cloning into 'example'...
   remote: Total 165 (delta 27), reused 165 (delta 27)
   Receiving objects: 100% (165/165), 434.18 KiB | 1022.00 KiB/s, done.
   Resolving deltas: 100% (27/27), done.
   ```

2. Add the module to the workspace

   The Git repo was just checked out into `./example`.
   The source code for the `golang.org/x/example/hello` module is in `./example/hello`.
   Add it to the workspace:

   ```
   $ go work use ./example/hello
   ```

   The `go work use` command adds a new module to the go.work file. It will now look like this:

   ```
   go 1.18

   use (
       ./hello
       ./example/hello
   )
   ```

   The workspace now includes both the `example.com/hello` module and the `golang.org/x/example/hello` module,
   which provides the `golang.org/x/example/hello/reverse` package.

   This will allow us to use the new code we will write in our copy of the `reverse` package
   instead of the version of the package in the module cache
   that we downloaded with the `go get` command.

3. Add the new function.

   We'll add a new function to reverse a number to the `golang.org/x/example/hello/reverse` package.

   Create a new file named `int.go` in the `workspace/example/hello/reverse` directory containing the following contents:

   ```
   package reverse

   import "strconv"

   // Int returns the decimal reversal of the integer i.
   func Int(i int) int {
       i, _ = strconv.Atoi(String(strconv.Itoa(i)))
       return i
   }
   ```

4. Modify the hello program to use the function.

   Modify the contents of `workspace/hello/hello.go` to contain the following contents:

   ```
   package main

   import (
       "fmt"

       "golang.org/x/example/hello/reverse"
   )

   func main() {
       fmt.Println(reverse.String("Hello"), reverse.Int(24601))
   }
   ```

#### Run the code in the workspace

   From the workspace directory, run

   ```
   $ go run ./hello
   olleH 10642
   ```

   The Go command finds the `example.com/hello` module specified in the
   command line in the `hello` directory specified by the `go.work`
   file, and similarly resolves the `golang.org/x/example/hello/reverse` import using
   the `go.work` file.

   `go.work` can be used instead of adding [`replace`](/ref/mod#go-mod-file-replace)
   directives to work across multiple modules.

   Since the two modules are in the same workspace it's easy
   to make a change in one module and use it in another.

#### Future step

   Now, to properly release these modules we'd need to make a release of the `golang.org/x/example/hello`
   module, for example at `v0.1.0`. This is usually done by tagging a commit on the module's version
   control repository. See the
   [module release workflow documentation](/doc/modules/release-workflow)
   for more details. Once the release is done, we can increase the requirement on the
   `golang.org/x/example/hello` module in `hello/go.mod`:

   ```
   cd hello
   go get golang.org/x/example/hello@v0.1.0
   ```

   That way, the `go` command can properly resolve the modules outside the workspace.

## Learn more about workspaces

   The `go` command has a couple of subcommands for working with workspaces in addition to `go work init` which
   we saw earlier in the tutorial:

   - `go work use [-r] [dir]` adds a `use` directive to the `go.work` file for `dir`,
   if it exists, and removes the `use` directory if the argument directory doesn't exist. The `-r`
   flag examines subdirectories of `dir` recursively.
   - `go work edit` edits the `go.work` file similarly to `go mod edit`
   - `go work sync` syncs dependencies from the workspace's build list into each of the workspace modules.

   See [Workspaces](/ref/mod#workspaces) in the Go Modules Reference for more detail on
   workspaces and `go.work` files.