Skip to content

posts🔗

Go R1 Day 25

Day 25 of 100

progress

  • Worked with Gorm, my first experience with ORM based querying.
  • Used gofakeit with gorm to connect to MSSQL Server in Docker and randomize name entries.
  • Learned a bit about Context package and how it helps with propagation of cancellation.
  • As a new user to this, the examples were very confusing as it mixed up go-mssqldb along with examples using just gorm. As I get better with it, I'll try to log better introductory examples.

Remove Chrome Autocomplete Suggestion

Do you have a Chrome suggestion for a domain, url, or specific site location that you don't want anymore?

You can remove an invalid suggestion that you don't want popping up each time by using shift+delete.

If it's the first entry it will remove it, or use arrow keys to highlight a different entry and press the same command.

Also relevant: To Delete Chrome Address Bar Suggestions with Mouse

Go R1 Day 24

Day 24 of 100

progress

  • Used glamour to render some nice console output.
  • Formatted text testing some text tooling.
  • Progressbar ui tested.
  • Connected successfully to MSSQL Docker instance and returned results of query, rendering to to console .

Go R1 Day 23

Day 23 of 100

progress

  • Used Viper to load configuration for a CLI tool.
  • Ran into problems with trying to print out map[string]interface{} type. Lots of magic performed by .NET to do this type of action. This is a lot more hands-on 😁.
  • Had stability issues with VSCode today, so I finally switched over to Intellij with the Go plugin and it worked well. The keyboard mappings are different so that was painful, but still overall a good experience that got me unblocked.

Experiments With Go Arrays and Slices

Simplicity Over Syntactic Sugar

As I've been learning Go, I've grown to learn that many decisions to simplify the language have removed many features that provide more succinct expressions in languages such as Python, PowerShell, C#, and others. The non-orthogonal features in the languages result in many expressive ways something can be done, but at a cost, according to Go's paradigm.

My background is also heavily focused in relational databases and set based work, so I'm realizing as I study more programming paradigms seperate from any database involvement, that it's a fundamental difference in the way a database developer and a normal developer writing backend code look at this. Rather than declarative based syntax, you need to focus a lot more on iterating through collections and manipulating these.

As I explored my assumptions, I found that even in .NET Linq expressions are abstracting the same basic concept of loops and iterations away for simpler syntax, but not fundamentally doing true set selections. In fact, in some cases I've read that Linq performance is often worse than a simple loop (see this interesting stack overflow answer) The catch to this is that the Linq expression might be more maintainable in an enterprise environment at the cost of some degraded performance (excluding some scenarios like deferred execution).

For example, in PowerShell, you can work with arrays in a multitude of ways.

$array[4..10] | ForEach-Object {}
# or
foreach($item in $array[$start..$end]){}

This syntactic sugar provides brevity, but as two ways among many I can think of this does add such a variety of ways and performance considerations. Go strips this cognitive load away by giving only a few ways to do the same thing.

Using For Loop

This example is just int slices, but I'm trying to understand the options as I range through a struct as well.

When working through these examples for this question, I discovered thanks to the Rubber Duck debugging, that you can simplify slice selection using newSlice := arr[2:5].

Simple Loop

As an example: Goplay Link To Run

package main
import "fmt"

func main() {
    startIndex := 2
    itemsToSelect := 3
    arr := []int{10, 15, 20, 25, 35, 45, 50}
    fmt.Printf("starting: arr: %v\n", arr)

    newCollection := []int{}
    fmt.Printf("initialized newCollection: %v\n", newCollection)
    for i := 0; i < itemsToSelect; i++ {
        newCollection = append(newCollection, arr[i+startIndex])
        fmt.Printf("\tnewCollection: %v\n", newCollection)
    }
    fmt.Printf("= newCollection: %v\n", newCollection)
    fmt.Print("expected: 20, 25, 35\n")
}```

This would result in:

```text
starting: arr: [10 15 20 25 35 45 50]
initialized newCollection: []
    newCollection: [20]
    newCollection: [20 25]
    newCollection: [20 25 35]
= newCollection: [20 25 35]
expected: 20, 25, 35

Moving Loop to a Function

Assuming there are no more effective selection libraries in Go, I'm assuming I'd write functions for this behavior such as Goplay Link To Run.

