This commit is contained in:
wagslane
2023-05-01 15:25:27 -06:00
parent f8912668b8
commit 9be3074de6
868 changed files with 58698 additions and 2 deletions

View File

@@ -0,0 +1,14 @@
package mailio
import (
"fmt"
)
func test(text string) {
fmt.Println(text)
}
func main() {
test("starting Mailio server")
test("stopping Mailio server")
}

View File

@@ -0,0 +1,14 @@
package main
import (
"fmt"
)
func test(text string) {
fmt.Println(text)
}
func main() {
test("starting Mailio server")
test("stopping Mailio server")
}

View File

@@ -0,0 +1,2 @@
starting Mailio server
stopping Mailio server

View File

@@ -0,0 +1,28 @@
# Packages
Every Go program is made up of packages.
You have probably noticed the `package main` at the top of all the programs you have been writing.
A package named "main" has an entrypoint at the `main()` function. A `main` package is compiled into an executable program.
A package by any other name is a "library package". Libraries have no entry point. Libraries simply export functionality that can be used by other packages. For example:
```go
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}
```
This program is an executable. It is a "main" package and *imports* from the `fmt` and `math/rand` library packages.
## Assignment
Fix the bug in the code.

View File

@@ -0,0 +1,8 @@
{
"question": "What does 'go install' do?",
"answers": [
"Compiles and installs the program locally",
"Installs dependencies",
"Saves local code to the remote source control provider"
]
}

View File

