Skip to content

2020🔗

Go R1 Day 8

Day 8 of 100

progress

  • Worked through Algorithms in Go: Determine if a number is in a list
  • Passed the tests without needing to find the solution, so that's a win.
  • Had to remember to grab the second value from the range operator like for _, i := range items instead of using foreach($i in $items) like PowerShell would do. It's more similar to using hashtables with GetEnumerator().
  • Used codespaces with Docker and also experimented with WSL2 and Visual Studio Code mounting the directory from inside WSL2.

Terraform's Elegance in Abstraction

Migrated a forked copy of a module over to a new module with similar schema. There were some additional properties that were removed. In rerunning the plan I was expecting to see some issues with resources being broken down and rebuilt. Instead, Terraform elegantly handled the module change.

I imagine this has to do with the resource name mapping being the same, but regardless it's another great example of how agile Terraform can be.

Reflections on Being a New Gopher With A Dotnet Background

Disclaimer

Newbie Gopher. Much of what I observe is likely to be half right. I'll probably look back at the end of the year and shake my head, but gotta start the journey somewhere, right? 😁

My Background

I've learned my development skills primarily in the dotnet world. Coming from SQL Server performance, schema, and development, I transitioned into learning PowerShell and some C#. I found for the most part the "DevOps" nature of what I was doing wasn't a good fit for focusing on C# and so have done the majority of my development in PowerShell.

For those unfamilar with PowerShell, I highly recommend it as a fantastic shell experience and as a great ecosystem for automation oriented programming.

With everything as an "object" in PowerShell, not only does the manipulation of those objects tend to be pretty flexible, but built in methods, properties, and deep diving into object collections in objection collections provide powerful control of working with things like AWS.Tool.SDK and Windows.

Why I Started With Go

I wanted to focus on Python, as I think it's a beautiful language and I'd probably be more productive quickly in it. However, as I started my Python journey I discovered that I was basically substituting PowerShell (my goto) with a language that in many ways was very similar.

Python provides a "glue" language that can do many things, in many varying domains with a vast ecosystem of user built modules.

So why Go?

Primarily, I wanted 2 main things from my next step:

  • Expand my horizons with a language that approached things differently than what I'm used to, forcing me to solve problems in a new way, not just a simple syntax shift.
  • Try something that was more strictly typed and opinionated to help align my next development to be less "adhoc" but more robust.

Some additional perks would be: choosing a language that made me more competitive in the market (so choosing low adoption languages), immersed me more in Linux while still supporting cross platform work, and additionally supported quick adhoc tooling to be able to deliver small portable tooling to help support a DevOps culture.

Is it better than x

No. It's not "better" than PowerShell, C#, Python, or even Bash.

That's an incomplete way to consider this, just like saying your hammer is better than a screwdriver or replaces the need for a table saw. 😁

How It's Helping Me Think Differently

What I find myself observing is it is accomplishing one of my primary objectives of thinking differently.

Interfaces

Interfaces are something I've rarely used, as I'm not doing much C#, but when I had used this it seemed to be extra work for the the sack of good design and abstraction of implementation. Since, most of my development was automation oriented, I had little case for regularly using them.

Bytes

Bytes are something I've rarely had to work with, as it's abstracted in PowerShell. However, in Go, bytes seem to be a universal medium.

Let's say I need to run a web request for gathering some results in json and manipulating then. With PowerShell a simple rest call with ConvertFrom-Json is all that is required. With Go, you have to convert the bytes and use json.Unmarshal as one way to take the response and place the response into a predefined struct (or empty struct is possible as well I believe)

Want to deal with images, files, web requests, and more... bytes. Endless streams of bytes.

Dotnet Types

Say, I want to work with a semver version number. This is provided in the standard System library in C#, and also accessible via a type accelerator in PowerShell.

$ver = [System.Version]::new()
[System.Version]::TryParse($ParseMe,[ref]$ver) # Returned bool success/fail
Write-Host $ParseMe

