Skip to content

Commit d10dfbe

Browse files
matloobmichaelmatloob
authored andcommitted
_content/doc/tutorial: add a tutorial for workspaces
Change-Id: I0686121523da9b22666cfbad54821527ac5b8feb Reviewed-on: https://go-review.googlesource.com/c/website/+/383854 Trust: Michael Matloob <[email protected]> Trust: Bryan Mills <[email protected]> Reviewed-by: Bryan Mills <[email protected]>
1 parent c18706c commit d10dfbe

File tree

3 files changed

+291
-0
lines changed

3 files changed

+291
-0
lines changed

_content/doc/index.html

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ <h3 id="create-module-tutorial"><a href="/doc/tutorial/create-module.html">Tutor
3737
A tutorial of short topics introducing functions, error handling, arrays, maps, unit testing, and compiling.
3838
</p>
3939

40+
<h3 id="workspaces-tutorial"><a href="/doc/tutorial/workspaces.html">Tutorial: Getting started with multi-module workspaces</a></h3>
41+
<p>
42+
Introduces the basics of creating and using multi-module workspaces in Go.
43+
Multi-module workspaces are useful for making changes across multiple modules.
44+
</p>
45+
4046
<h3 id="web-service-gin-tutorial"><a href="/doc/tutorial/web-service-gin.html">Tutorial: Developing a RESTful
4147
API with Go and Gin</a></h3>
4248
<p>

_content/doc/tutorial/index.html

+9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
features from the Go perspective.
3333
</td>
3434
</tr>
35+
<tr class="DocTable-row">
36+
<td class="DocTable-cell">
37+
<a href="/doc/tutorial/workspaces.html">Getting started with multi-module workspaces</a>
38+
</td>
39+
<td class="DocTable-cell">
40+
Introduces the basics of creating and using multi-module workspaces in Go.
41+
Multi-module workspaces are useful for making changes across multiple modules.
42+
</td>
43+
</tr>
3544
<tr class="DocTable-row">
3645
<td class="DocTable-cell">
3746
<a href="/doc/tutorial/database-access">Accessing a relational

_content/doc/tutorial/workspaces.md

+276
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
<!--{
2+
"Title": "Tutorial: Getting started with multi-module workspaces"
3+
}-->
4+
5+
This tutorial introduces the basics of multi-module workspaces in Go.
6+
With multi-module workspaces, you can tell the Go command that you're
7+
writing code in multiple modules at the same time and easily build and
8+
run code in those modules.
9+
10+
In this tutorial, you'll create two modules in a shared multi-module
11+
workspace, make changes across those modules, and see the results
12+
of those changes in a build.
13+
14+
<!-- TODO TOC -->
15+
16+
**Note:** For other tutorials, see [Tutorials](/doc/tutorial/index.html).
17+
18+
## Prerequisites
19+
20+
* **An installation of Go 1.18 or later.**
21+
* **A tool to edit your code.** Any text editor you have will work fine.
22+
* **A command terminal.** Go works well using any terminal on Linux and Mac,
23+
and on PowerShell or cmd in Windows.
24+
25+
This tutorial requires go1.18 or later. Make sure you've installed Go at Go 1.18 or later using the
26+
links at [go.dev/dl](https://go.dev/dl).
27+
28+
## Create a module for your code {#create_folder}
29+
30+
To begin, create a module for the code you’ll write.
31+
32+
1. Open a command prompt and change to your home directory.
33+
34+
On Linux or Mac:
35+
36+
```
37+
$ cd
38+
```
39+
40+
On Windows:
41+
42+
```
43+
C:\> cd %HOMEPATH%
44+
```
45+
46+
The rest of the tutorial will show a $ as the prompt. The commands you use
47+
will work on Windows too.
48+
49+
2. From the command prompt, create a directory for your code called workspace.
50+
51+
```
52+
$ mkdir workspace
53+
$ cd workspace
54+
```
55+
56+
3. Initialize the module
57+
58+
Our example will create a new module `hello` that will depend on the golang.org/x/example module.
59+
60+
Create the hello module:
61+
62+
```
63+
$ mkdir hello
64+
$ cd hello
65+
$ go mod init example.com/hello
66+
go: creating new go.mod: module example.com/hello
67+
```
68+
69+
Add a dependency on the golang.org/x/example module by using `go get`.
70+
71+
```
72+
$ go get golang.org/x/example
73+
```
74+
75+
Create hello.go in the hello directory with the following contents:
76+
77+
```
78+
package main
79+
80+
import (
81+
"fmt"
82+
83+
"golang.org/x/example/stringutil"
84+
)
85+
86+
func main() {
87+
fmt.Println(stringutil.Reverse("Hello"))
88+
}
89+
```
90+
91+
Now, run the hello program:
92+
93+
```
94+
$ go run example.com/hello
95+
olleH
96+
```
97+
98+
## Create the workspace
99+
100+
In this step, we'll create a `go.work` file to specify a workspace with the module.
101+
102+
#### Initialize the workspace
103+
104+
In the `workspace` directory, run:
105+
106+
```
107+
$ go work init ./hello
108+
```
109+
110+
The `go work init` command tells `go` to create a `go.work` file
111+
for a workspace containing the modules in the `./hello`
112+
directory.
113+
114+
The `go` command produces a `go.work` file that looks like this:
115+
116+
```
117+
go 1.18
118+
119+
use ./hello
120+
```
121+
122+
The `go.work` file has similar syntax to `go.mod`.
123+
124+
The `go` directive tells Go which version of Go the file should be
125+
interpreted with. It's similar to the `go` directive in the `go.mod`
126+
file.
127+
128+
The `use` directive tells Go that the module in the `hello`
129+
directory should be main modules when doing a build.
130+
131+
So in any subdirectory of `workspace` the module will be active.
132+
133+
#### Run the program in the workspace directory
134+
135+
In the `workspace` directory, run:
136+
137+
```
138+
$ go run example.com/hello
139+
olleH
140+
```
141+
142+
The Go command includes all the modules in the workspace as main modules. This allows us
143+
to refer to a package in the module, even outside the module. Running the `go run` command
144+
outside the module or the workspace would result in an error because the `go` command
145+
wouldn't know which modules to use.
146+
147+
Next, we'll add a local copy of the `golang.org/x/example` module to the workspace. We'll then
148+
add a new function to the `stringutil` package that we can use instead of `Reverse`.
149+
150+
## Download and modify the `golang.org/x/example` module
151+
152+
In this step, we'll download a copy of the Git repo containing the `golang.org/x/example` module,
153+
add it to the workspace, and then add a new function to it that we will use from the hello program.
154+
155+
1. Clone the repository
156+
157+
From the workspace directory, run the `git` command to clone the repository:
158+
159+
```
160+
$ git clone https://go.googlesource.com/example
161+
Cloning into 'example'...
162+
remote: Total 165 (delta 27), reused 165 (delta 27)
163+
Receiving objects: 100% (165/165), 434.18 KiB | 1022.00 KiB/s, done.
164+
Resolving deltas: 100% (27/27), done.
165+
```
166+
167+
2. Add the module to the workspace
168+
169+
```
170+
$ go work use ./example
171+
```
172+
173+
The `go work use` command adds a new module to the go.work file. It will now look like this:
174+
175+
```
176+
go 1.18
177+
178+
use (
179+
./hello
180+
./example
181+
)
182+
```
183+
184+
The module now includes both the `example.com/hello` module and the `golang.org/x/example module.
185+
186+
This will allow us to use the new code we will write in our copy of the `stringutil` module
187+
instead of the version of the module in the module cache that we downloaded with the `go get` command.
188+
189+
3. Add the new function.
190+
191+
We'll add a new function to uppercase a string to the `golang.org/x/example/stringutil` package.
192+
193+
Add a new folder to the `workspace/example/stringutil` directory containing the following contents:
194+
195+
```
196+
package stringutil
197+
198+
import "unicode"
199+
200+
// ToUpper uppercases all the runes in its argument string.
201+
func ToUpper(s string) string {
202+
r := []rune(s)
203+
for i := range r {
204+
r[i] = unicode.ToUpper(r[i])
205+
}
206+
return string(r)
207+
}
208+
```
209+
210+
4. Modify the hello program to use the function.
211+
212+
Modify the contents of `workspace/hello/hello.go` to contain the following contents:
213+
214+
```
215+
package main
216+
217+
import (
218+
"fmt"
219+
220+
"golang.org/x/example/stringutil"
221+
)
222+
223+
func main() {
224+
fmt.Println(stringutil.ToUpper("Hello"))
225+
}
226+
```
227+
228+
#### Run the code in the workspace
229+
230+
From the workspace directory, run
231+
232+
```
233+
$ go run example/hello
234+
HELLO
235+
```
236+
237+
The Go command finds the `example.com/hello` module specified in the
238+
command line in the `hello` directory specified by the `go.work`
239+
file, and similarly resolves the `golang.org/x/example` import using
240+
the `go.work` file.
241+
242+
`go.work` can be used instead of adding [`replace`](https://go.dev/ref/mod#go-mod-file-replace)
243+
directives to work across multiple modules.
244+
245+
Since the two modules are in the same workspace it's easy
246+
to make a change in one module and use it in another.
247+
248+
#### Future step
249+
250+
Now, to properly release these modules we'd need to make a release of the `golang.org/x/example`
251+
module, for example at `v0.1.0`. This is usually done by tagging a commit on the module's version
252+
control repository. See the
253+
[module release workflow documentation](https://go.dev/doc/modules/release-workflow)
254+
for more details. Once the release is done, we can increase the requirement on the
255+
`golang.org/x/example` module in `hello/go.mod`:
256+
257+
```
258+
cd hello
259+
go get example.com/[email protected]
260+
```
261+
262+
That way, the `go` command can properly resolve the modules outside the workspace.
263+
264+
## Learn more about workspaces
265+
266+
The `go` command has a couple of subcommands for working with workspaces in addition to `go work init` which
267+
we saw earlier in the tutorial:
268+
269+
- `go work use [-r] [dir]` adds a `use` directive to the `go.work` file for `dir`,
270+
if it exists, and removes the `use` directory if the argument directory doesn't exist. The `-r`
271+
flag examines subdirectories of `dir` recursively.
272+
- `go work edit` edits the `go.work` file similarly to `go mod edit`
273+
- `go work sync` syncs dependencies from the workspace's build list into each of the workspace modules.
274+
275+
See [Workspaces](https://go.dev/ref/mod#workspaces) in the Go Modules Reference for more detail on
276+
workspaces and `go.work` files.

0 commit comments

Comments
 (0)