Go for Python Programmers¶
This book is intended to provide a solid introduction to the Go language for experienced Python programmers.
Contents
About This Book¶
Copying¶
All source code used in this book is Free Software, released under the terms of the GPL v3.
The remainder of the book is released under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Sing along with Richard Stallman, founder of the Free Software movement!
Resources¶
The Sphinx source code for this book is available on on Github.
The latest version of this book is published at Read the Docs. It is also available in PDF and ePub formats.
Classroom Instruction¶
Classroom instruction in Go, Python, SQL, REST API development, cloud deployment, and continuous integration is available from the author in Silicon Valley, or on demand anywhere in the world, for groups of five to twelve students. Contact the author for more information.
Author¶
Jason McVetta is an independent consultant, teacher, and Free Software activist based in beautiful-but-too-cold San Francisco. He studied government and philosophy in college, but was unwilling to sell his soul to the Demopublicratican Party, so he went to work in software. After 12 years as a professional Pythonist he met his new love, Go. He is able to fly without mechanical assistance.
Payment¶
This is a Free book, but you are more than welcome to pay me for it! You are under no obligation, legal or moral, to do so. But I can always use a couple bucks for coffee. =)
Citations
[1] | https://en.wikipedia.org/wiki/Go_(programming_language) |
Introduction¶
Go is like C and Python had a kid, who inherited Python’s good looks and pleasant demeanor, along with C’s confidence and athletic ability.
What is Go?¶
Go is an open source, compiled, garbage-collected, concurrent system programming language. It was first designed and developed at Google Inc. beginning in September 2007 by Robert Griesemer, Rob Pike, and Ken Thompson. [1]
Minimalist¶
The creators of Go advocate a minimalist approach to language design. This minimal elegance is often contrasted with the “kitchen sink” approach of C++.
Opinionated¶
Like Python, in Go there is often “one right way to do things”, although that phrase is not so commonly used as in the Pythonist community. The compiler is renowed for its strictness. Things that would at most be warnings in other languages - e.g. unused imports, unused variables - are hard compiler errors in Go. At first that may seem like a draconian buzzkill - but soon you will begin to appreciate how clean and cruft-free it keeps your code.
Fast¶
No question about it - Go is blazing fast. Despite a still young compiler with minimal speed optimizations, Go regularly scores at or near the top of inter-language benchmark comparisons. That’s because Go is statically typed, compiled - and although garbage-collected, allows the programmer some degree of control over memory usage.
Batteries Included¶
To a large degree Go follows Python’s “batteries included” philosophy. Although there are not yet as many 3rd party libraries as there are for Python, nevertheless Go’s standard library provides a solid foundation for many modern programming tasks. Built-in support for serving HTTP, de/serializing JSON, template rendering, and strong cryptography make Go ideal for modern web services development.
Productive¶
Go is frequently - and favorably - compared with Python and Ruby for programmer productivity. Its clean and elegant syntax, unobtrusive static typing, optional duck typing, batteries-included standard library, lighting-fast compiliation, and support for a variety of modern continuous integration tools make Go a productivity champion.
Searching¶
Since “go” is such a common English word, it is completely useless as a search term when googling. Instead search for “golang”. It is standard practice in the community that all Go-related blog posts, Github repos, tweets, job postings, etc be tagged with “golang”.
Who’s Using Go?¶
- Home of the Go authors and core team, signifiant parts of the Google infrastructure are thought to be written in Go. The company however does not publicly disclose which Google services are written in which languages. Youtube is known to be powered by Vitess, an open source, massively scalable database multiplexing layer written in Go.
- Heroku
- Maintainers of the pq driver for PostgreSQL, significant parts of Heroku’s infrastructure are said to be written in Go. One component that has been open sourced is Doozer, a consistent distributed data store.
- Canonical
- The company behind Ubuntu Linux recently rewrote its Juju devops management application from Python to Go, with pleasing results.
- Soundcloud
- Internet music thought leaders SoundCloud use a bespoke build and deployment system called Bazooka, designed to be a platform for managing the deployment of internal services. It is promised that Bazooka will be open sourced soon.
- Bitly
- Significant parts of Bitly are written in Go, including nsq, a realtime distributed message processing system.
- Cloudflare
- Large volumes of internet traffic are served by Cloudflare’s Railgun web optimization software, designed to speed up the delivery of content that cannot be cached.
- Iron.io
- Cloud infrastructure company and core Go community supporters Iron.io replaced parts of their Ruby codebase with Go, allowing them to handle a greater load with 2 workers than with 30 Ruby workers.
- TinkerCAD
- Cloud-based CAD application TinkerCAD is written in Go.
- Drone.io
- Continuous integration service Drone.io is written in Go.
Background Assumptions¶
- Familiarity with Python or a similar dynamic, interpreted language.
- Comfortable working on the UNIX command line.
- Basic understanding of internet protocols such as HTTP(S).
Requirements¶
Command line examples were written on an Ubuntu 12.10 desktop environment. Everything we do in this book can also be done on other flavors of Linux, on Mac OSX - probably even on Windows.
In addition to Go language basics, this book also covers cloud deployment and continuous integration tools & techniques popular in the Go community. You will need free accounts on the following services:
Further Reading¶
- Effective Go by the creators of the language. Perhaps the single most valuable documentation resource for Go programmers.
- An Introduction to Programming in Go by Caleb Doxsey
- Go for Pythonists by Aditya Mukurjee
Citations
[1] | https://en.wikipedia.org/wiki/Go_(programming_language) |
Installation & Setup¶
Installing Go¶
The first thing we need is a working Go installation on our system. The following instructions were derived from the official Getting Started documentation.
Binary Packages¶
Binary distributions of Go are available for the FreeBSD, Linux, Mac OS X, NetBSD, and Windows operating systems from the official downloads page.
Building from Source¶
Many developers prefer to install Go directly from the source code. Building is easy and quick - the Go compiler and tool chain can be compiled in a matter of minutes on even a modest workstation or laptop.
Install Build Tools¶
The Go tool chain is written in C. To build it, you need a C compiler installed. You will also need the Mercurial DVCS tool to download the source. On Ubuntu run the following command to install the necessary packages:
$ sudo apt-get install gcc libc6-dev mercurial
See Installing Go from source and Install C tools for build instructions on other platforms.
Fetch the repository¶
Go will install to a directory named go
. Change to the directory that will
be its parent and make sure the go
directory does not exist. Then check out
the repository:
$ hg clone -u release https://code.google.com/p/go
Build Go¶
To build the Go distribution, run
$ cd go/src
$ ./all.bash
If all goes well, it will finish by printing output like:
ALL TESTS PASSED
---
Installed Go for linux/amd64 in /home/you/go.
Installed commands in /home/you/go/bin.
*** You need to add /home/you/go/bin to your $PATH. ***
where the details on the last few lines reflect the operating system, architecture, and root directory used during the install.
Environment Variables¶
These instructions assume Go is installed at ~/go
. If you installed
elsewhere, change the commands to reflect your actual installation path.
The Go tools look for several environment variables. Typically these are set in
your shell profile. If you are using Bash, add the following lines to your
~/.bashrc
:
export GOBIN=~/go/bin
export GOARCH=amd64
export GOOS=linux
export GOROOT=~/go
PATH¶
You probably also want to add the path to your go/bin
directory to your PATH
:
export PATH=$PATH:/home/you/go/bin
Reload your ~/.bashrc
file to active the new environment variables. Once
the go
binary is on your PATH
, you can confirm your install is working
correctly by running the go version
command.
$ go version
go version go1.1.1 linux/amd64
GOPATH¶
The GOPATH
environment variable is used to specify directories outside of
$GOROOT
that contain Go source code. Typically GOPATH
is set to the
root of a workspace.
See Project Layout for more detail.
Intellij IDE¶
Go bindings are available for many popular programming editors and IDEs. As Go is still a relatively young language, none of these bindings are as full-featured as those for a mature language like Java. However a good integrated development environment, even if not perfect, is still a valuable tool.
Currently (July 2013) the IDE with the best Go support is Intellij IDEA.
Download¶
Download the Free community edition of Intellij IDEA appropriate for your platform from the official download page.
Untar the downloaded tarball, descend into the resulting folder, and start Intellij by running:
$ ./bin/idea.sh
Install Go Plugin¶
Open the Settings window (File -> Settings
) and go to Plugins
under
IDE Settings
. Click on Browse repositories
, and type “golang” into the
search form. There should be only one result, “golang.org support”.
Double-click on it to install, and close the settings. You will be prompted to
restart Intellij.
If you like vi-keys, you may also wish to install the IdeaVim
plugin.
Hello, World!¶
Let’s start out with a Hello World example. Our program will greet the world with a hello and the current time.
In Python it looks something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/usr/bin/env python
import time
def greeting():
'''Returns a pleasant, semi-useful greeting.'''
return "Hello world, the time is: " + time.ctime()
def main():
print greeting()
if __name__ == '__main__':
main()
|
It’s not that different in Go:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // A "Hello World" program that prints a greeting with the current time.
package main
import (
"fmt"
"time"
)
// greeting returns a pleasant, semi-useful greeting.
func greeting() string {
return "Hello world, the time is: " + time.Now().String()
}
func main() {
fmt.Println(greeting())
}
|
Curly Braces¶
The first thing one may notice is that whereas Python uses whitespace to denote
scope, Go uses curly braces. The Go authors did, however, take a lesson from
Python’s culture of readable code. Although it is certainly possible to write
syntactically valid Go code without any indentation at all, nevertheless almost
all Go code one sees is formatted consistently and readably. That’s because,
Go includes a code formatter along with the compiler. The formatter, gofmt
,
is considered canonically correct by the Go community - if you don’t like how
gofmt
formats your code, you are wrong. It is customary that gofmt
always be run before checking in code.
$ gofmt -w hello.go # -w option updates the file(s) in place
Package¶
In any .go
file, the first non-comment line is a package
declaration.
The package declaration is mandatory - every .go
file must begin with one.
Every .go
file in the same folder must have the same package name.
The package
declaration is preceded by a comment, called the package
comment. Automatic documentation tools like godoc
extract the package
comment as the description of your program.
// A "Hello World" program that prints a greeting with the current time.
package main
Import¶
Next comes the import
declaration. Although it is optional, most .go
files will have one. Each package to be imported is listed on a separate line,
inside quotation marks. The packages in our example, fmt
and time
, come
from the standard library. By convention, 3rd-party packages are named after
their repository URL. For example, my Neo4j library hosted on Github would be
imported as "github.com/jmcvetta/neo4j"
.
import (
"fmt"
"time"
)
Functions¶
Our program has two functions, greeting()
and main()
.
The function greeting()
takes no arguments, and returns a string. Unlike
Java and C, in Go the type declaration follows the function name. Like all
good function declarations, this one includes a doc comment describing what it
does.
// greeting returns a pleasant, semi-useful greeting.
func greeting() string {
Return¶
Every function that declares a return type, must end with a return
statement. In this case we add a literal string to the output of
time.Now().String()
Let’s look at the documentatation for time
. We can see that time.Now()
returns an instance of type Time
. That instance, in turn, exports a
String()
method that unsurprisingly returns a string
. Using the
addition operator with two strings results in the strings being concatenated.
If we had tried to add our greeting string to just time.Now()
the code would
not compile, due to type mismatch.
$ godoc time Now String
PACKAGE DOCUMENTATION
package time
import "time"
[ ... ]
type Time struct {
// contains filtered or unexported fields
}
A Time represents an instant in time with nanosecond precision.
Programs using times should typically store and pass them as values, not
pointers. That is, time variables and struct fields should be of type
time.Time, not *time.Time. A Time value can be used by multiple
goroutines simultaneously.
Time instants can be compared using the Before, After, and Equal
methods. The Sub method subtracts two instants, producing a Duration.
The Add method adds a Time and a Duration, producing a Time.
The zero value of type Time is January 1, year 1, 00:00:00.000000000
UTC. As this time is unlikely to come up in practice, the IsZero method
gives a simple way of detecting a time that has not been initialized
explicitly.
Each Time has associated with it a Location, consulted when computing
the presentation form of the time, such as in the Format, Hour, and Year
methods. The methods Local, UTC, and In return a Time with a specific
location. Changing the location in this way changes only the
presentation; it does not change the instant in time being denoted and
therefore does not affect the computations described in earlier
paragraphs.
func Now() Time
Now returns the current local time.
func (t Time) String() string
String returns the time formatted using the format string
"2006-01-02 15:04:05.999999999 -0700 MST"
[ ... ]
Variables¶
Python is dynamically typed. That means there is no difference between variable
assignment and declaration. For example, saying x = 3
is equally valid if
x
was previously undeclared, or if it was already declared as an integer, or
even if it was already declared as e.g. a string.
Go, on the other hand, is statically typed. A variable must be declared as a
specific type before a value can be assigned to it. Once declared, a variable
may only be assigned values of its declared type. Go also provides an operator,
:=
, that combined declaration and assignment in the same statement.
Let’s look at a needlessly complex version of our greeting function to see how variable declaration and assignment work.
1 2 3 4 5 6 7 8 9 | // needlesslyComplexGreeting uses needlessly complex operations to return a
// pleasant, semi-useful greeting.
func needlesslyComplexGreeting() string {
var now string
now = time.Now().String()
msg := "Hello world, the time is: "
msg += now
return msg
}
|
On line 4 we used the var
keyword to declare the variable now
as a
string. It is initially set to the zero value for string
type, which is
“” the empty string. Line 5 assigns the (string) return value of
time.Now().String()
to now
.
On line 6 we use the short variable declaration syntax to declare msg
as
a string
, and immediately assign it the value of a literal string. The
resulting variable is exactly the same as if we had declared it as var msg
string
on a seperate line.
Line 7 appends the value of now
to the value of msg
, working in this
case exactly like Python’s +=
operator. However unlike Python, only
strings can be added to other strings, no automatic type coercion is ever
attempted.
main()
¶
Our Hello World program declares its package as main
, and contains a special
function main()
. That tells Go to compile this code as an executable
program, with the entry point at main()
. The function main()
has no
arguments and no return value. Command line arguments - called “argv” in many
languages - are available from the standard library, either raw from
os.Args
, or with higher level abstraction from the package flag
.
Compiling¶
Python is an interpretted language - our program can be run immediately with the
python
command:
$ python hello.py
Hello world, the time is: Sat Jul 13 12:49:14 2013
Go on the other hand is a compiled language - our source code must first be
compiled into an executable binary before we can run it. We will use the go
command line tool to access the compiler.
go run
¶
As a convenience, the go
tool provides a run
command that first compiles
the specified file(s), then executes the resulting binary. Given Go’s
lightning-quick compile times, using go run
can feel similar to working with
an interpretted language like Python or Ruby.
$ go run hello.go
Hello world, the time is: 2013-07-13 13:01:23.837155926 -0700 PDT
Only programs that declare package main
– in other words, those which can
be compiled into an executable application – can be run with go run
. Note
that all files to be compiled must be specified on the command line, even tho
they are all declared as part of the same package.
Running code with go run
does not leave an executable binary file laying
around - it is deleted immediately after it is run.
go build
¶
We can use the go build
command to compile our code into an executable
binary. The binary is statically linked, and can be redistributed (on the same
platform) just by copying it, with no dependencies. The binary file is created
in the same folder that contains the source code.
$ ls
hello.go
$ go build -v .
hello
$ ls
hello* hello.go
$ ./hello
Hello world, the time is: 2013-07-13 13:07:57.150564433 -0700 PDT
go install
¶
The go install
command works like go build
, except instead of putting
the binary file in the source code folder, it installs it to
$GOPATH/bin
. If $GOPATH/bin
is on your $PATH
, your program will be
available as a command after running go install
.
$ ls
hello.go
$ go install -v .
hello
$ ls
hello.go
$ ls $GOPATH/bin
hello*
Documentation¶
Good documentation is an essential part of any Go program. You will frequently need to read and understand the documentation for 3rd Party Open Source libraries. As you become a skilled Gopher you will probably also want to publish your own Open Source packages. A well-documented package attracts more users, and reflects well on its author.
Self-Documenting Code¶
Go code is self-documenting, meaning the source code explains itself without
needing external documentation. If you include doc comments in your code as
described below, tools like godoc
will automatically generate useful
documentation for your packages. [1]
Package Comments¶
Every package should have a package comment, a block comment preceding the package clause. For multi-file packages, the package comment only needs to be present in one file, and any one will do. The package comment should introduce the package and provide information relevant to the package as a whole. It will appear first on the godoc page and should set up the detailed documentation that follows.
/*
Package regexp implements a simple library for regular expressions.
The syntax of the regular expressions accepted is:
regexp:
concatenation { '|' concatenation }
concatenation:
{ closure }
closure:
term [ '*' | '+' | '?' ]
term:
'^'
'$'
'.'
character
'[' [ '^' ] character-ranges ']'
'(' regexp ')'
*/
package regexp
If the package is simple, the package comment can be brief.
// Package path implements utility routines for
// manipulating slash-separated filename paths.
package path
Comments do not need extra formatting such as banners of stars. The generated output may not even be presented in a fixed-width font, so don’t depend on spacing for alignment—godoc, like gofmt, takes care of that. The comments are uninterpreted plain text, so HTML and other annotations such as _this_ will reproduce verbatim and should not be used. One adjustment godoc does do is to display indented text in a fixed-width font, suitable for program snippets. The package comment for the fmt package uses this to good effect.
Depending on the context, godoc might not even reformat comments, so make sure they look good straight up: use correct spelling, punctuation, and sentence structure, fold long lines, and so on.
Doc Comments¶
Inside a package, any comment immediately preceding a top-level declaration serves as a doc comment for that declaration. Every exported (capitalized) name in a program should have a doc comment.
Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.
// Compile parses a regular expression and returns, if successful, a Regexp
// object that can be used to match against text.
func Compile(str string) (regexp *Regexp, err error) {
If the name always begins the comment, the output of godoc can usefully be run through grep. Imagine you couldn’t remember the name “Compile” but were looking for the parsing function for regular expressions, so you ran the command,
$ godoc regexp | grep parse
If all the doc comments in the package began, “This function…”, grep wouldn’t help you remember the name. But because the package starts each doc comment with the name, you’d see something like this, which recalls the word you’re looking for.
$ godoc regexp | grep parse
Compile parses a regular expression and returns, if successful, a Regexp
parsed. It simplifies safe initialization of global variables holding
cannot be parsed. It simplifies safe initialization of global variables
$
Go’s declaration syntax allows grouping of declarations. A single doc comment can introduce a group of related constants or variables. Since the whole declaration is presented, such a comment can often be perfunctory.
// Error codes returned by failures to parse an expression.
var (
ErrInternal = errors.New("regexp: internal error")
ErrUnmatchedLpar = errors.New("regexp: unmatched '('")
ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")
...
)
Uncommented Code Is Broken¶
Seriously, if your code doesn’t have good doc comments, it is by definition lousy code.
Todo
Write a short diatribe on the importance of code commentary.
godoc
tool¶
Godoc extracts and generates documentation for Go programs. [2]
It has two modes.
Without the -http
flag, it runs in command-line mode and prints plain text
documentation to standard output and exits. If both a library package and a
command with the same name exists, using the prefix cmd/ will force
documentation on the command rather than the library package. If the -src
flag is specified, godoc prints the exported interface of a package in Go source
form, or the implementation of a specific exported language entity:
godoc fmt # documentation for package fmt
godoc fmt Printf # documentation for fmt.Printf
godoc cmd/go # force documentation for the go command
godoc -src fmt # fmt package interface in Go source form
godoc -src fmt Printf # implementation of fmt.Printf
With the -http
flag, it runs as a web server and presents the documentation
as a web page.
godoc -http=:6060
GoDoc.org¶
GoDoc is an open source web application that displays documentation for Go
packages on Bitbucket, Github, Launchpad and Google Project Hosting. It is
similar to the godoc
command, but can display documentation for any open
source Go module specified by its import URL.
Using GoDoc.org¶
To view a package’s documentation on GoDoc.org you enter its import path. Let’s
check out the docs for mgo
, the popular MongoDB database driver. Its import
path is labix.org/v2/mgo
.
We could also haved typed in just “mgo” and GoDoc would show us packages with
that string in their name. However it is does not attempt to rank results by
relevance or popularity, so the actual mgo
driver would not be one of the
first few results.
Click “Go!” and GoDoc will display the documentation for our package. The documentation starts with the package’s name, import path, and package comment.
Up next is an alphabetical index of all the exported entities in the package - constants, variables, types, and functions. Methods are displayed beneath the type to which they are bound.
Click on the index entry for Collection
to be taken to its detailed
documentation. The exported fields and methods of structs are displayed, as
well as the type signature of functions and methods. The entity’s doc comment
is displayed, if it has one.
Sometimes the documentation is not enough, and we want to look at the source
code. Click on the function name Count
to see its source.
Open Source¶
GoDoc.org is open source! If you want to see how it works, check out https://github.com/garyburd/gddo!
Go Walker¶
Also check out Go Walker, a new enhanced version of GoDoc that displays code snippets alongside the documentation.
Citations
[1] | The following sections mostly copied from http://golang.org/doc/effective_go.html#commentary |
[2] | The following section copied from the package comment of godoc |
The Go Toolchain¶
Go is a compiled language - the source code you write must be converted to a
binary format understandable to a computer before it is executed. The compiler
is accessed through the go
command. In addition, the go
command
provides several other tools
The sections below describe several of the more popular go
commands, but do
not cover the complete set. For full information run:
$ go help
go build
¶
Build compiles the packages named by the import paths, along with their dependencies, but it does not install the results.
If the arguments are a list of .go files, build treats them as a list of source files specifying a single package.
When the command line specifies a single main package, build writes the resulting executable to output. Otherwise build compiles the packages but discards the results, serving only as a check that the packages can be built.
$ go build somefile.go # Build just this one file
$ go build # Build package in current folder
Project Layout¶
Just as $PYTHONPATH
controls where the Python interpreter will look for
source files, $GOPATH
controls where the Go compiler and tools will look for
source code.
Hello World¶
Let us consider a modified version of the standard “Hello World” program. Our example will consist of a library package and an application package. The library exports one function, which returns the string “Hello world, the time is: ” plus the current time. The application package calls the library function, and prints the hello message to the console.
Python¶
In Python we might have a file layout like this:
$PYTHONPATH/
hello.py
greeter.py
The library package is contained in greeter.py
:
The application is contained in hello.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/usr/bin/env python
import time
def greeting():
'''Returns a pleasant, semi-useful greeting.'''
return "Hello world, the time is: " + time.ctime()
def main():
print greeting()
if __name__ == '__main__':
main()
|
We run the Python application like this:
$ python hello.py
Hello world, the time is: Mon Jul 8 19:16:40 2013
Go¶
The “standard” layout for Go code is more complex than that for Python code. The disadvantage is that setup is slightly more work. The upside is a well-structured codebase that encourages modular code and keeps things orderly as a project grows in size.
Typically Go code is developed using distributed version control systems like Git or Mercurial. Therefore import paths are conventionally named based on the Github etc URL. The Go toolchain is aware of this, and can gracefully handle automatic dependency installation if your project conforms to the convention.
Imagine for a moment we have created a Github repository named hello
for our
Hello World example. We would create a file layout like this:
$GOPATH/
src/
github.com/
jmcvetta/
hello/
hello.go
greeter/
greeter.go
The library is located in greeter.go
. Note the package name, greeter
,
is the same as the name of the containing folder. This is mandatory. The
package imports time
from the standard library.
The application is in hello.go
. This file declares its package as main
,
and defines a main()
function. This tells the compiler to generate an
executable from the file. The package imports fmt
from the standard
library, and our greeter
package specified by its path.
Functions imported from another package are always namespaced with the package
name. In this case, we call greeter.Greeting()
. Go intentionally has no
equivalent of Python’s from some_package import *
.
We can build the application with the go build
command:
$ go build -v
github.com/jmcvetta/hello/greeter
github.com/jmcvetta/hello
$ ls
greeter/ hello* hello.go
$ ./hello
Hello world, the time is: 2013-07-08 19:49:39.946836748 -0700 PDT
Dependencies¶
The go
tool can automatically install dependencies. They are installed in
the same URL-derived folder heirarchy alongside your code.
Let’s embelish our Greeting()
function by making it return the current
PATH
as well. Although this could be done using nothing but the standard
library, for purpose of instruction we will use the popular env package.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package greeter
import (
"github.com/darkhelmet/env"
"time"
)
// Greeting returns a pleasant, semi-useful greeting.
func Greeting() string {
msg := "Hello world, the time is "
msg += time.Now().String()
msg += " and your PATH is "
msg += env.String("PATH")
return msg
}
|
We can automatically install our new dependency with the go get
command:
$ go get -v .
github.com/darkhelmet/env (download)
github.com/darkhelmet/env
github.com/jmcvetta/hello/greeter
github.com/jmcvetta/hello
Now we the env
package installed, and our file system looks like:
$GOPATH/
src/
github.com/
darkhelmet/
env/
env.go
env_test.go
format.bash
LICENSE.md
README.md
jmcvetta/
hello/
hello.go
greeter/
greeter.go
We can try out our new Hello World with the go run
command, which build the application then runs it.
$ go run hello.go
Hello world, the time is 2013-07-08 20:36:31.496236239 -0700 PDT and your PATH is /home/jason/.rvm/gems/ruby-1.9.2-p320/bin:/home/jason/.rvm/gems/ruby-1.9.2-p320@global/bin:/home/jason/.rvm/rubies/ruby-1.9.2-p320/bin:/home/jason/.rvm/bin:/usr/local/heroku/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/jason/opt/bin:/home/jason/.scripts:/home/jason/opt/go/bin:/home/jason/work/go/bin:/home/jason/.rvm/bin