@@ -0,0 +1,27 @@
# Go Install
## Build an executable
Ensure you are in your `hellogo` repo, then run:
```bash
go install
```
Navigate out of your project directory:
```bash
cd ../
```
Go has installed the `hellogo` program globally. Run it with:
```bash
hellogo
```
## Tip about "not found"
If you get an error regarding "hellogo not found" it means you probably don't have your Go environment setup properly. Specifically, `go install` is adding your binary to your `GOBIN` directory, but that may not be in your `PATH`.
You can read more about that here in the [go install docs](https://pkg.go.dev/cmd/go#hdr-Compile_and_install_packages_and_dependencies).

View File

@@ -0,0 +1,7 @@
{
"question": "Code must be compiled with 'go build' before running 'go install'",
"answers": [
"False",
"True"
]
}

View File

@@ -0,0 +1,27 @@
# Go Install
## Build an executable
Ensure you are in your `hellogo` repo, then run:
```bash
go install
```
Navigate out of your project directory:
```bash
cd ../
```
Go has installed the `hellogo` program globally. Run it with:
```bash
hellogo
```
## Tip about "not found"
If you get an error regarding "hellogo not found" it means you probably don't have your Go environment setup properly. Specifically, `go install` is adding your binary to your `GOBIN` directory, but that may not be in your `PATH`.
You can read more about that here in the [go install docs](https://pkg.go.dev/cmd/go#hdr-Compile_and_install_packages_and_dependencies).

View File

@@ -0,0 +1,7 @@
{
"question": "What was the output from 'go build' in the library package",
"answers": [
"The compiled package is silently saved to the local build cache",
"An executable program"
]
}

View File

@@ -0,0 +1,45 @@
# Custom Package
Let's write a package to import and use in `hellogo`.
Create a sibling directory at the same level as the `hellogo` directory:
```bash
mkdir mystrings
cd mystrings
```
Initialize a module:
```bash
go mod init {REMOTE}/{USERNAME}/mystrings
```
Then create a new file `mystrings.go` in that directory and paste the following code:
```go
// by convention, we name our package the same as the directory
package mystrings
// Reverse reverses a string left to right
// Notice that we need to capitalize the first letter of the function
// If we don't then we won't be able access this function outside of the
// mystrings package
func Reverse(s string) string {
result := ""
for _, v := range s {
result = string(v) + result
}
return result
}
```
Note that there is no `main.go` or `func main()` in this package.
`go build` won't build an executable from a library package. However, `go build` will still compile the package and save it to our local build cache. It's useful for checking for compile errors.
Run:
```bash
go build
```

View File

@@ -0,0 +1,7 @@
{
"question": "Why is the function 'Reverse()' instead of 'reverse()'?",
"answers": [
"Lowercase names aren't exported for external use",
"Conventionally uppercase names are used in Go"
]
}

View File

@@ -0,0 +1,45 @@
# Custom Package
Let's write a package to import and use in `hellogo`.
Create a sibling directory at the same level as the `hellogo` directory:
```bash
mkdir mystrings
cd mystrings
```
Initialize a module:
```bash
go mod init {REMOTE}/{USERNAME}/mystrings
```
Then create a new file `mystrings.go` in that directory and paste the following code:
```go
// by convention, we name our package the same as the directory
package mystrings
// Reverse reverses a string left to right
// Notice that we need to capitlize the first letter of the function
// If we don't then we won't be able access this function outside of the
// mystrings package
func Reverse(s string) string {
result := ""
for _, v := range s {
result = string(v) + result
}
return result
}
```
Note that there is no `main.go` or `func main()` in this package.
`go build` won't build an executable from a library package. However, `go build` will still compile the package and save it to our local build cache. It's useful for checking for compile errors.
Run:
```bash
go build
```

View File

@@ -0,0 +1,8 @@
{
"question": "Does a package in a folder named 'dateparser' need to also be called 'dateparser'",
"answers": [
"No, but it should by convention",
"Yes",
"No, by convention we should avoid consistent naming"
]
}

View File

@@ -0,0 +1,45 @@
# Custom Package
Let's write a package to import and use in `hellogo`.
Create a sibling directory at the same level as the `hellogo` directory:
```bash
mkdir mystrings
cd mystrings
```
Initialize a module:
```bash
go mod init {REMOTE}/{USERNAME}/mystrings
```
Then create a new file `mystrings.go` in that directory and paste the following code:
```go
// by convention, we name our package the same as the directory
package mystrings
// Reverse reverses a string left to right
// Notice that we need to capitlize the first letter of the function
// If we don't then we won't be able access this function outside of the
// mystrings package
func Reverse(s string) string {
result := ""
for _, v := range s {
result = string(v) + result
}
return result
}
```
Note that there is no `main.go` or `func main()` in this package.
`go build` won't build an executable from a library package. However, `go build` will still compile the package and save it to our local build cache. It's useful for checking for compile errors.
Run:
```bash
go build
```

View File

@@ -0,0 +1,8 @@
{
"question": "What was printed by the new hellogo program?",
"answers": [
"dlrow olleh",
"hello world",
"world hello"
]
}

View File

@@ -0,0 +1,40 @@
# Custom Package Continued
Let's use our new `mystrings` package in `hellogo`
Modify hellogo's `main.go` file:
```go
package main
import (
"fmt"
"{REMOTE}/{USERNAME}/mystrings"
)
func main() {
fmt.Println(mystrings.Reverse("hello world"))
}
```
Don't forget to replace {REMOTE} and {USERNAME} with the values you used before. Then edit hellogo's `go.mod` file to contain the following:
```go
module example.com/username/hellogo
go 1.20
replace example.com/username/mystrings v0.0.0 => ../mystrings
require (
example.com/username/mystrings v0.0.0
)
```
Now build and run the new program:
```bash
go build
./hellogo
```

View File

@@ -0,0 +1,9 @@
{
"question": "How does the go toolchain know where to find the imported code?",
"answers": [
"We used the 'replace' keyword in go.mod to point it to the relative location of mystrings",
"It downloads it from Google's servers",
"NPM hosts the files publicly",
"It was fetched from Github"
]
}

View File

@@ -0,0 +1,40 @@
# Custom Package Continued
Let's use our new `mystrings` package in `hellogo`
Modify hellogo's `main.go` file:
```go
package main
import (
"fmt"
"{REMOTE}/{USERNAME}/mystrings"
)
func main() {
fmt.Println(mystrings.Reverse("hello world"))
}
```
Don't forget to replace {REMOTE} and {USERNAME} with the values you used before. Then edit hellogo's `go.mod` file to contain the following:
```go
module example.com/username/hellogo
go 1.20
replace example.com/username/mystrings v0.0.0 => ../mystrings
require (
example.com/username/mystrings v0.0.0
)
```
Now build and run the new program:
```bash
go build
./hellogo
```

View File

@@ -0,0 +1,7 @@
{
"question": "How did the Go toolchain know where to download the go-tinytime package?",
"answers": [
"The module import path is used for remote lookups, e.g. https://github.com/wagslane/go-tinytime",
"The go toolchain has every open-source Go module's location memorized"
]
}

View File

@@ -0,0 +1,86 @@
# Remote Packages
Let's learn how to use an open-source package that's available online.
## A note on how you should publish modules
Be aware that using the "replace" keyword like we did in the last assignment *isn't advised*, but can be useful to get up and running quickly. The *proper* way to create and depend on modules is to publish them to a remote repository. When you do that, the "replace keyword can be dropped from the `go.mod`:
### Bad
This works for local-only development
```go
module github.com/wagslane/hellogo
go 1.20
replace github.com/wagslane/mystrings v0.0.0 => ../mystrings
require (
github.com/wagslane/mystrings v0.0.0
)
```
### Good
This works if we publish our modules to a remote location like Github as we should.
```go
module github.com/wagslane/hellogo
go 1.20
require (
github.com/wagslane/mystrings v0.0.0
)
```
## Assignment
First, create a new directory in the same parent directory as `hellogo` and `mystrings` called `datetest`.
Create `main.go` in `datetest` and add the following code:
```go
package main
import (
"fmt"
"time"
tinytime "github.com/wagslane/go-tinytime"
)
func main() {
tt := tinytime.New(1585750374)
tt = tt.Add(time.Hour * 48)
fmt.Println(tt)
}
```
Initialize a module:
```bash
go mod init {REMOTE}/{USERNAME}/datetest
```
Download and install the remote go-tinydate package using `go get`:
```bash
go get github.com/wagslane/go-tinytime
```
Print the contents of your go.mod file to see the changes:
```bash
cat go.mod
```
Compile and run your program:
```bash
go build
./datetest
```

View File

@@ -0,0 +1,8 @@
{
"question": "What was printed after running the new datetest program?",
"answers": [
"2020-04-03T14:12:54Z",
"2025-04-03T14:12:54Z",
"Year: 2020, Month: 04, Day: 05"
]
}

View File

@@ -0,0 +1,87 @@
# Remote Packages
Let's learn how to use an open-source package that's available online.
## A note on how you should publish modules
Be aware that using the "replace" keyword like we did in the last assignment *isn't advised*, but can be useful to get up and running quickly. The *proper* way to create and depend on modules is to publish them to a remote repository. When you do that, the "replace keyword can be dropped from the `go.mod`:
### Bad
This works for local-only development
```go
module github.com/wagslane/hellogo
go 1.20
replace github.com/wagslane/mystrings v0.0.0 => ../mystrings
require (
github.com/wagslane/mystrings v0.0.0
)
```
### Good
This works if we publish our modules to a remote location like Github as we should.
```go
module github.com/wagslane/hellogo
go 1.20
require (
github.com/wagslane/mystrings v0.0.0
)
```
## Assignment
First, create a new directory in the same parent directory as `hellogo` and `mystrings` called `datetest`.
Create `main.go` in `datetest` and add the following code:
```go
package main
import (
"fmt"
"time"
tinytime "github.com/wagslane/go-tinytime"
)
func main() {
tt := tinytime.New(1585750374)
tt = tt.Add(time.Hour * 48)
fmt.Println(tt)
}
```
Initialize a module:
```bash
go mod init {REMOTE}/{USERNAME}/datetest
```
Download and install the remote go-tinydate package using `go get`:
```bash
go get github.com/wagslane/go-tinytime
```
Print the contents of your go.mod file to see the changes:
```bash
cat go.mod
```
Compile and run your program:
```bash
go build
./datetest
```

View File

@@ -0,0 +1,7 @@
{
"question": "Should you export code from the main package?",
"answers": [
"Nope",
"Yup"
]
}

View File

@@ -0,0 +1,50 @@
# Clean Packages
Ive often seen, and have been responsible for, throwing code into packages without much thought. Ive quickly drawn a line in the sand and started putting code into different folders (which in Go are different packages by definition) just for the sake of findability. Learning to properly build small and reusable packages can take your Go career to the next level.
## Rules Of Thumb
### 1. Hide internal logic
If you're familiar with the pillars of OOP, this is a practice in *encapsulation*.
Oftentimes an application will have complex logic that requires a lot of code. In almost every case the logic that the application cares about can be exposed via an API, and most of the dirty work can be kept within a package. For example, imagine we are building an application that needs to classify images. We could build a package:
```go
package classifier
// ClassifyImage classifies images as "hotdog" or "not hotdog"
func ClassifyImage(image []byte) (imageType string) {
return hasHotdogColors(image) && hasHotdogShape(image)
}
func hasHotdogShape(image []byte) bool {
// internal logic that the application doesn't need to know about
return true
}
func hasHotdogColors(image []byte) bool {
// internal logic that the application doesn't need to know about
return true
}
```
We create an API by only exposing the function(s) that the application-level needs to know about. All other logic is unexported to keep a clean separation of concerns. The application doesnt need to know how to classify an image, just the result of the classification.
### 2. Dont change APIs
The unexported functions within a package can and should change often for testing, refactoring, and bug fixing.
A well-designed library will have a stable API so that users arent receiving breaking changes each time they update the package version. In Go, this means not changing exported functions signatures.
### 3. Dont export functions from the main package
A `main` package isn't a library, there's no need to export functions from it.
### 4. Packages shouldn't know about dependents
Perhaps one of the most important and most broken rules is that a package shouldnt know anything about its dependents. In other words, a package should never have specific knowledge about a particular application that uses it.
## Further Reading
You can optionally [read more here](https://blog.boot.dev/golang/how-to-separate-library-packages-in-go/) if you're interested.

View File

@@ -0,0 +1,7 @@
{
"question": "When should you NOT export a function, variable, or type?",
"answers": [
"When the end-user doesn't need to know about it",
"Never, its better to share code!"
]
}

View File

@@ -0,0 +1,50 @@
# Clean Packages
Ive often seen, and have been responsible for, throwing code into packages without much thought. Ive quickly drawn a line in the sand and started putting code into different folders (which in Go are different packages by definition) just for the sake of findability. Learning to properly build small and reusable packages can take your Go career to the next level.
## Rules Of Thumb
### 1. Hide internal logic
If you're familiar with the pillars of OOP, this is a practice in *encapsulation*.
Oftentimes an application will have complex logic that requires a lot of code. In almost every case the logic that the application cares about can be exposed via an API, and most of the dirty work can be kept within a package. For example, imagine we are building an application that needs to classify images. We could build a package:
```go
package classifier
// ClassifyImage classifies images as "hotdog" or "not hotdog"
func ClassifyImage(image []byte) (imageType string) {
return hasHotdogColors(image) && hasHotdogShape(image)
}
func hasHotdogShape(image []byte) bool {
// internal logic that the application doesn't need to know about
return true
}
func hasHotdogColors(image []byte) bool {
// internal logic that the application doesn't need to know about
return true
}
```
We create an API by only exposing the function(s) that the application-level needs to know about. All other logic is unexported to keep a clean separation of concerns. The application doesnt need to know how to classify an image, just the result of the classification.
### 2. Dont change APIs
The unexported functions within a package can and should change often for testing, refactoring, and bug fixing.
A well-designed library will have a stable API so that users arent receiving breaking changes each time they update the package version. In Go, this means not changing exported functions signatures.
### 3. Dont export functions from the main package
A `main` package isn't a library, there's no need to export functions from it.
### 4. Packages shouldn't know about dependents
Perhaps one of the most important and most broken rules is that a package shouldnt know anything about its dependents. In other words, a package should never have specific knowledge about a particular application that uses it.
## Further Reading
You can optionally [read more here](https://blog.boot.dev/golang/how-to-separate-library-packages-in-go/) if you're interested.

View File

@@ -0,0 +1,8 @@
{
"question": "Should you often change a package's exported API?",
"answers": [
"No, try to keep changes to internal functionality",
"Yes, move fast and break things",
"If the package is 'main' then yes"
]
}

View File

@@ -0,0 +1,52 @@
# Clean Packages
Ive often seen, and have been responsible for, throwing code into packages without much thought. Ive quickly drawn a line in the sand and started putting code into different folders (which in Go are different packages by definition) just for the sake of findability. Learning to properly build small and reusable packages can take your Go career to the next level.
## Rules Of Thumb
### 1. Hide internal logic
If you're familiar with the pillars of OOP, this is a practice in *encapsulation*.
Oftentimes an application will have complex logic that requires a lot of code. In almost every case the logic that the application cares about can be exposed via an API, and most of the dirty work can be kept within a package. For example, imagine we are building an application that needs to classify images. We could build a package:
```go
package classifier
// ClassifyImage classifies images as "hotdog" or "not hotdog"
func ClassifyImage(image []byte) (imageType string) {
return hasHotdogColors(image) && hasHotdogShape(image)
}
func hasHotdogShape(image []byte) bool {
// internal logic that the application doesn't need to know about
return true
}
func hasHotdogColors(image []byte) bool {
// internal logic that the application doesn't need to know about
return true
}
```
We create an API by only exposing the function(s) that the application level needs to know about. All other logic is unexported to keep a clean separation of concerns. The application doesnt need to know how to classify an image, just the result of the classification.
### 2. Dont change APIs
The unexported functions within a package can and should change often for testing, refactoring, and bug fixing.
A well-designed library will have a stable API so that users arent receive breaking changes each time they update the package version. In Go, this means not changing exported functions signatures. If you *must* make breaking changes, then you should use [semantic versioning](https://semver.org/) to communicate the changes to your users by bumping the major version.
For example `v1.0.0` -> `v2.0.0`
### 3. Dont export functions from the main package
A `main` package isn't a library, there's no need to export functions from it.
### 4. Packages shouldn't know about dependents
Perhaps one of the most important and most broken rules is that a package shouldnt know anything about its dependents. In other words, a package should never have specific knowledge about a particular application that uses it.
## Further Reading
You can optionally [read more here](https://blog.boot.dev/golang/how-to-separate-library-packages-in-go/) if you're interested.

View File

@@ -0,0 +1,9 @@
{
"question": "What would be the conventional package name of a package with the path github.com/wagslane/parser?",
"answers": [
"parser",
"wagslane",
"go-parser",
"github.com"
]
}

View File

@@ -0,0 +1,21 @@
# Package Naming
## Naming Convention
By *convention*, a package's name is the same as the last element of its import path. For instance, the `math/rand` package comprises files that begin with:
```go
package rand
```
That said, package names aren't *required* to match their import path. For example, I could write a new package with the path `github.com/mailio/rand` and name the package `random`:
```go
package random
```
While the above is possible, it is discouraged for the sake of consistency.
## One Package / Directory
A directory of Go code can have **at most** one package. All `.go` files in a single directory must all belong to the same package. If they don't an error will be thrown by the compiler. This is true for main and library packages alike.

View File

@@ -0,0 +1,10 @@
{
"question": "Given the import path of path/to/rand, which of these is a valid package name?",
"answers": [
"Any of these",
"path",
"rand",
"random",
"spam"
]
}

View File

@@ -0,0 +1,21 @@
# Package Naming
## Naming Convention
By *convention*, a package's name is the same as the last element of its import path. For instance, the `math/rand` package comprises files that begin with:
```go
package rand
```
That said, package names aren't *required* to match their import path. For example, I could write a new package with the path `github.com/mailio/rand` and name the package `random`:
```go
package random
```
While the above is possible, it is discouraged for the sake of consistency.
## One Package / Directory
A directory of Go code can have **at most** one package. All `.go` files in a single directory must all belong to the same package. If they don't an error will be thrown by the compiler. This is true for main and library packages alike.

View File

@@ -0,0 +1,8 @@
{
"question": "What does the 'go version' command print?",
"answers": [
"go version {version} {os}/{architecture}",
"go version {os}/{architecture} {version}",
"{version} {os}/{architecture}"
]
}

View File

@@ -0,0 +1,32 @@
# About this chapter
Our courses can be completed *almost* completely in the browser, but there are some things that you need to do on your local machine for the sake of learning!
For the majority of this chapter, coding in the browser won't be useful because you need to learn how Go code is organized in a local development environment. We'll be explaining *how* to do this and quizzing you on it.
This section will almost entirely be quiz-style, with very little coding in the browser. As usual, if you get lost please use our discord channel as a resource:
[Discord Community](https://boot.dev/community)
## An example project to follow along with
If you get lost during this chapter, refer to this `src` folder of our "Social Media Server in Go" project that can be [found here](https://github.com/bootdotdev/projects/tree/main/projects/social-media-backend-golang/10-posts_endpoints/src). It will serve as a basic example of many of the concepts in this chapter.
## Unix
This guide will assume you are on a Unix environment like Linux or Mac. If you're on Windows you may have to do just a *bit* of Google-ing or ask in Discord to figure out how some commands translate to Windows.
If you are on Windows, I'd optionally recommend checking out [WSL (Windows Subsystem for Linux)](https://docs.microsoft.com/en-us/windows/wsl/install) so that you can work in a Unix environment on your local machine.
## Download Go locally
I typically recommend one of two ways:
* [Official Download](https://golang.org/doc/install)
* [Webi Downloader](https://webinstall.dev/golang/)
Make sure to use at least version `1.20`. This can be verified after installation by typing:
```bash
go version
```

View File

@@ -0,0 +1,9 @@
{
"question": "What is a Go module?",
"answers": [
"A collection of packages that are released together",
"A library package",
"An executable main package",
"A file of Go code"
]
}

View File

@@ -0,0 +1,33 @@
# Modules
Go programs are organized into *packages*. A package is a directory of Go code that's all compiled together. Functions, types, variables, and constants defined in one source file are visible to **all other source files within the same package (directory)**.
A *repository* contains one or more *modules*. A module is a collection of Go packages that are released together.
## A Go repository typically contains only one module, located at the root of the repository.
A file named `go.mod` at the root of a project declares the module. It contains:
* The module path
* The version of the Go language your project requires
* Optionally, any external package dependencies your project has
The module path is just the import path prefix for all packages within the module. Here's an example of a `go.mod` file:
```
module github.com/bootdotdev/exampleproject
go 1.20
require github.com/google/examplepackage v1.3.0
```
Each module's path not only serves as an import path prefix for the packages within but *also indicates where the go command should look to download it*. For example, to download the module `golang.org/x/tools`, the go command would consult the repository located at [https://golang.org/x/tools](https://golang.org/x/tools).
> An "import path" 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 `github.com/google/go-cmp` contains a package in the directory `cmp/`. That package's import path is `github.com/google/go-cmp/cmp`. Packages in the standard library do not have a module path prefix.
- Paraphrased from Golang.org's [code organization](https://golang.org/doc/code#Organization)
## Do I need to put my package on GitHub?
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 keep a copy of all your projects on a remote server, like GitHub.

View File

@@ -0,0 +1,7 @@
{
"question": "Do packages in the standard library have a module path prefix?",
"answers": [
"No",
"Yes"
]
}

View File

@@ -0,0 +1,33 @@
# Modules
Go programs are organized into *packages*. A package is a directory of Go code that's all compiled together. Functions, types, variables, and constants defined in one source file are visible to **all other source files within the same package (directory)**.
A *repository* contains one or more *modules*. A module is a collection of Go packages that are released together.
## A Go repository typically contains only one module, located at the root of the repository.
A file named `go.mod` at the root of a project declares the module. It contains:
* The module path
* The version of the Go language your project requires
* Optionally, any external package dependencies your project has
The module path is just the import path prefix for all packages within the module. Here's an example of a `go.mod` file:
```
module github.com/bootdotdev/exampleproject
go 1.20
require github.com/google/examplepackage v1.3.0
```
Each module's path not only serves as an import path prefix for the packages within but *also indicates where the go command should look to download it*. For example, to download the module `golang.org/x/tools`, the go command would consult the repository located at [https://golang.org/x/tools](https://golang.org/x/tools).
> An "import path" 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 `github.com/google/go-cmp` contains a package in the directory `cmp/`. That package's import path is `github.com/google/go-cmp/cmp`. Packages in the standard library do not have a module path prefix.
- Paraphrased from Golang.org's [code organization](https://golang.org/doc/code#Organization)
## Do I need to put my package on GitHub?
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 keep a copy of all your projects on a remote server, like GitHub.

View File

@@ -0,0 +1,8 @@
{
"question": "What is an import path?",
"answers": [
"A module path + package subdirectory",
"An HTTP connection",
"A RESTful server"
]
}

View File

@@ -0,0 +1,33 @@
# Modules
Go programs are organized into *packages*. A package is a directory of Go code that's all compiled together. Functions, types, variables, and constants defined in one source file are visible to **all other source files within the same package (directory)**.
A *repository* contains one or more *modules*. A module is a collection of Go packages that are released together.
## A Go repository typically contains only one module, located at the root of the repository.
A file named `go.mod` at the root of a project declares the module. It contains:
* The module path
* The version of the Go language your project requires
* Optionally, any external package dependencies your project has
The module path is just the import path prefix for all packages within the module. Here's an example of a `go.mod` file:
```
module github.com/bootdotdev/exampleproject
go 1.20
require github.com/google/examplepackage v1.3.0
```
Each module's path not only serves as an import path prefix for the packages within but *also indicates where the go command should look to download it*. For example, to download the module `golang.org/x/tools`, the go command would consult the repository located at [https://golang.org/x/tools](https://golang.org/x/tools).
> An "import path" 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 `github.com/google/go-cmp` contains a package in the directory `cmp/`. That package's import path is `github.com/google/go-cmp/cmp`. Packages in the standard library do not have a module path prefix.
- Paraphrased from Golang.org's [code organization](https://golang.org/doc/code#Organization)
## Do I need to put my package on GitHub?
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 keep a copy of all your projects on a remote server, like GitHub.

View File

@@ -0,0 +1,8 @@
{
"question": "Do you need to put your code inside of your GOPATH?",
"answers": [
"No, in fact you shouldn't",
"It doesn't matter",
"Yes"
]
}

View File

@@ -0,0 +1,23 @@
# Setting up your machine
Your machine will contain many version control *repositories* (managed by Git, for example).
Each repository contains one or more *packages*, but will typically be a single *module*.
Each package consists of one or more *Go source files* in a single directory.
The path to a package's directory determines its *import path* and where it can be downloaded from if you decide to host it on a remote version control system like Github or Gitlab.
## A note on GOPATH
The $GOPATH environment variable will be set by default somewhere on your machine (typically in the home directory, `~/go`). Since we will be working in the new "Go modules" setup, you *don't need to worry about that*. If you read something online about setting up your GOPATH, that documentation is probably out of date.
These days you should *avoid* working in the `$GOPATH/src` directory. Again, that's the old way of doing things and can cause unexpected issues, so better to just avoid it.
## Get into your workspace
Navigate to a location on your machine where you want to store some code. For example, I store all my code in `~/workspace`, then organize it into subfolders based on the remote location. For example,
`~/workspace/github.com/wagslane/go-password-validator` = [https://github.com/wagslane/go-password-validator](https://github.com/wagslane/go-password-validator)
That said, you can put your code wherever you want.

View File

@@ -0,0 +1,8 @@
{
"question": "Why does Go include a remote URL in module paths?",
"answers": [
"To simplify remote downloading of packages",
"To confuse new gophers",
"To ensure that developers are using source control"
]
}

View File

@@ -0,0 +1,22 @@
# First Local Program
Once inside your personal workspace, create a new directory and enter it:
```bash
mkdir hellogo
cd hellogo
```
Inside the directory declare your module's name:
```bash
go mod init {REMOTE}/{USERNAME}/hellogo
```
Where `{REMOTE}` is your preferred remote source provider (i.e. `github.com`) and `{USERNAME}` is your Git username. If you don't use a remote provider yet, just use `example.com/username/hellogo`
Print your `go.mod` file:
```bash
cat go.mod
```

View File

@@ -0,0 +1,7 @@
{
"question": "What is hellogo in our case?",
"answers": [
"The repository/directory name",
"The module path prefix"
]
}

View File

@@ -0,0 +1,22 @@
# First Local Program
Once inside your personal workspace, create a new directory and enter it:
```bash
mkdir hellogo
cd hellogo
```
Inside the directory declare your module's name:
```bash
go mod init {REMOTE}/{USERNAME}/hellogo
```
Where `{REMOTE}` is your preferred remote source provider (i.e. `github.com`) and `{USERNAME}` is your Git username. If you don't use a remote provider yet, just use `example.com/username/hellogo`
Print your `go.mod` file:
```bash
cat go.mod
```

View File

@@ -0,0 +1,8 @@
{
"question": "What does the first line of go.mod contain?",
"answers": [
"module {REMOTE}/{USERNAME}/hellogo",
"{REMOTE}/{USERNAME}/hellogo",
"module hellogo"
]
}

View File

@@ -0,0 +1,22 @@
# First Local Program
Once inside your personal workspace, create a new directory and enter it:
```bash
mkdir hellogo
cd hellogo
```
Inside the directory declare your module's name:
```bash
go mod init {REMOTE}/{USERNAME}/hellogo
```
Where `{REMOTE}` is your preferred remote source provider (i.e. `github.com`) and `{USERNAME}` is your Git username. If you don't use a remote provider yet, just use `example.com/username/hellogo`
Print your `go.mod` file:
```bash
cat go.mod
```

View File

@@ -0,0 +1,7 @@
{
"question": "Does 'go run' build a production executable?",
"answers": [
"No",
"Yes"
]
}

View File

@@ -0,0 +1,31 @@
# Go Run
Inside `hellogo`, create a new file called `main.go`.
Conventionally, the file in the `main` package that contains the `main()` function is called `main.go`.
Paste the following code into your file:
```go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
```
## Run the code
```bash
go run main.go
```
The `go run` command is used to quickly compile and run a Go package. The compiled binary is *not* saved in your working directory. Use `go build` instead to compile production executables.
I rarely use `go run` other than to quickly do some testing or debugging.
## Further reading
Execute `go help run` in your shell and read the instructions.

View File

@@ -0,0 +1,8 @@
{
"question": "Which can 'go run' accept as arguments?",
"answers": [
"Both",
"File names",
"Package names"
]
}

View File

@@ -0,0 +1,31 @@
# Go Run
Inside `hellogo`, create a new file called `main.go`.
Conventionally, the file in the `main` package that contains the `main()` function is called `main.go`.
Paste the following code into your file:
```go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
```
## Run the code
```bash
go run main.go
```
The `go run` command is used to quickly compile and run a Go package. The compiled binary is *not* saved in your working directory. Use `go build` instead to compile production executables.
I rarely use `go run` other than to quickly do some testing or debugging.
## Further reading
Execute `go help run` in your shell and read the instructions.

View File

@@ -0,0 +1,8 @@
{
"question": "What was created after running 'go build'?",
"answers": [
"An executable file named 'hellogo'",
"An executable file named main",
"A package named cmd"
]
}

View File

@@ -0,0 +1,17 @@
# Go Build
`go build` compiles go code into an executable program
## Build an executable
Ensure you are in your hellogo repo, then run:
```bash
go build
```
Run the new program:
```bash
./hellogo
```

View File

@@ -0,0 +1,8 @@
{
"question": "What happens when you run './hellogo'?",
"answers": [
"'hello world' is printed",
"The program panics",
"The code compiles"
]
}

View File

@@ -0,0 +1,17 @@
# Go Build
`go build` compiles go code into an executable program
## Build an executable
Ensure you are in your hellogo repo, then run:
```bash
go build
```
Run the new program:
```bash
./hellogo
```