Skip to content

Commit

Permalink
_content/doc/tutorial: add a tutorial for workspaces
Browse files Browse the repository at this point in the history
Change-Id: I0686121523da9b22666cfbad54821527ac5b8feb
Reviewed-on: https://go-review.googlesource.com/c/website/+/383854
Trust: Michael Matloob <michaelmatloob@gmail.com>
Trust: Bryan Mills <bcmills@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
  • Loading branch information
passionSeven committed Mar 1, 2022
1 parent 14e838d commit 7595837
Show file tree
Hide file tree
Showing 3 changed files with 291 additions and 0 deletions.
6 changes: 6 additions & 0 deletions _content/doc/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ <h3 id="create-module-tutorial"><a href="/doc/tutorial/create-module.html">Tutor
A tutorial of short topics introducing functions, error handling, arrays, maps, unit testing, and compiling.
</p>

<h3 id="workspaces-tutorial"><a href="/doc/tutorial/workspaces.html">Tutorial: Getting started with multi-module workspaces</a></h3>
<p>
Introduces the basics of creating and using multi-module workspaces in Go.
Multi-module workspaces are useful for making changes across multiple modules.
</p>

<h3 id="web-service-gin-tutorial"><a href="/doc/tutorial/web-service-gin.html">Tutorial: Developing a RESTful
API with Go and Gin</a></h3>
<p>
Expand Down
9 changes: 9 additions & 0 deletions _content/doc/tutorial/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@
features from the Go perspective.
</td>
</tr>
<tr class="DocTable-row">
<td class="DocTable-cell">
<a href="/doc/tutorial/workspaces.html">Getting started with multi-module workspaces</a>
</td>
<td class="DocTable-cell">
Introduces the basics of creating and using multi-module workspaces in Go.
Multi-module workspaces are useful for making changes across multiple modules.
</td>
</tr>
<tr class="DocTable-row">
<td class="DocTable-cell">
<a href="/doc/tutorial/database-access">Accessing a relational
Expand Down
276 changes: 276 additions & 0 deletions _content/doc/tutorial/workspaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
<!--{
"Title": "Tutorial: Getting started with multi-module workspaces"
}-->

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

* **An installation of Go 1.18 or later.**
* **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.

This tutorial requires go1.18 or later. Make sure you've installed Go at Go 1.18 or later using the
links at [go.dev/dl](https://go.dev/dl).

## 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 module by using `go get`.
```
$ go get golang.org/x/example
```
Create hello.go in the hello directory with the following contents:
```
package main

import (
"fmt"

"golang.org/x/example/stringutil"
)

func main() {
fmt.Println(stringutil.Reverse("Hello"))
}
```
Now, run the hello program:
```
$ go run example.com/hello
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 example.com/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` module to the workspace. We'll then
add a new function to the `stringutil` package that we can use instead of `Reverse`.
## Download and modify the `golang.org/x/example` module
In this step, we'll download a copy of the Git repo containing the `golang.org/x/example` 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
```
$ go work use ./example
```
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
)
```
The module now includes both the `example.com/hello` module and the `golang.org/x/example module.
This will allow us to use the new code we will write in our copy of the `stringutil` module
instead of the version of the module in the module cache that we downloaded with the `go get` command.
3. Add the new function.
We'll add a new function to uppercase a string to the `golang.org/x/example/stringutil` package.
Add a new folder to the `workspace/example/stringutil` directory containing the following contents:
```
package stringutil

import "unicode"

// ToUpper uppercases all the runes in its argument string.
func ToUpper(s string) string {
r := []rune(s)
for i := range r {
r[i] = unicode.ToUpper(r[i])
}
return string(r)
}
```
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/stringutil"
)

func main() {
fmt.Println(stringutil.ToUpper("Hello"))
}
```
#### Run the code in the workspace
From the workspace directory, run
```
$ go run example/hello
HELLO
```
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` import using
the `go.work` file.
`go.work` can be used instead of adding [`replace`](https://go.dev/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`
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](https://go.dev/doc/modules/release-workflow)
for more details. Once the release is done, we can increase the requirement on the
`golang.org/x/example` module in `hello/go.mod`:
```
cd hello
go get example.com/dep@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](https://go.dev/ref/mod#workspaces) in the Go Modules Reference for more detail on
workspaces and `go.work` files.

0 comments on commit 7595837

Please sign in to comment.