From 1e8d9c59f4b186d0ac69a41a07bf2ab9aee15075 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Mon, 28 Oct 2019 22:20:15 +0000 Subject: [PATCH] Initial commit --- CHANGELOG.md | 12 + LICENSE | 12 + README.md | 9 + build.sh | 27 +++ overview.md | 105 +++++++++ src/1-hello-world.md | 387 ++++++++++++++++++++++++++++++++ src/10-repo-hygiene.md | 6 + src/11-go-modules.md | 6 + src/12-wiki.md | 6 + src/13-webapp-abstractions.md | 6 + src/14-conclusion.md | 5 + src/15-battlesnake.md | 6 + src/2-data-tyes.md | 6 + src/3-slices-maps.md | 6 + src/4-control-structures.md | 6 + src/5-functions.md | 5 + src/6-structures.md | 6 + src/7-http.md | 6 + src/8-testing.md | 6 + src/9-cli-app.md | 6 + src/GReeTZ.md | 11 + src/other_work_by_the_author.md | 4 + src/title.md | 6 + 23 files changed, 655 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100755 build.sh create mode 100644 overview.md create mode 100644 src/1-hello-world.md create mode 100644 src/10-repo-hygiene.md create mode 100644 src/11-go-modules.md create mode 100644 src/12-wiki.md create mode 100644 src/13-webapp-abstractions.md create mode 100644 src/14-conclusion.md create mode 100644 src/15-battlesnake.md create mode 100644 src/2-data-tyes.md create mode 100644 src/3-slices-maps.md create mode 100644 src/4-control-structures.md create mode 100644 src/5-functions.md create mode 100644 src/6-structures.md create mode 100644 src/7-http.md create mode 100644 src/8-testing.md create mode 100644 src/9-cli-app.md create mode 100644 src/GReeTZ.md create mode 100644 src/other_work_by_the_author.md create mode 100644 src/title.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6df33cf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +- The skeleton of the book is created +- The overview/TODO list is created +- Chapter 1 is written diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c6afc22 --- /dev/null +++ b/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2019 Christine Dodrill + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c6703d9 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# GetGoing + +A book on getting started with Go. + +## Building + +```console +$ ./build.sh +``` diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..4ab208b --- /dev/null +++ b/build.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +files=' + src/title.md + CHANGELOG.md + src/1-hello-world.md + src/2-data-tyes.md + src/3-slices-maps.md + src/4-control-structures.md + src/5-functions.md + src/6-structures.md + src/7-http.md + src/8-testing.md + src/9-cli-app.md + src/10-repo-hygiene.md + src/11-go-modules.md + src/12-wiki.md + src/13-webapp-abstractions.md + src/14-conclusion.md + src/15-battlesnake.md + src/GReeTZ.md + src/other_work_by_the_author.md +' + +rev=$(git rev-parse HEAD) + +pandoc -o getgoing diff --git a/overview.md b/overview.md new file mode 100644 index 0000000..7d82fc1 --- /dev/null +++ b/overview.md @@ -0,0 +1,105 @@ +--- +sitename: "Within" +title: "Overview" +template: blog +--- + +The following is my overview for what I want this book to cover. This may be +incomplete and probably will become out of date quickly, but this is basically +my TODO list. + +Each top level bullet point is its own chapter/workshop. Slides will be made +available as soon as they are created. + +- [x] Basic getting started + - [x] installing go + - [x] hello world + - [x] doing math +- [ ] Data Types + - [ ] Variables + - [ ] Declaring variables + - [ ] Assigning variables + - [ ] Integers + - [ ] byte, int, int32, int64 + - [ ] Implement Subtract/Multiply + - [ ] Floating-point numbers + - [ ] Differences between floating point numbers and integers + - [ ] float32, float64 + - [ ] Strings + - [ ] examples of strings + - [ ] immutable + - [ ] combining strings +- [ ] Slices and maps + - [ ] generic types (this doesn’t mean Go has user-defined generic types) + - [ ] Slices + - [ ] creating + - [ ] appending + - [ ] sorting + - [ ] common slice types + - [ ] Maps + - [ ] make() + - [ ] add value + - [ ] delete value +- [ ] Control structures + - [ ] conditionals + - [ ] if + - [ ] switch + - [ ] type switch + - [ ] looping + - [ ] conditional looping + - [ ] C-style for loop + - [ ] iteration +- [ ] Functions + - [ ] Writing functions + - [ ] Documentation + - [ ] Types of functions + - [ ] Functions are data + - [ ] Functions as arguments to functions +- [ ] Structures + - [ ] defining structs + - [ ] documenting structs + - [ ] instantiating structs + - [ ] JSON support for structures + - [ ] What's the deal with pointers? + - [ ] pointers make values mutable across functions +- [ ] HTTP operations + - [ ] fetching data from canhazip.com + - [ ] validating response + - [ ] parsing response + - [ ] printing response +- [ ] Testing + - [ ] making a fake server for canhazip.com + - [ ] using it in testing +- [ ] Command line app writing + - [ ] Flags + - [ ] Help + - [ ] How to test a command line app +- [ ] Repo hygiene + - [ ] What should go where + - [ ] Applying that to previous things +- [ ] Go Modules + - [ ] how to depend on people's code + - [ ] best practices for releasing code + - [ ] semantic versioning and side effects + - [ ] add markdown support to the wiki +- [ ] Putting it all together with a webapp + - [ ] The Wiki example from the Go documentation  + - [ ] https://golang.org/doc/articles/wiki/ + - [ ] Updated a bit + - [ ] Tests +- [ ] Webapp Abstractions + - [ ] Adding a JSON api to it + - [ ] Making a client package + - [ ] Tests + - [ ] Abstracting its storage layer to a database (ql?) + - [ ] Migrations  + - [ ] Tests + - [ ] Dockerizing + - [ ] Making the Dockerfile + - [ ] Testing with Docker +- [ ] Bonus: Introduction to Battlesnake + - [ ] brief overview of the problem space + - [ ] the types involved + - [ ] tutorial on how to make a snake + - [ ] somewhere to run it? + diff --git a/src/1-hello-world.md b/src/1-hello-world.md new file mode 100644 index 0000000..b18b759 --- /dev/null +++ b/src/1-hello-world.md @@ -0,0 +1,387 @@ +--- +sitename: Within +title: "Go Training 1: Get Going" +template: blog +--- + +This post is the first in a series I'm creating to help people learn the +[Go][go] programming language. It's aimed at people who understand the high +level concepts of programming, but haven't had much practical experience with +it. + +[go]: https://golang.org + +Like always, feedback is very welcome. Any feedback I get will be used to help +make this course even better. + +## What is Go? + +Go is a compiled programming language made by Google. It has a lot of features +out of the box, including: + +* A static type system +* Fast compile times +* Efficient code generation +* Parallel programming for free* +* A strong standard library +* Cross-compilation with ease (including webassembly) +* and more! + +\* You still have to write code that can avoid race conditions, more on those +later. + +### Why Use Go? + +Go is a very easy to read and write programming language. Consider this snippet: + +```go +func Add(x int, y int) int { + return x + y +} +``` + +This function wraps [integer +addition](https://golang.org/ref/spec#Arithmetic_operators). When you call it it +returns the sum of x and y. + +## Installing Go + +### Linux + +Installing Go on Linux systems is a very distribution-specific thing. Please see +[this tutorial on +DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-install-go-on-ubuntu-18-04) +for more information. + +### macOS + +* Go to https://golang.org/dl +* Download the .pkg file +* Double-click on it and go through the installer process + +### Windows + +* Go to https://golang.org/dl +* Download the .msi file +* Double-click on it and go through the installer process + +### Next Steps + +These next steps are needed to set up your shell for Go programs. + +Pick a directory you want to store Go programs and downloaded source code in. +This is called your GOPATH. This is usually the `go` folder in +your home directory. If for some reason you want another folder for this, use +that folder instead of `$HOME/go` below. + +#### Linux/macOS + +This next step is unfortunately shell-specific. To find out what shell you are +using, run the following command in your terminal: + +```console +$ env | grep SHELL +``` + +The name at the path will be the shell you are using. + +##### bash + +If you are using bash, add the following lines to your .bashrc (Linux) or +.bash_profile (macOS): + +``` +export GOPATH=$HOME/go +export PATH=$PATH:$GOPATH/bin +``` + +Then reload the configuration by closing and re-opening your terminal. + +##### fish + +If you are using fish, create a file in ~/.config/fish/conf.d/go.fish with the +following lines: + +``` +set -gx GOPATH $HOME/go +set -gx PATH $PATH $GOPATH/bin +``` + +##### zsh + +If you are using zsh, add the following lines to your .zshrc: + +``` +export GOPATH=$HOME/go +export PATH=$PATH:$GOPATH/bin +``` + +#### Windows + +Follow the instructions [here](https://github.com/golang/go/wiki/SettingGOPATH#windows). + +## Hello, world! + +Now that everything is installed, let's test it with the classic "Hello, world!" +program. Create a folder in your code folder called `go_learning` and create a +subfolder called `hello`. Open a file in there called `hello.go` in your +favorite text editor and type in the following: + +```go +// Command hello is your first Go program. +package main + +import "fmt" + +func main() { + fmt.Println("Hello, world!") +} +``` + +This program prints "Hello, world!" and then immediately exits. Here's each of +the parts in detail: + +```go +// Command hello is your first go program. +package main // Every go file must be in a package. + // Package main is used for creating executable files. + +import "fmt" // Go doesn't implicitly import anything. You need to + // explicitly import "fmt" for printing text to + // standard output. + +func main() { // func main is the entrypoint of the program, or + // where the computer starts executing your code + fmt.Println("Hello, world!") // This prints "Hello, world!" followed by a newline + // to standard output. +} // This ends the main function +``` + +Now to run this program run the following command: + +```console +$ go run hello.go +Hello, world! +``` + +`go run` compiles and runs the code for you, without creating a persistent binary +file. This is a good way to run programs while you are writing them. + +To create a binary, use `go build`: + +```console +$ go build hello.go +$ ./hello +Hello, world! +``` + +`go build` has the compiler create a persistent binary file and puts it in the +same directory as you are running `go` from. Go will choose the filename of the +binary based on the name of the .go file passed to it. These binaries are +usually static binaries, or binaries that are safe to distribute to other +computers without having to worry about linked libraries. + +## Go Modules + +[Go modules](https://github.com/golang/go/wiki/Modules) are the current state of +the art of dependency and project management for programs written in Go. We will +cover them in much more detail in the future, but for now create a module for +your hello command with the following command: + +```console +$ go mod init your-name.localhost/hello +go: creating new go.mod: module christine-dodrill.localhost/hello +``` + +This creates a file called go.mod that tells the compiler details about your +project. Again, we will cover this in more detail in the future, but just know +this exists for now. + +## Creating Other Files + +Go packages map to folders on the filesystem. This means that every .go file in +the same filesystem folder must be inside the same package in order for the +package to compile. There are some edge case exceptions to this rule, of course, +but those will be covered later. + +### Adding Numbers + +Create a new file called `math.go` with the following contents: + +``` +package main + +// Add adds two numbers and returns the sum. +func Add(x, y int) int { + return x + y +} +``` + +This file creates a function called `Add` that adds the numbers it is given. +This function is also documented because there's a comment immediately above it +explaining what it does. We can view the documentation with the `go doc` +command: + +```console +$ go doc -all +Command hello is your first Go program. + +FUNCTIONS + +func Add(x, y int) int + Add adds two numbers and returns the sum. This helps you understand functions. +``` + +Go automatically keeps track of documentation comments and lets you query them +with `go doc`. These comments should usually help explain _why_ things are the +way they are. That helps your future self understand what is going on there. + +### Dividing Numbers + +Go allows functions to return multiple values. When a function returns a result +but can also results in an error it is a common idiom to return two values: the +result and the error. + +Unlike Java and Python, Go does not have have Exceptions that get thrown. +Instead, errors are regular values returned by functions. + +We can model this idiom with integer division, where anything divided by zero is +famously undefined. + +Add the following to `math.go`: + +```go +// ErrDivideByZero is returned when Divide would divide by zero. +var ErrDivideByZero = errors.New("divide by zero") + +// Divide performs floating-point division and returns the result. If the right +// hand side of Divide is zero, it returns ErrDivideByZero to avoid a panic. +func Divide(lhs, rhs float64) (float64, error) { + if rhs == 0 { + return 0, ErrDivideByZero + } + + return lhs / rhs, nil +} +``` + +And add this to the top of `math.go`, just below the `package` line: + +```go +import "errors" +``` + +We need to import the errors package to create the ErrDivideByZero error. This +error will be returned when the left-hand-side of the Divide function is zero. + +### Weaving it Together + +Now these functions in `math.go` are usable from `hello.go`. Let's add a few +numbers after the "Hello, world!" call. + +```go +var sum int = Add(2, 2) +fmt.Println("2 + 2:", sum) +``` + +This creates an integer variable called sum and sets it to the result of adding +2 and 2 together. You can also create the sum variable by doing this: + +```go +sum := Add(2, 2) +``` + +The `:=` operator automagically declares the variable on its left hand side with +the value on its right hand side. + +Now run it with `go run .`. The `.` argument tells `go run` to use the package +in the current working directory. + +```console +$ go run . +Hello, world! +2 + 2: 4 +``` + +Let's add division. Add the following lines under the last fmt.Println call: + +```go +quotient, err := Divide(4, 2) +if err != nil { + panic(err) +} +fmt.Println("4 / 2:", quotient) +``` + +And run it: + +```console +$ go run . +Hello, world! +2 + 2: 4 +4 / 2: 2 +``` + +Now, what would happen if you divide something by zero? Let's find out by adding +the following after the last fmt.Println call: + +```go +quotient, err = Divide(4, 0) +if err != nil { + panic(err) +} +fmt.Println("but the quotient of 4 / 0 was:", quotient) +``` + +The `:=` operator isn't used here because that would cause a compile error. This +error would happen because the last `:=` already defined the variables and names +cannot be redefined in Go. + +Now let's run it: + +```console +$ go run . +Hello, world! +2 + 2: 4 +4 / 2: 2 +panic: divide by zero + +goroutine 1 [running]: +main.main() + /Users/christine.dodrill/Code/go_learning/hello/hello.go:20 +0x26c +exit status 2 +``` + +This panics with the error "divide by zero" because of the call on line 20. +Let's change that panic to a println so we can see what the quotient would be: + +```go +quotient, err = Divide(4, 0) +if err != nil { + fmt.Println("got an error:", err) +} +fmt.Println("but the quotient of 4 / 0 was:", quotient) +``` + +And run it: + +```console +$ go run . +Hello, world! +2 + 2: 4 +4 / 2: 2 +got an error: divide by zero +but the quotient of 4 / 0 was: 0 +
``` + +The error was caught. This lets you handle errors with any custom logic you'd +need to write. Sometimes it could mean passing an error up to its caller, +sometimes it could mean retrying. It really depends on the context. + +## Conclusion + +And that about wraps it up for Lesson 1 in Go. Next we'll be covering making a +HTTP request and validating its response with icanhazip.com. Like I mentioned +before, feedback on this helps a lot. + +Thanks and be well. diff --git a/src/10-repo-hygiene.md b/src/10-repo-hygiene.md new file mode 100644 index 0000000..8700dbf --- /dev/null +++ b/src/10-repo-hygiene.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 10: Repo Hygiene" +template: blog +--- + diff --git a/src/11-go-modules.md b/src/11-go-modules.md new file mode 100644 index 0000000..77c65ae --- /dev/null +++ b/src/11-go-modules.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 11: Go Modules" +template: blog +--- + diff --git a/src/12-wiki.md b/src/12-wiki.md new file mode 100644 index 0000000..3b54d8c --- /dev/null +++ b/src/12-wiki.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 12: Putting it All Together with a Wiki" +template: blog +--- + diff --git a/src/13-webapp-abstractions.md b/src/13-webapp-abstractions.md new file mode 100644 index 0000000..b1118f3 --- /dev/null +++ b/src/13-webapp-abstractions.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 13: Webapp Abstractions" +template: blog +--- + diff --git a/src/14-conclusion.md b/src/14-conclusion.md new file mode 100644 index 0000000..e13d355 --- /dev/null +++ b/src/14-conclusion.md @@ -0,0 +1,5 @@ +--- +title: "Go Training 14: Conclusion" +sitename: Within +template: blog +--- diff --git a/src/15-battlesnake.md b/src/15-battlesnake.md new file mode 100644 index 0000000..674ce52 --- /dev/null +++ b/src/15-battlesnake.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 15: Bonus: Battlesnake" +template: blog +--- + diff --git a/src/2-data-tyes.md b/src/2-data-tyes.md new file mode 100644 index 0000000..9a06477 --- /dev/null +++ b/src/2-data-tyes.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 2: Types" +template: blog +--- + diff --git a/src/3-slices-maps.md b/src/3-slices-maps.md new file mode 100644 index 0000000..7064eb2 --- /dev/null +++ b/src/3-slices-maps.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 3: Slices, Arrays and Maps" +template: blog +--- + diff --git a/src/4-control-structures.md b/src/4-control-structures.md new file mode 100644 index 0000000..f7d9c49 --- /dev/null +++ b/src/4-control-structures.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 4: Control Structures" +template: blog +--- + diff --git a/src/5-functions.md b/src/5-functions.md new file mode 100644 index 0000000..29993ad --- /dev/null +++ b/src/5-functions.md @@ -0,0 +1,5 @@ +--- +sitename: Within +title: "Go Training 5: Functions" +template: blog +--- diff --git a/src/6-structures.md b/src/6-structures.md new file mode 100644 index 0000000..0a5a223 --- /dev/null +++ b/src/6-structures.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 6: Structures" +template: blog +--- + diff --git a/src/7-http.md b/src/7-http.md new file mode 100644 index 0000000..4f774c9 --- /dev/null +++ b/src/7-http.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 7: HTTP Operations" +template: blog +--- + diff --git a/src/8-testing.md b/src/8-testing.md new file mode 100644 index 0000000..7cc0a17 --- /dev/null +++ b/src/8-testing.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 8: Testing" +template: blog +--- + diff --git a/src/9-cli-app.md b/src/9-cli-app.md new file mode 100644 index 0000000..813b005 --- /dev/null +++ b/src/9-cli-app.md @@ -0,0 +1,6 @@ +--- +sitename: Within +title: "Go Training 9: Writing a Command-line App" +template: blog +--- + diff --git a/src/GReeTZ.md b/src/GReeTZ.md new file mode 100644 index 0000000..b907304 --- /dev/null +++ b/src/GReeTZ.md @@ -0,0 +1,11 @@ +# GReeTZ + +This book wouldn't have been possible without the help of the following people +(in no particular order): + +- Amit Malhotra +- A. Wilcox +- Dylan Bourque +- Ashvita Sidharthan (TODO: check spelling) +- Edward Muller +- Vladimir Pouzanov diff --git a/src/other_work_by_the_author.md b/src/other_work_by_the_author.md new file mode 100644 index 0000000..8d57a03 --- /dev/null +++ b/src/other_work_by_the_author.md @@ -0,0 +1,4 @@ +# Other Work By the Author + +- [Christine Dodrill's Blog](https://christine.website/blog) +- [When then Zen](https://when-then-zen.christine.website) diff --git a/src/title.md b/src/title.md new file mode 100644 index 0000000..ace9616 --- /dev/null +++ b/src/title.md @@ -0,0 +1,6 @@ +--- +title: Get Going +author: Christine Dodrill +language: en_us +rights: 0BSD +---