| <!--{ | |
| "Title": "How to Write Go Code", | |
| "Template": true, | |
| "Breadcrumb": true | |
| }--> | |
| <h2 id="Introduction">Introduction</h2> | |
| <p> | |
| This document demonstrates the development of a simple Go package inside a | |
| module and introduces the <a href="/cmd/go/">go tool</a>, the standard way to | |
| fetch, build, and install Go modules, packages, and commands. | |
| </p> | |
| <h2 id="Organization">Code organization</h2> | |
| <p> | |
| Go programs are organized into packages. A <dfn>package</dfn> is a collection | |
| of source files in the same directory that are compiled together. Functions, | |
| types, variables, and constants defined in one source file are visible to all | |
| other source files within the same package. | |
| </p> | |
| <p> | |
| A repository contains one or more modules. A <dfn>module</dfn> is a collection | |
| of related Go packages that are released together. A Go repository typically | |
| contains only one module, located at the root of the repository. A file named | |
| <code>go.mod</code> there declares the <dfn>module path</dfn>: the import path | |
| prefix for all packages within the module. The module contains the packages in | |
| the directory containing its <code>go.mod</code> file as well as subdirectories | |
| of that directory, up to the next subdirectory containing another | |
| <code>go.mod</code> file (if any). | |
| </p> | |
| <p> | |
| Note that you don't need to publish your code to a remote repository before you | |
| can build it. A module can be defined locally without belonging to a repository. | |
| However, it's a good habit to organize your code as if you will publish it | |
| someday. | |
| </p> | |
| <p> | |
| Each module's path not only serves as an import path prefix for its packages, | |
| but also indicates where the <code>go</code> command should look to download it. | |
| For example, in order to download the module <code>golang.org/x/tools</code>, | |
| the <code>go</code> command would consult the repository indicated by | |
| <code>https://golang.org/x/tools</code> (described more <a href="/cmd/go/#hdr-Remote_import_paths">here</a>). | |
| </p> | |
| <p> | |
| An <dfn>import path</dfn> is a string used to import a package. A package's | |
| import path is its module path joined with its subdirectory within the module. | |
| For example, the module <code>github.com/google/go-cmp</code> contains a package | |
| in the directory <code>cmp/</code>. That package's import path is | |
| <code>github.com/google/go-cmp/cmp</code>. Packages in the standard library do | |
| not have a module path prefix. | |
| </p> | |
| <h2 id="Command">Your first program</h2> | |
| <p> | |
| To compile and run a simple program, first choose a module path (we'll use | |
| <code>example/user/hello</code>) and create a <code>go.mod</code> file that | |
| declares it: | |
| </p> | |
| <pre> | |
| $ mkdir hello # Alternatively, clone it if it already exists in version control. | |
| $ cd hello | |
| $ <b>go mod init example/user/hello</b> | |
| go: creating new go.mod: module example/user/hello | |
| $ cat go.mod | |
| module example/user/hello | |
| go 1.16 | |
| $ | |
| </pre> | |
| <p> | |
| The first statement in a Go source file must be | |
| <code>package <dfn>name</dfn></code>. Executable commands must always use | |
| <code>package main</code>. | |
| </p> | |
| <p> | |
| Next, create a file named <code>hello.go</code> inside that directory containing | |
| the following Go code: | |
| </p> | |
| <pre> | |
| package main | |
| import "fmt" | |
| func main() { | |
| fmt.Println("Hello, world.") | |
| } | |
| </pre> | |
| <p> | |
| Now you can build and install that program with the <code>go</code> tool: | |
| </p> | |
| <pre> | |
| $ <b>go install example/user/hello</b> | |
| $ | |
| </pre> | |
| <p> | |
| This command builds the <code>hello</code> command, producing an executable | |
| binary. It then installs that binary as <code>$HOME/go/bin/hello</code> (or, | |
| under Windows, <code>%USERPROFILE%\go\bin\hello.exe</code>). | |
| </p> | |
| <p> | |
| The install directory is controlled by the <code>GOPATH</code> | |
| and <code>GOBIN</code> <a href="/cmd/go/#hdr-Environment_variables">environment | |
| variables</a>. If <code>GOBIN</code> is set, binaries are installed to that | |
| directory. If <code>GOPATH</code> is set, binaries are installed to | |
| the <code>bin</code> subdirectory of the first directory in | |
| the <code>GOPATH</code> list. Otherwise, binaries are installed to | |
| the <code>bin</code> subdirectory of the default <code>GOPATH</code> | |
| (<code>$HOME/go</code> or <code>%USERPROFILE%\go</code>). | |
| </p> | |
| <p> | |
| You can use the <code>go env</code> command to portably set the default value | |
| for an environment variable for future <code>go</code> commands: | |
| </p> | |
| <pre> | |
| $ go env -w GOBIN=/somewhere/else/bin | |
| $ | |
| </pre> | |
| <p> | |
| To unset a variable previously set by <code>go env -w</code>, use <code>go env -u</code>: | |
| </p> | |
| <pre> | |
| $ go env -u GOBIN | |
| $ | |
| </pre> | |
| <p> | |
| Commands like <code>go install</code> apply within the context of the module | |
| containing the current working directory. If the working directory is not within | |
| the <code>example/user/hello</code> module, <code>go install</code> may fail. | |
| </p> | |
| <p> | |
| For convenience, <code>go</code> commands accept paths relative | |
| to the working directory, and default to the package in the | |
| current working directory if no other path is given. | |
| So in our working directory, the following commands are all equivalent: | |
| </p> | |
| <pre> | |
| $ go install example/user/hello | |
| </pre> | |
| <pre> | |
| $ go install . | |
| </pre> | |
| <pre> | |
| $ go install | |
| </pre> | |
| <p> | |
| Next, let's run the program to ensure it works. For added convenience, we'll | |
| add the install directory to our <code>PATH</code> to make running binaries | |
| easy: | |
| </p> | |
| <!-- Note: we can't use $(go env GOBIN) here until https://golang.org/issue/23439 is addressed. --> | |
| <pre> | |
| # Windows users should consult /wiki/SettingGOPATH | |
| # for setting %PATH%. | |
| $ <b>export PATH=$PATH:$(dirname $(go list -f '{{"{{.Target}}"}}' .))</b> | |
| $ <b>hello</b> | |
| Hello, world. | |
| $ | |
| </pre> | |
| <p> | |
| If you're using a source control system, now would be a good time to initialize | |
| a repository, add the files, and commit your first change. Again, this step is | |
| optional: you do not need to use source control to write Go code. | |
| </p> | |
| <pre> | |
| $ <b>git init</b> | |
| Initialized empty Git repository in /home/user/hello/.git/ | |
| $ <b>git add go.mod hello.go</b> | |
| $ <b>git commit -m "initial commit"</b> | |
| [master (root-commit) 0b4507d] initial commit | |
| 1 file changed, 7 insertion(+) | |
| create mode 100644 go.mod hello.go | |
| $ | |
| </pre> | |
| <p> | |
| The <code>go</code> command locates the repository containing a given module path by requesting a corresponding HTTPS URL and reading metadata embedded in the HTML response (see | |
| <code><a href="/cmd/go/#hdr-Remote_import_paths">go help importpath</a></code>). | |
| Many hosting services already provide that metadata for repositories containing | |
| Go code, so the easiest way to make your module available for others to use is | |
| usually to make its module path match the URL for the repository. | |
| </p> | |
| <h3 id="ImportingLocal">Importing packages from your module</h3> | |
| <p> | |
| Let's write a <code>morestrings</code> package and use it from the <code>hello</code> program. | |
| First, create a directory for the package named | |
| <code>$HOME/hello/morestrings</code>, and then a file named | |
| <code>reverse.go</code> in that directory with the following contents: | |
| </p> | |
| <pre> | |
| // Package morestrings implements additional functions to manipulate UTF-8 | |
| // encoded strings, beyond what is provided in the standard "strings" package. | |
| package morestrings | |
| // ReverseRunes returns its argument string reversed rune-wise left to right. | |
| func ReverseRunes(s string) string { | |
| r := []rune(s) | |
| for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { | |
| r[i], r[j] = r[j], r[i] | |
| } | |
| return string(r) | |
| } | |
| </pre> | |
| <p> | |
| Because our <code>ReverseRunes</code> function begins with an upper-case | |
| letter, it is <a href="/ref/spec#Exported_identifiers"><dfn>exported</dfn></a>, | |
| and can be used in other packages that import our <code>morestrings</code> | |
| package. | |
| </p> | |
| <p> | |
| Let's test that the package compiles with <code>go build</code>: | |
| </p> | |
| <pre> | |
| $ cd $HOME/hello/morestrings | |
| $ <b>go build</b> | |
| $ | |
| </pre> | |
| <p> | |
| This won't produce an output file. Instead it saves the compiled package in the | |
| local build cache. | |
| </p> | |
| <p> | |
| After confirming that the <code>morestrings</code> package builds, let's use it | |
| from the <code>hello</code> program. To do so, modify your original | |
| <code>$HOME/hello/hello.go</code> to use the morestrings package: | |
| </p> | |
| <pre> | |
| package main | |
| import ( | |
| "fmt" | |
| <b>"example/user/hello/morestrings"</b> | |
| ) | |
| func main() { | |
| fmt.Println(morestrings.ReverseRunes("!oG ,olleH")) | |
| } | |
| </pre> | |
| <p> | |
| Install the <code>hello</code> program: | |
| </p> | |
| <pre> | |
| $ <b>go install example/user/hello</b> | |
| </pre> | |
| <p> | |
| Running the new version of the program, you should see a new, reversed message: | |
| </p> | |
| <pre> | |
| $ <b>hello</b> | |
| Hello, Go! | |
| </pre> | |
| <h3 id="ImportingRemote">Importing packages from remote modules</h3> | |
| <p> | |
| An import path can describe how to obtain the package source code using a | |
| revision control system such as Git or Mercurial. The <code>go</code> tool uses | |
| this property to automatically fetch packages from remote repositories. | |
| For instance, to use <code>github.com/google/go-cmp/cmp</code> in your program: | |
| </p> | |
| <pre> | |
| package main | |
| import ( | |
| "fmt" | |
| "example/user/hello/morestrings" | |
| "github.com/google/go-cmp/cmp" | |
| ) | |
| func main() { | |
| fmt.Println(morestrings.ReverseRunes("!oG ,olleH")) | |
| fmt.Println(cmp.Diff("Hello World", "Hello Go")) | |
| } | |
| </pre> | |
| <p> | |
| Now that you have a dependency on an external module, you need to download that | |
| module and record its version in your <code>go.mod</code> file. The <code>go | |
| mod tidy</code> command adds missing module requirements for imported packages | |
| and removes requirements on modules that aren't used anymore. | |
| </p> | |
| <pre> | |
| $ go mod tidy | |
| go: finding module for package github.com/google/go-cmp/cmp | |
| go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.5.4 | |
| $ go install example/user/hello | |
| $ hello | |
| Hello, Go! | |
| string( | |
| - "Hello World", | |
| + "Hello Go", | |
| ) | |
| $ cat go.mod | |
| module example/user/hello | |
| go 1.16 | |
| <b>require github.com/google/go-cmp v0.5.4</b> | |
| $ | |
| </pre> | |
| <p> | |
| Module dependencies are automatically downloaded to the <code>pkg/mod</code> | |
| subdirectory of the directory indicated by the <code>GOPATH</code> environment | |
| variable. The downloaded contents for a given version of a module are shared | |
| among all other modules that <code>require</code> that version, so | |
| the <code>go</code> command marks those files and directories as read-only. To | |
| remove all downloaded modules, you can pass the <code>-modcache</code> flag | |
| to <code>go clean</code>: | |
| </p> | |
| <pre> | |
| $ go clean -modcache | |
| $ | |
| </pre> | |
| <h2 id="Testing">Testing</h2> | |
| <p> | |
| Go has a lightweight test framework composed of the <code>go test</code> | |
| command and the <code>testing</code> package. | |
| </p> | |
| <p> | |
| You write a test by creating a file with a name ending in <code>_test.go</code> | |
| that contains functions named <code>TestXXX</code> with signature | |
| <code>func (t *testing.T)</code>. | |
| The test framework runs each such function; | |
| if the function calls a failure function such as <code>t.Error</code> or | |
| <code>t.Fail</code>, the test is considered to have failed. | |
| </p> | |
| <p> | |
| Add a test to the <code>morestrings</code> package by creating the file | |
| <code>$HOME/hello/morestrings/reverse_test.go</code> containing | |
| the following Go code. | |
| </p> | |
| <pre> | |
| package morestrings | |
| import "testing" | |
| func TestReverseRunes(t *testing.T) { | |
| cases := []struct { | |
| in, want string | |
| }{ | |
| {"Hello, world", "dlrow ,olleH"}, | |
| {"Hello, 世界", "界世 ,olleH"}, | |
| {"", ""}, | |
| } | |
| for _, c := range cases { | |
| got := ReverseRunes(c.in) | |
| if got != c.want { | |
| t.Errorf("ReverseRunes(%q) == %q, want %q", c.in, got, c.want) | |
| } | |
| } | |
| } | |
| </pre> | |
| <p> | |
| Then run the test with <code>go test</code>: | |
| </p> | |
| <pre> | |
| $ cd $HOME/hello/morestrings | |
| $ <b>go test</b> | |
| PASS | |
| ok example/user/hello/morestrings 0.165s | |
| $ | |
| </pre> | |
| <p> | |
| Run <code><a href="/cmd/go/#hdr-Test_packages">go help test</a></code> and see the | |
| <a href="/pkg/testing/">testing package documentation</a> for more detail. | |
| </p> | |
| <h2 id="next">What's next</h2> | |
| <p> | |
| Subscribe to the | |
| <a href="https://groups.google.com/group/golang-announce">golang-announce</a> | |
| mailing list to be notified when a new stable version of Go is released. | |
| </p> | |
| <p> | |
| See <a href="/doc/effective_go.html">Effective Go</a> for tips on writing | |
| clear, idiomatic Go code. | |
| </p> | |
| <p> | |
| Take | |
| <a href="/tour/">A Tour of Go</a> | |
| to learn the language proper. | |
| </p> | |
| <p> | |
| Visit the <a href="/doc/#articles">documentation page</a> for a set of in-depth | |
| articles about the Go language and its libraries and tools. | |
| </p> | |
| <h2 id="help">Getting help</h2> | |
| <p> | |
| For real-time help, ask the helpful gophers in the community-run | |
| <a href="https://gophers.slack.com/messages/general/">gophers Slack server</a> | |
| (grab an invite <a href="https://invite.slack.golangbridge.org/">here</a>). | |
| </p> | |
| <p> | |
| The official mailing list for discussion of the Go language is | |
| <a href="https://groups.google.com/group/golang-nuts">Go Nuts</a>. | |
| </p> | |
| <p> | |
| Report bugs using the | |
| <a href="/issue">Go issue tracker</a>. | |
| </p> |