This guide is based on the official “Create a module” tutorial.
This guide introduces a few fundamental features of the Go language. If you’re just getting started with Go, be sure to take a look at the “Get Started with Go” guide, which introduces the go command, Go modules, and very simple Go code.
In this guide you’ll create two modules. The first is a library which is intended to be imported by other libraries or applications. The second is a caller application which will use the first.
This guide’s sequence includes six brief topics that each illustrate a different part of the language.
- Create a module – Write a small module with functions you can call from another module.
- Call your code from another module – Import and use your new module.
- Return and handle an error – Add simple error handling.
- Return a random greeting – Handle data in slices (Go’s dynamically-sized arrays).
- Return greetings for multiple people – Store key/value pairs in a map.
- Add a test – Use Go’s built-in unit testing features to test your code.
- Compile and install the application – Compile and install your code locally.
This guide requires you to push code to remote source code repositories. A unique user, {{{.GITEA_USERNAME}}}
, has
been automatically created for you, as have the repositories {{{.GREETINGS}}}
and
{{{.HELLO}}}
. For more details on how play-with-go.dev
guides work, please see the
Introduction to play-with-go.dev
guides guide.
Prerequisites
You should already have completed:
This guide is running using:
$ go version
go version go1.19.1 linux/amd64
Create a module that others can use
Start by creating a Go module. In a module, you collect one or more related packages for a discrete and useful set of functions. For example, you might create a module with packages that have functions for doing financial analysis so that others writing financial applications can use your work.
Go code is grouped into packages, and packages are grouped into modules. Your package’s module specifies the context Go needs to run the code, including the Go version the code is written for and the set of other modules it requires.
As you add or improve functionality in your module, you publish new versions of the module. Developers writing code that calls functions in your module can import the module’s updated packages and test with the new version before putting it into production use.
As with all play-with-go.dev guides, you start in your home directory:
$ pwd
/home/gopher
Create a greetings
directory for your Go module source code. This is where you’ll write your module code:
$ mkdir /home/gopher/greetings
$ cd /home/gopher/greetings
Start your module using the go mod init
command to create a go.mod
file. In this
guide you will publish your greetings module to {{{.GREETINGS}}}
:
$ go mod init {{{.GREETINGS}}}
go: creating new go.mod: module {{{.GREETINGS}}}
The go mod init
command creates a go.mod
file that identifies your code as a module that might be used from
other code. The file you just created includes only the name of your module and the Go version your code supports:
$ cat go.mod
module {{{.GREETINGS}}}
go 1.19
As you add dependencies – meaning packages from other modules – the go.mod
file will list the specific module
versions to use. This keeps builds reproducible and gives you direct control over which module versions to use.
Now let’s create greetings.go:
package greetings
import "fmt"
// Hello returns a greeting for the named person.
func Hello(name string) string {
// Return a greeting that embeds the name in a message.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
This is the first code for your module. It returns a greeting to any caller that asks for one. You’ll write code that calls this function in the next step.
In this code, you:
- Declare a
greetings
package to collect related functions. - Implement a Hello function to return the greeting. This function takes a name parameter whose type is
string
, and returns astring
. In Go, a function whose name starts with a capital letter can be called by a function not in the same package. This is known in Go as an exported name. - Declare a
message
variable to hold your greeting. In Go, the:=
operator is a shortcut for declaring and initializing a variable in one line (Go uses the value on the right to determine the variable’s type). Let’s rewrite this the long way:
package greetings
import "fmt"
// Hello returns a greeting for the named person.
func Hello(name string) string {
// Return a greeting that embeds the name in a message.
var message string
message = fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
- Use the
fmt
package’sSprintf
function to create a greeting message. The first argument is a format string, andSprintf
substitutes the name parameter’s value for the%v
format verb. Inserting the value of the name parameter completes the greeting text. - Return the formatted greeting text to the caller.
For people to be able to use your module you need to publish it. You publish a module by pushing a commit to a version
control system like GitHub. You will publish your module to
{{{.GREETINGS}}}
.
Initialise a local git
repository for your greetings
module:
$ git init -q
$ git remote add origin https://{{{.GREETINGS}}}.git
Add and commit the greetings.go
file you created earlier:
$ git add go.mod greetings.go
$ git commit -q -m 'Initial commit'
Publish this commit by pushing it to the remote repository:
$ git push -q origin main
remote: . Processing 1 references
remote: Processed 1 references in total
Call your code from another module
You’ll now write code that you can execute as an application, which makes calls to the Hello
function in the
greetings
module you published to {{{.GREETINGS}}}
.
Create the directory /home/gopher/hello
for your Go module source code. This is where you’ll write your caller.
$ mkdir /home/gopher/hello
$ cd /home/gopher/hello
Create a new module for this hello
package using the go mod init
command to create a go.mod
file as you did before, but this time using the unique path for the hello
module:
$ go mod init {{{.HELLO}}}
go: creating new go.mod: module {{{.HELLO}}}
Declare a dependency on {{{.GREETINGS}}}
using go get
:
$ go get {{{.GREETINGS}}}
go: downloading {{{.GREETINGS}}} v0.0.0-20060102150405-abcedf12345
go: added {{{.GREETINGS}}} v0.0.0-20060102150405-abcedf12345
Without any version specified, go get
will retrieve the latest version of the greetings
module. And
because you didn’t publish a specific version, go get
resolves a pseudo
version from the commit you pushed, specifically:
$ go list -m -f {{.Version}} {{{.GREETINGS}}}
v0.0.0-20060102150405-abcedf12345
Create hello.go
as follows:
package main
import (
"fmt"
"{{{.GREETINGS}}}"
)
func main() {
// Get a greeting message and print it.
message := greetings.Hello("Gladys")
fmt.Println(message)
}
In this code, you:
- Declare a
main
package. In Go, code executed as an application must go in amain
package. - Import two packages:
{{{.GREETINGS}}}
andfmt
. This gives your code access to functions in those packages. Importing{{{.GREETINGS}}}
(the package contained in the module you created earlier) gives you access to theHello
function. You also importfmt
, with functions for handling input and output text (such as printing text to the console). - Get a greeting by calling the
greetings
package’sHello
function.
Build and run your program:
$ go build
$ ./hello
Hi, Gladys. Welcome!
Congrats! You’ve written two functioning modules. Next you’ll add some error handling.
Return and handle an error
Handling errors is an essential feature of solid code. In this section, you’ll add a bit of code to return an error from
the greetings
module, then handle it in the caller.
Return to the greetings
module directory:
$ cd /home/gopher/greetings
There’s no sense sending a greeting back if you don’t know who to greet. Return an error to the caller if the name is
empty. Update greetings.go
as follows:
package greetings
import (
"errors"
"fmt"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return "", errors.New("empty name")
}
// If a name was received, return a value that embeds the name
// in a greeting message.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message, nil
}
In this code, you:
- Change the function so that it returns two values: a
string
and anerror
. Your caller will check the second value to see if an error occurred. (Any Go function can return multiple values.) - Import the Go standard library
errors
package so you can use itserrors.New
function. - Add an
if
statement to check for an invalid request (an empty string where the name should be) and return an error if the request is invalid. Theerrors.New
function returns an error with your message inside. - Add
nil
(meaning no error) as a second value in the successful return. That way, the caller can see that the function succeeded.
At this point your hello
module is referring to a pseudo version that represents the previous commit you
pushed. Therefore, you need to publish a new version of the greetings
module.
Add and commit the changes we made to greetings.go
:
$ git add greetings.go
$ git commit -q -m 'Added error handling'
Note the id of the commit we just created:
$ greetings_error_commit=$(git rev-parse HEAD)
Republish the greetings
module:
$ git push -q origin main
remote: . Processing 1 references
remote: Processed 1 references in total
Return to the hello
module directory to now use this new version:
$ cd /home/gopher/hello
By default, go get
uses proxy.golang.org
to resolve and download modules. In order to
improve the proxy’s caching and serving latencies, new versions may not show up right away. Therefore, to be sure you do
not resolve a stale latest version, use the latest commit of the greetings
module as an explicit version:
$ go get {{{.GREETINGS}}}@$greetings_error_commit
go: downloading {{{.GREETINGS}}} v0.0.0-20060102150405-abcedf12345
go: upgraded {{{.GREETINGS}}} v0.0.0-20060102150405-abcedf12345 => v0.0.0-20060102150405-abcedf12345
In your hello.go, handle the error now returned by the Hello
function, along with the non-error value:
package main
import (
"fmt"
"log"
"{{{.GREETINGS}}}"
)
func main() {
// Set properties of the predefined Logger, including
// the log entry prefix and a flag to disable printing
// the time, source file, and line number.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// Request a greeting message.
message, err := greetings.Hello("")
// If an error was returned, print it to the console and
// exit the program.
if err != nil {
log.Fatal(err)
}
// If no error was returned, print the returned message
// to the console.
fmt.Println(message)
}
In this code, you:
- Configure the
log
package to print the command name ("greetings: "
) at the start of its log messages, without a time stamp or source file information. - Assign both of the
Hello
return values, including the error, to variables. - Change the
Hello
argument from Gladys’s name to an empty string, so you can try out your error-handling code. - Look for a non-nil error value. There’s no sense continuing in this case.
- Use the functions in the standard library’s
log
package to output error information. If you get an error, you use the log package’sFatal
function to print the error and stop the program.
Run hello.go to confirm that the code works; now that you’re passing in an empty name, you’ll get an error:
$ go run hello.go
greetings: empty name
exit status 1
That’s essentially how error handling in Go works: Return an error as a value so the caller can check for it. It’s pretty simple.
Return a random greeting
Now you’ll change your code so that instead of returning the same greeting every time, it returns one of several predefined greeting messages.
To do this, you’ll use a Go slice. A slice is like an array, except that it’s dynamically sized as you add and remove items. It’s one of the most useful types in Go. You’ll add a small slice to contain three greeting messages, then have your code return one of the messages randomly.
Return to the greetings
module:
$ cd /home/gopher/greetings
Update greetings.go
as follows:
package greetings
import (
"errors"
"fmt"
"math/rand"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// init sets initial values for variables used in the function.
func init() {
// For truly random greetings, import "time" and replace the call
// to rand.Seed with:
//
// rand.Seed(time.Now().UnixNano())
//
// Calling rand.Seed with a constant value means that we always
// generate the same pseudo-random sequence.
rand.Seed(1)
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return one of the message formats selected at random.
return formats[rand.Intn(len(formats))]
}
In this code, you:
- Add a
randomFormat
function that returns a randomly selected format for a greeting message. Note thatrandomFormat
starts with a lowercase letter, making it accessible only to code in its own package (in other words, it’s not exported). - In
randomFormat
, declare aformats
slice with three message formats. When declaring a slice, you omit its size in the brackets, like this:[]string
. This tells Go that the array underlying a slice can be dynamically sized. - Use the
math/rand
package to generate a random number for selecting an item from the slice. - Add an
init
function to seed the rand package. Go executesinit
functions automatically at program startup, after global variables have been initialized. - In
Hello
, call therandomFormat
function to get a format for the message you’ll return, then use the format and name value together to create the message. - Return the message (or an
error
) as you did before.
Note that you are seeding the math/rand
package with a constant seed. This means the code will always generate the same
pseudo-random sequence.
You now need to re-publish the updated greetings
module so that we can use it in our hello
module.
Add and commit the changes you just made:
$ git add greetings.go
$ git commit -q -m 'Added random format'
Note the id of the commit we just created:
$ greetings_random_commit=$(git rev-parse HEAD)
Republish the greetings
module:
$ git push -q origin main
remote: . Processing 1 references
remote: Processed 1 references in total
Return to the hello
module directory and use this new version:
$ cd /home/gopher/hello
$ go get {{{.GREETINGS}}}@$greetings_random_commit
go: downloading {{{.GREETINGS}}} v0.0.0-20060102150405-abcedf12345
go: upgraded {{{.GREETINGS}}} v0.0.0-20060102150405-abcedf12345 => v0.0.0-20060102150405-abcedf12345
Re-add Gladys’s name as an argument to the Hello
function call in hello.go
:
package main
import (
"fmt"
"log"
"{{{.GREETINGS}}}"
)
func main() {
// Set properties of the predefined Logger, including
// the log entry prefix and a flag to disable printing
// the time, source file, and line number.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// Request a greeting message.
message, err := greetings.Hello("Gladys")
// If an error was returned, print it to the console and
// exit the program.
if err != nil {
log.Fatal(err)
}
// If no error was returned, print the returned message
// to the console.
fmt.Println(message)
}
Run hello.go
to confirm the code works. Notice that because of the constant seed, running the program
always gives the same greeting format. We will come back to that shortly:
$ go run hello.go
Hail, Gladys! Well met!
$ go run hello.go
Hail, Gladys! Well met!
That’s an introduction to a Go slice. To get even more use out of this type, you’ll use a slice to greet multiple people, where we will start to see some “real” pseudo-random greetings!
Return greetings for multiple people
In the last changes you’ll make to the greetings
module code, you’ll add support for getting greetings for
multiple people in one request. In other words, you’ll handle a multiple-value input and pair values with a
multiple-value output.
Change back to the greetings
module:
$ cd /home/gopher/greetings
To do this, you’ll need to pass a set of names to a function that can return a greeting for each of them. Changing the
Hello
function’s parameter from a single name to a set of names would change the function signature. Given that you
have already published the greetings module, other users might already have written code calling Hello
, that change
would break their programs. In this situation, a better choice is to give new functionality a new name.
Add a new function Hellos
that takes a set of names. For the sake of simplicity, have the new function call the
existing one. Keeping both functions in the package leaves the original for existing callers (or future callers who only
need one greeting) and adds a new one for callers that want the expanded functionality:
package greetings
import (
"errors"
"fmt"
"math/rand"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// Hellos returns a map that associates each of the named people
// with a greeting message.
func Hellos(names []string) (map[string]string, error) {
// A map to associate names with messages.
messages := make(map[string]string)
// Loop through the received slice of names, calling
// the Hello function to get a message for each name.
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
// In the map, associate the retrieved message with
// the name.
messages[name] = message
}
return messages, nil
}
// init sets initial values for variables used in the function.
func init() {
// For truly random greetings, import "time" and replace the call
// to rand.Seed with:
//
// rand.Seed(time.Now().UnixNano())
//
// Calling rand.Seed with a constant value means that we always
// generate the same pseudo-random sequence.
rand.Seed(1)
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return one of the message formats selected at random.
return formats[rand.Intn(len(formats))]
}
In this code, you:
- Add a
Hellos
function whose parameter is a slice of names rather than a single name. Also, you change one of its return types from astring
to amap
so you can return names mapped to greeting messages. - Have the new
Hellos
function call the existingHello
function. This leaves both functions in place. - Create a
messages
map to associate each of the received names (as a key) with a generated message (as a value). In Go, you initialize a map with the following syntax:make(map[key-type]value-type)
. You have theHello
function return this map to the caller. - Loop through the names your function received, checking that each has a non-empty value, then associate a message with
each. In this
for
loop,range
returns two values: the index of the current item in the loop and a copy of the item’s value. You don’t need the index, so you use the Go blank identifier (an underscore) to ignore it.
Instead of republishing the greetings
module, let’s add a replace
directive in our hello
module that tells the go
command
to use a local directory instead of a published module.
First return to the hello
module:
$ cd /home/gopher/hello
Now add a replace
directive using go mod edit
:
$ go mod edit -replace {{{.GREETINGS}}}=/home/gopher/greetings
We can see the result in the hello
module go.mod
file:
$ cat go.mod
module {{{.HELLO}}}
go 1.19
require {{{.GREETINGS}}} v0.0.0-20060102150405-abcedf12345 // indirect
replace {{{.GREETINGS}}} => /home/gopher/greetings
In your hello.go
calling code, pass a slice of names, then print the contents of the names/messages map you
get back:
package main
import (
"fmt"
"log"
"{{{.GREETINGS}}}"
)
func main() {
// Set properties of the predefined Logger, including
// the log entry prefix and a flag to disable printing
// the time, source file, and line number.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// A slice of names.
names := []string{"Gladys", "Samantha", "Darrin"}
// Request greeting messages for the names.
messages, err := greetings.Hellos(names)
if err != nil {
log.Fatal(err)
}
// If no error was returned, print the returned map of
// messages to the console.
fmt.Println(messages)
}
With these changes, you:
- Create a
names
variable as a slice type holding three names. - Pass the
names
variable as the argument to theHellos
function.
Run hello.go
to confirm that the code works, the output should be a string representation of the map
associating names with messages:
$ go run hello.go
map[Darrin:Hail, Darrin! Well met! Gladys:Hail, Gladys! Well met! Samantha:Hi, Samantha. Welcome!]
This section introduced maps for representing name/value pairs. It also introduced the idea of preserving backward compatibility by implementing a new function for new or changed functionality in a module. In the next section, you’ll use built-in features to create a unit test for your code.
Add a test
Now that you’ve gotten your code to a stable place (nicely done, by the way), add a test. Testing your code during
development can expose bugs that find their way in as you make changes. In this topic, you add a test for the Hello
function.
Go’s built-in support for unit testing makes it easier to test as you go. Specifically, using naming conventions, Go’s
testing
package, and the go test
command, you can quickly write and execute tests. You will create this test in the
greetings
module.
Return to the greetings
module:
$ cd /home/gopher/greetings
Create a file called greetings_test.go
:
package greetings
import (
"regexp"
"testing"
)
// TestHelloName calls greetings.Hello with a name, checking
// for a valid return value.
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\b` + name + `\b`)
msg, err := Hello(name)
if !want.MatchString(msg) || err != nil {
t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, <nil>`, msg, err, want)
}
}
// TestHelloEmpty calls greetings.Hello with an empty string,
// checking for an error.
func TestHelloEmpty(t *testing.T) {
msg, err := Hello("")
if msg != "" || err == nil {
t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
}
}
If this code, you:
- Implement test functions in the same package as the code you’re testing.
- Create two test functions to test the
greetings.Hello
function. Test function names have the formTestName
, whereName
is specific to the test. Also, test functions take a pointer to thetesting
package’stesting.T
as a parameter. You use this parameter’s methods for reporting and logging from your test. - Implement
TestHelloName
.TestHelloName
calls theHello
function, passing aname
value with which the function should be able to return a valid response message. If the call returns an error or an unexpected response message (one that doesn’t include the name you passed in), you use the t parameter’sFatalf
method to print a message to the console and end execution. - Implement
TestHelloEmpty
.TestHelloEmpty
calls theHello
function with an empty string. This test is designed to confirm that your error handling works. If the call returns a non-empty string or no error, you use the t parameter’sFatalf
method to print a message to the console and end execution.
At the command line in the greetings directory, run the go test
command to execute the test. The
go test
command executes test functions (whose names begin with Test
) in test files (whose names end with
_test.go
). You can add the -v
flag to get verbose output that lists all of the tests and their results.
The tests should pass:
$ go test
PASS
ok {{{.GREETINGS}}} 0.001s
$ go test -v
=== RUN TestHelloName
--- PASS: TestHelloName (0.00s)
=== RUN TestHelloEmpty
--- PASS: TestHelloEmpty (0.00s)
PASS
ok {{{.GREETINGS}}} 0.001s
You will now break the greetings.Hello
function to view a failing test. The TestHelloName
test function
checks the return value for the name you specified as a Hello
function parameter. To view a failing test result, change
the greetings.Hello
function so that it no longer includes the name:
package greetings
import (
"errors"
"fmt"
"math/rand"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
// message := fmt.Sprintf(randomFormat(), name)
message := fmt.Sprint(randomFormat())
return message, nil
}
// Hellos returns a map that associates each of the named people
// with a greeting message.
func Hellos(names []string) (map[string]string, error) {
// A map to associate names with messages.
messages := make(map[string]string)
// Loop through the received slice of names, calling
// the Hello function to get a message for each name.
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
// In the map, associate the retrieved message with
// the name.
messages[name] = message
}
return messages, nil
}
// init sets initial values for variables used in the function.
func init() {
// For truly random greetings, import "time" and replace the call
// to rand.Seed with:
//
// rand.Seed(time.Now().UnixNano())
//
// Calling rand.Seed with a constant value means that we always
// generate the same pseudo-random sequence.
rand.Seed(1)
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return one of the message formats selected at random.
return formats[rand.Intn(len(formats))]
}
Note that the highlighted lines change the value that the function returns, as if the name
argument had been
accidentally removed.
At the command line in the greetings directory, run go test
to execute the test. This time, run go test
without the -v
flag. The output will include results for only the tests that failed, which can be useful when you have
a lot of tests. The TestHelloName
test should fail – TestHelloEmpty
still passes:
$ go test
--- FAIL: TestHelloName (0.00s)
greetings_test.go:15: Hello("Gladys") = "Hail, %v! Well met!", <nil>, want match for `\bGladys\b`, <nil>
FAIL
exit status 1
FAIL {{{.GREETINGS}}} 0.001s
Let’s restore greetings.Hello
to a working state
package greetings
import (
"errors"
"fmt"
"math/rand"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// Hellos returns a map that associates each of the named people
// with a greeting message.
func Hellos(names []string) (map[string]string, error) {
// A map to associate names with messages.
messages := make(map[string]string)
// Loop through the received slice of names, calling
// the Hello function to get a message for each name.
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
// In the map, associate the retrieved message with
// the name.
messages[name] = message
}
return messages, nil
}
// init sets initial values for variables used in the function.
func init() {
// For truly random greetings, import "time" and replace the call
// to rand.Seed with:
//
// rand.Seed(time.Now().UnixNano())
//
// Calling rand.Seed with a constant value means that we always
// generate the same pseudo-random sequence.
rand.Seed(1)
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return one of the message formats selected at random.
return formats[rand.Intn(len(formats))]
}
And re-run go test
to verify our change:
$ go test
PASS
ok {{{.GREETINGS}}} 0.001s
This section introduced Go’s built-in support for unit testing. In the next section, you’ll see how to compile and install your code to run it locally.
Compile and install the application
In the last section, you’ll learn a new go
command. While the go run
command is a useful shortcut for compiling and
running a single-file program, it doesn’t generate a binary executable you can easily run again. If you want one of
those, a good choice is to run the go install
command, which compiles your code and installs the resulting binary
executable where you can run it.
Change to the directory that contains the hello
module:
$ cd /home/gopher/hello
Discover the Go install path, where the go
command will install the current package:
$ go list -f '{{.Target}}'
/home/gopher/go/bin/hello
Add the Go install directory to your system’s shell path (this is generally a one-off step, you won’t need to do this for other programs). That way, you’ll be able to run your program’s executable without specifying where the executable is:
$ goinstalldir="$(dirname "$(go list -f '{{.Target}}')")"
$ export PATH="$goinstalldir:$PATH"
Once you’ve updated the shell path, run the go install
command to compile and install the package:
$ go install
Run your application by simply typing its name:
$ hello
map[Darrin:Hail, Darrin! Well met! Gladys:Hail, Gladys! Well met! Samantha:Hi, Samantha. Welcome!]
Conclusion
That wraps up this guide!
As a next step you might like to consider: