I [always wanted](https://aikchar.me/blog/vision-2020.html) to spend more time learning Go. After a long break I finally got a chance to take it up seriously. The best lesson for me was to not learn it from scratch like I did with my first programming language. I learned a few basics first from the official documentation and [Learn Go Programming - Golang Tutorial for Beginners](https://youtu.be/YS4e4q9oBaU). Since I'm already well experienced in writing good sized code bases in Python, I decided to dive right in and implement a project on top of [Azure SDK](https://docs.microsoft.com/en-us/azure/developer/go/management-libraries). One big advantage of this approach was that I could learn from working examples in Azure documentation and build my knowledge over time. The second advantage was that I was building something useful right away that kept my motivation up; I wasn't building some abstract thing where I also needed to conjure a problem and solution. This post is still a work in progress. I'll update it as I go along. [TOC] # Companion git Repo This blog post has a companion git repo: [https://github.com/aikchar/learngo](https://github.com/aikchar/learngo). There are multiple checkpoints in this post. Each checkpoint has a corresponding branch in the repo. As you follow along the post you can checkout the checkpoint branch and inspect it. # Initial Setup The best place to start: - [https://golang.org/doc/install](https://golang.org/doc/install) - [https://golang.org/doc/code](https://golang.org/doc/code) # Incremental Learning Some tricks I use as I learn Go, its type system, etc. I use Visual Studio Code with the Go extension. By hovering the mouse over a function from a library, such as Azure SDK, I can click the documentation link that pops up right above it. It's a life saver. Visual Studio Code also automatically add the `import` line as soon as I start using the function from that library. It's really neat. When I'm unsure of the data type, I print it with `fmt.Printf("%s", myvar)`. The compiler yells at me that the data type is not a string and outputs the real data type. # Organize Code I'm still learning how to do this. This is what I know so far. Figure out the "_namespace_" and _name_ of the project. For example, my namespace is _github.com/aikchar_ and name is _learngo_. The full name, or the import path, is _github.com/aikchar/learngo_. Create a directory of the same name to make things easier. $ mkdir -p ~/repos/github.com/aikchar/learngo I usually put my repos under ~/repos so that's what I did here. You can use whichever parent directory you prefer. Create packages in sub-directories of the root directory. For example, $ mkdir -p ~/repos/github.com/aikchar/learngo/mypkg1 $ mkdir -p ~/repos/github.com/aikchar/learngo/mypkg2 Create your main file, with `package main` and `func main()`, in the root directory. You don't have to call it _main.go_ but it's easier to identify. $ touch ~/repos/github.com/aikchar/learngo/main.go From here on assume we're always in the ~/repos/github.com/aikchar/learngo directory unless otherwise stated. # Modules Initialize your _go.mod_ first. $ go mod init github.com/aikchar/learngo More information: - [Tutorial: Create a Go module](https://golang.org/doc/tutorial/create-module) - [EVERYTHING You SHOULD know about Go Modules (Go Basics #8)](https://www.youtube.com/watch?v=Z1VhG7cf83M) # Dependencies Change to your project's directory and fetch your first dependency. In my case it was the Azure SDK. I fetched two different authentication libraries below. $ go get github.com/Azure/azure-sdk-for-go/sdk/azidentity # Newer $ go get github.com/Azure/go-autorest/autorest/azure/auth # Older If you already have the dependency downloaded in some other path, you can alias the official import path with your local path. This uses the `replace` keyword. You can also _vendor_ Azure SDK. It means that you maintain a copy of it in your own source tree. It removes the need to fetch it everytime you need to build your project on a new machine; it's always right there along with your code. It's optional so you decide if you want to do this. $ go mod vendor If you don't use a dependency in your code, you can _remove_ depdencies automatically. This can be tricky because if you previously `go get` that dependency it will be removed from _go.mod_. Use this carefully. Most people use it before they commit their changes. $ go mod tidy Since we are not using any dependencies yet, let's remove Azure SDK. Run, $ go mod tidy More information: - [How to use local go modules with golang with examples](https://brokencode.io/how-to-use-local-go-modules-with-golang-with-examples/) - [SIV and the V2+ issue](https://changelog.com/gotime/188) # main.go First Draft Let's create a skeleton `main.go`. $ vim main.go package main func main(){} Here we'll also try `go fmt` for the first time. This will format our code according to community standards. $ go fmt # Build Building is also easy. $ go build This will create a static binary with the same name as the parent directory. In my case it's _learngo_. $ ls go.mod go.sum learngo main.go # Checkpoint 1 This is our first checkpoint. You can clone [https://github.com/aikchar/learngo](https://github.com/aikchar/learngo) and checkout branch cp-1. $ git clone https://github.com/aikchar/learngo.git $ git checkout -t origin/cp-1 I will not include binaries in the repo. For example, you won't see the _learngo_ file. # Test TBD # Release - [Module release and versioning workflow](https://golang.org/doc/modules/release-workflow)