package main

import "fmt"

func main() {
    startIndex := 2
    itemsToSelect := 3
    arr := []int{10, 15, 20, 25, 35, 45, 50}
    fmt.Printf("starting: arr: %v\n", arr)
    newCollection := GetSubselection(arr, startIndex, itemsToSelect)
    fmt.Printf("GetSubselection returned: %v\n", newCollection)
    fmt.Print("expected: 20, 25, 35\n")
}

func GetSubselection(arr []int, startIndex int, itemsToSelect int) (newSlice []int) {
    fmt.Printf("newSlice: %v\n", newSlice)
    for i := 0; i < itemsToSelect; i++ {
        newSlice = append(newSlice, arr[i+startIndex])
        fmt.Printf("\tnewSlice: %v\n", newSlice)
    }
    fmt.Printf("= newSlice: %v\n", newSlice)
    return newSlice
}

which results in:

starting: arr: [10 15 20 25 35 45 50]
newSlice: []
    newSlice: [20]
    newSlice: [20 25]
    newSlice: [20 25 35]
= newSlice: [20 25 35]
GetSubselection returned: [20 25 35]
expected: 20, 25, 35

Trimming this down further I found I could use the slice syntax (assuming the consecutive range of values) such as: Goplay Link To Run

func GetSubselection(arr []int, startIndex int, itemsToSelect int) (newSlice []int) {
    fmt.Printf("newSlice: %v\n", newSlice)
    newSlice = arr[startIndex:(startIndex + itemsToSelect)]
    fmt.Printf("\tnewSlice: %v\n", newSlice)
    fmt.Printf("= newSlice: %v\n", newSlice)
    return newSlice
}

Range

The range expression gives you both the index and value, and it works for maps and structs as well.

Turns outs you can also work with a subselection of a slice in the range expression.

package main

import "fmt"

func main() {
    startIndex := 2
    itemsToSelect := 3
    arr := []int{10, 15, 20, 25, 35, 45, 50}
    fmt.Printf("starting: arr: %v\n", arr)

    fmt.Printf("Use range to iterate through arr[%d:(%d + %d)]\n", startIndex, startIndex, itemsToSelect)
    for i, v := range arr[startIndex:(startIndex + itemsToSelect)] {
        fmt.Printf("\ti: %d v: %d\n", i, v)
    }
    fmt.Print("expected: 20, 25, 35\n")
}

Slices

While the language is simple, understanding some behaviors with slices caught me off-guard.

First, I needed to clarify my language. Since I was looking to have a subset of an array, slices were the correct choice. For a fixed set with no changes, a standard array would be used.

Tour On Go says it well with:

An array has a fixed size. A slice, on the other hand, is a dynamically-sized, flexible view into the elements of an array. In practice, slices are much more common than arrays.

For instance, I tried to think of what I would do to scale performance on a larger array, so I used a pointer to my int array. However, I was using a slice.

This means that using a pointer wasn't valid. This is because whenever I pass the slice it is a pass by reference already, unlike many of the other types.

newCollection := GetSubSelection(&arr,2,3)

func GetSubSelection(arr *[]int){ ...

I think some of these behaviors aren't quite intuitive to a new Gopher, but writing them out helped clarify the behavior a little more.

Resources

This is a bit of a rambling about what I learned so I could solidify some of these discoveries by writing them down. #learninpublic

For some great examples, look at some examples in:

If you have any insights, feel free to drop a comment here (it's just a GitHub powered comment system, no new account required).

Go R1 Day 22

Day 22 of 100

progress

Using Dash, I read through much of the language specification. Dry reading for sure, but helped a bit in understanding a little more on stuff like arrays, slices, loops, etc.

Nothing profound to add, except to say I don't think I want to write a language specification.

Go R1 Day 21

Day 21 of 100

progress

  • Signed up for exercism.io, which is a pretty great website to work through progressively harder exercises.
  • Did Hello world to start with as requires progressive steps through the exercises.
  • Did a string concatenation exercise as well (Two Fer).

I like the mentor feedback system concept and submission of work. After I finish this, would be good to add myself as a mentor and contribute back to this community. This is a fantastic concept to help get acclimated to a new language and do progressively harder exercises to better learn the language usage.