In Go, this wouldn't be part of the standard library (at least from what I've found). Instead, you'd get the same essential functionality by finding a package like: go-version and using it.

Instead of a class object being returned, such as shown about with PowerShell, you'd have structs returned.

Where [pscustomobject]@{}| Get-Member would report back the .NET type of System.Management.Automation.PSCustomObject, running reflection against something go.

From go-version

// Version represents a single version.
type Version struct {
    metadata string
    pre      string
    segments []int64
    si       int
    original string
}

This would be basically the new Type that I'd expect to see in Go.

Last Thoughts

I'm really enjoying the experience of looking at things from a new perspective and doing my best to keep an open mind to learn Go without prejudice to force it to my way of thinking.

So far it has been interesting and probably harder initially because my paradigm has come from the dotnet ecosystem. Removing dotnet from the equation, it's interesting to see how much I take for granted.

I think if I had been immersed in Python from the beginning, transitioning to Go would be more intuitive to me. When I was juggling C# and PowerShell, I found it very intuitive as most of the basics were just syntax differences, until you added in more complex things like Linq/Delegates, abstract classes, interfaces, and other things that don't have quite the place in the PowerShell world.

The generalization of "everything is an object" in Windows vs in Linux "everything is a file/text" rings true in the approach I think I've observed underlying the way the languages function.

Give Something New A Shot

If you are from a Linux background, I'd suggest you give PowerShell a shot (its cross platform now) and try this experience of learning a new paradigm. Using something like InvokeBuild will give you a much richer experience than Make files. If from Windows, then Python or Go would be a great choice to help challenge you.

Give Yourself Time To Be Terrible At It

I read recently from @Duffney:

My biggest challenge with using the 20 hours rule to learn new things is becoming comfortable being "unproductive"

I think that was a very freeing concept, as I've wrestled with this. Being pretty experienced in PowerShell, being ok writing non-idiomatic Go code with rough project structure, limited tests, and more has been mentally inhibiting.

It's always better to get momentum on something and once competence is growing, challenge yourself to excel with more idomatic, tested, and well designed solutions. Build and ship some stuff so you can even get to the place where you wince at your old work in the first place 😆

Go R1 Day 7

Day 7 of 100

progress

  • Successfully deployed lambda to AWS
  • Figured out how to return value cleanly from AWS Lambda vs the log output.

Go R1 Day 6

Day 6 of 100

progress

  • Learned a little on bubble sort algorithm
  • Edited aws-go lambda tests
  • Used debugger a bit more to look at error return values on failure

Rebuild Dash Index Due to Corrupted Index

I use Dash for improved doc access. Terraform updated recently to 0.13.x and I began having odd issues with AWS provider results coming through. If you need to rollback, just go to the preferences and pick an older docset, in my case 0.13.0 worked correctly. Make sure to remove the problematic version (the uninstall refers to just the most recent, not any additional versions you selected under the dropdown)

If the index doesn't rebuild, you can close the app, manually remove the index, and it will rebuild on open. I'm pretty sure you don't need to do this if you use the uninstall option in the dialogue.

On macOS 10.15, you can find the index at ~/Library/Application Support/Dash/Data/manIndex.dsidx and delete this. Reopen Dash and it will rebuild the index.

Incredible setup experience with gitpod

What a polished setup experience from gitpod. Super impressed as I've never seen an interactive terraform setup asking for user input.

This basically generated an entire setup for GitPod, and persisted the Terraform plan for the entire stack it created in a directory for management and adjustments as desired.

I'm seriously impressed.

Check this out at: Install on AWS

# Setup Gitpod with self-setup docker installer
# https://www.gitpod.io/docs/self-hosted/latest/install/install-on-aws-script/
# Set-Location ./terraform/gitpod

Import-Module aws.tools.common, aws.tools.SecurityToken

Set-AWSCredential -ProfileName 'MyProfileName' -Scope Global

$ENV:AWS_ACCESS_KEY_ID = $cred.GetCredentials().AccessKey
$ENV:AWS_SECRET_ACCESS_KEY = $cred.GetCredentials().SecretKey
$ENV:AWS_DEFAULT_REGION = 'eu-west-1'

# can't use STS temporary credentials to create iam resources, so use normal iam credentials
docker run --rm -it -e AWS_ACCESS_KEY_ID=$ENV:AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY=$ENV:AWS_SECRET_ACCESS_KEY -e AWS_DEFAULT_REGION=$ENV:AWS_DEFAULT_REGION `
-v ${PWD}/awsinstall:/workspace eu.gcr.io/gitpod-io/self-hosted/installer:latest aws

Go R1 Day 5

Day 5 of 100

progress

  • I created my first unit test for go
  • It's a bit interesting coming from a background with PowerShell and Pester as my primary unit test framework. For instance, in Pester you'd declare the anything, but autodiscovery works with *.tests.ps1, being the normal convention.
  • There is no pointer value providing the test package, it's just other PowerShell calling PowerShell.
  • I'm biased I know, but the first test condition being like below seems clunky. I was hoping for something that was more like Pester with test.Equals(got, want,"Error message") as the syntax is more inline to what I'd expect. I haven't dived in further so this is just a thought, hoping this is just the newbie 101 test case example and there are more succinct comparison and test methods available.
package main

import "testing"

func TestHello(t *testing.T) {
    got := Hello()
    want := "Hello, world"
    if got != want {
        t.Errorf("got %q want %q", got, want)
    }
}
  • Update: 2020-08-24 2020-08-24
  • I'll stick with the default package while I'm learning. However, there is a package called Testify that is worth exploring if I find I still want assertions later on.

Go R1 Day 4

Day 4 of 100

progress

  • In the last week some more Pluralsight Go (Nigel's courses are always stellar)
  • I've done some odd work as had time in between last update, but nothing structured. Might continue with learn-go-with-tests but also came across exercism and might tackle that soon as well.
  • Setup new project in Visual Studio Codespaces
  • Used Serverless Framework to generate aws-go template project
  • Imported aws-go-sdk resources for AWS SSM Secrets Manager
  • Grabbed SSM Secrets manager output and used to create a POST request for authorization token
  • Used DumpRequest to pretty print output for debugging purpose
  • Hung my head in shame at my copy pasta project 😀
  • Realized half of the battle is just getting my lambda debugging effort running locally. Not exactly the easiest starter project.
  • Need to master different request types. PowerShell makes this easy with Invoke-RestMethod and object construction. I found that the Post method wasn't appropriate as I wanted to control custom headers. This required me to use a different approach, which I ended up doing with http.Client{}.
  • Not sure in a Go Playground sample to test and echo a post request. Thinking if no service that does this might try creating a Go routine to accept the request locally and echo for the purpose of a demo. Any suggestions welcome.
  • Identified i really need better understanding of the godoc libraries as would help a lot. Vscode intellisense even in codespaces isn't performing great, so I'm not getting that help that would really expedite discovery as a beginner. I might give my EAP Goland install a try and see if it helps.
  • Successfully included zap logging library
  • Successfully submitted request for authorization token and got response back into a struct, something that as a newbie I found a major win 🎉 using json.Unmarshal([]byte(body), ar) with ar referring to a pointer another win for me as new to pointers) being passed in like below:
// AuthResponse the authorization object returned by taco service when doing fancy things
type AuthResponse struct {
    MagicalToken string `json:"magical_token"`
    ExpiresIn    int    `json:"expires_in"`
}

func main() {
    var ar AuthResponse
    getToken(&ar) // pointer for the win ⚡️
}
func getToken(ar *AuthResponse) {
    json.Unmarshal([]byte(body), ar) // ❓ using bytes for json is new to me. gotta learn more
    sugar.Infow("Logging library with zap used to generate structured logs",
    "authResponse", ar,  // trailing quotes is the norm, also a new pattern for me
)
}