{"id":18876462,"url":"https://github.com/meleu/learning-golang","last_synced_at":"2026-02-18T12:30:17.921Z","repository":{"id":63718813,"uuid":"569501092","full_name":"meleu/learning-golang","owner":"meleu","description":"Learning Go with tests, from https://quii.gitbook.io/learn-go-with-tests","archived":false,"fork":false,"pushed_at":"2024-06-02T21:55:05.000Z","size":19,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-31T02:13:20.142Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meleu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-23T01:01:27.000Z","updated_at":"2024-06-02T21:55:09.000Z","dependencies_parsed_at":"2024-06-02T19:09:55.397Z","dependency_job_id":"691e04bd-a9df-4391-9bcb-ec79e2490052","html_url":"https://github.com/meleu/learning-golang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meleu%2Flearning-golang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meleu%2Flearning-golang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meleu%2Flearning-golang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meleu%2Flearning-golang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meleu","download_url":"https://codeload.github.com/meleu/learning-golang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239832475,"owners_count":19704607,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T06:13:14.127Z","updated_at":"2026-02-18T12:30:17.853Z","avatar_url":"https://github.com/meleu.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Learning Golang\n\nFollowing the [Learn Go with tests](https://quii.gitbook.io/learn-go-with-tests/) gitbook.\n\nHere I list some things I learned in each exercise.\n\n## Hello, World\n\n- \u003chttps://quii.gitbook.io/learn-go-with-tests/go-fundamentals/hello-world\u003e\n\n### What I learned\n\n#### Golang tooling\n\nStart a new project as a module with:\n\n```bash\nmkdir hello\ncd hello\ngo mod init hello\n# check if the \"go.mod\" file was created\n```\n\nRecommended linter: [GolangCI-Lint](https://golangci-lint.run/). It can be installed with Homebrew or `asdf` (I used `asdf`).\n\nUseful config to be used in VSCode:\n\n```json\n{\n  \"go.lintTool\": \"golangci-lint\",\n  \"go.lintFlags\": [\"--fast\"],\n  \"go.coverOnSave\": true,\n  \"go.coverageDecorator\": {\n    \"type\": \"gutter\",\n    \"coveredHighlightColor\": \"rgba(64,128,128,0.5)\",\n    \"uncoveredHighlightColor\": \"rgba(128,64,64,0.25)\",\n    \"coveredGutterStyle\": \"blockgreen\",\n    \"uncoveredGutterStyle\": \"slashred\"\n  }\n}\n```\n\nAwesome tool to rerun tests on file change: [watchexec](https://github.com/watchexec/watchexec). Example of usage:\n\n```bash\n# run 'go test' when a change happens on a file ending with .go\nwatchexec -e go -- go test -v\n```\n\nLocal documentation:\n\n```bash\n# installing local documentation\ngo install golang.org/x/tools/cmd/godoc@latest\n\n# NOTE: sometimes godoc won't be in your path.\n# in my case it went to `~/.asdf/` structure and I created an alias:\nalias godoc=$(find $HOME/.asdf/installs/golang -type f -path '*packages/bin/godoc')\n\n# now you can launch the local documentation server\ngodoc -http :8000\n```\n\n#### Golang basics\n\n- a program have a `main` package defined with a `main` func inside.\n- `func` defines a function with a name and a body (aka block)\n- blocks are defined with `{`curly braces`}`\n- `import \"fmt\"` is necessary to use `fmt.Println`\n- `if` works like other programming languages, without `(`parenthesis`)`\n- variables are ~~assigned~~ declared like this: `varName := value`\n  - I [researched](https://stackoverflow.com/a/36513229/6354514) and realized that\n    - `:=` for [short variable declarations](https://go.dev/ref/spec#Short_variable_declarations) (with type inference)\n    - `=` for [variable declarations](https://go.dev/ref/spec#Variable_declarations) and [assignments](https://go.dev/ref/spec#Assignment_statements).\n- constants are defined like `const myConst = \"My String\"`\n- `PublicFunctions` start with a capital letter and `privateFunctions` start with a lowercase.\n- `func greetingPrefix(language string) (prefix string)` creates a **named return value**\n  - creates a variable called `prefix` in the function\n  - it will be assigned the \"zero\" value. In this case (`string`): `\"\"`\n  - example (also showing a `switch` statement):\n\n```go\nfunc greetingPrefix(language string) (prefix string) {\n\tswitch language {\n\tcase spanish:\n\t\tprefix = spanishHelloPrefix\n\tcase french:\n\t\tprefix = frenchHelloPrefix\n\tcase portuguese:\n\t\tprefix = portugueseHelloPrefix\n\tdefault:\n\t\tprefix = englishHelloPrefix\n\t}\n\treturn\n}\n```\n\n- example of grouping constants:\n\n```go\nconst (\n\tspanish    = \"Spanish\"\n\tfrench     = \"French\"\n\tportuguese = \"Portuguese\"\n\n\tenglishHelloPrefix    = \"Hello, \"\n\tspanishHelloPrefix    = \"Hola, \"\n\tfrenchHelloPrefix     = \"Bonjour, \"\n\tportugueseHelloPrefix = \"Olá, \"\n)\n```\n\n#### Golang testing\n\n- file name must be `${something}_test.go`\n- `import \"testing\"`\n- the test function must start with `Test`\n- test function takes only one argument `t *testing.T` (it's your \"hook\" into the testing framework)\n- `t.Errorf` prints a message when a test fails.\n- `%q` means \"string surrounded with double quotes\", in the string format context\n- subtests go in `t.Run(\"test name\", testFunction)`. Example:\n\n```go\nfunc TestHello(t *testing.T) {\n  // 👇 t.Run(testName, testFunction)\n\tt.Run(\"say hello to people\", func(t *testing.T) {\n\t\tactual := Hello(\"Chris\")\n\t\texpected := \"Hello, Chris!\"\n\t\tassertCorrectMessage(t, actual, expected)\n\t})\n\n  // 👇 t.Run(testName, testFunction)\n\tt.Run(\"say 'Hello, World!' when passing empty string\", func(t *testing.T) {\n\t\tactual := Hello(\"\")\n\t\texpected := \"Hello, World!\"\n\t\tassertCorrectMessage(t, actual, expected)\n\t})\n}\n\n// comments about this helper function right after this codeblock\nfunc assertCorrectMessage(t testing.TB, actual, expected string) {\n\tt.Helper() // \u003c-- pra que isso?\n\tif actual != expected {\n\t\tt.Errorf(\"expected: %q; actual: %q\", expected, actual)\n\t}\n}\n```\n\n- For helper functions, accept `testing.TB` is a good idea.\n- `t.Helper` is needed to report the caller line number when the test fails\n  (not the line number in the helper function)\n\n## Integers\n\n### Testable Examples\n\n[Official article](https://go.dev/blog/examples).\n\nHere's an example:\n\n```go\nfunc ExampleAdd() {\n\tsum := Add(1, 5)\n\tfmt.Println(sum)\n\t// Output: 6\n}\n```\n\nThe special comment `// Output: 6` makes the example to be executed.\n\nThis example also goes to the documentation of your package. You can check by\nrunning `godoc -http :8000` and looking for the `Integers` package.\n\n## Iteration\n\n### Golang\n\nIn Go you iterate using `for`. There are **no** `while`, `do`, `until` keywords.\n\nIt's usually used like other C-like languages:\n\n```go\nfor i := 0; i \u003c 5; i++ {\n\trepeated += character\n}\n```\n\nOther ways of using `for` are listed here: \u003chttps://gobyexample.com/for\u003e\n\n### Benchmarking\n\nExample:\n\n```go\nfunc BenchmarkRepeat(b *testing.B) {\n\tfor i := 0; i \u003c b.N; i++ {\n\t\tRepeat(\"a\")\n\t}\n}\n```\n\n- `testing.B` gives you access to the (cryptic) `b.N`.\n- the benchmark code is executed `b.N` times and measures how long it takes.\n  - the amount of times shouldn't matter, the framework determine what is a \"good\" value.\n- run the benchmark with `go test -bench=.`\n- the results show how many times the code was executed and how many nanoseconds it took to run.\n\n## Arrays\n\n\u003chttps://quii.gitbook.io/learn-go-with-tests/go-fundamentals/arrays-and-slices\u003e\n\n### Golang\n\nArrays can be initialized in two ways:\n\n- `[N]type{value1, value2, ..., valueN}`\n  - example: `numbers := [5]int{1, 2, 3, 4, 5}`\n- `[...]type{value1, value2, ..., valueN}`\n  - example: `numbers := [...]int{1, 2, 3, 4, 5}`\n\nThe `%v` placeholder print the variable in the \"default\" format (in this case\nan array).\n\nLet's check the `range` instruction:\n\n```go\nfunc Sum(numbers [5]int) int {\n\tsum := 0\n\t// numbers is the array given as argument\n\tfor _, number := range numbers {\n\t\tsum += number\n\t}\n\treturn sum\n}\n```\n\n- `range` let you iterate over an array\n- on each iteration it returns two values: the index and the value\n- in the example we are choosing to ignore the index by using the\n  `_` [blank identifier](https://go.dev/doc/effective_go#blank)\n\n## Slices\n\n### Golang\n\nThe [slice type](https://go.dev/doc/effective_go#slices) allows us to have\ncollections of any size. The syntax is very similar to arrays, just omit\nthe size.\n\nExample: `mySlice := []int{1, 2, 3}`\n\nChecking equality of slices:\n\n```go\nimport \"reflect\"\n\nreflect.DeepEqual(slice1, slice2)\n```\n\nAdding elements to a slice:\n\n```go\n// append() creates a new slice, therefore you need to assign the variable again\nmySlice = append(mySlice, newElement)\n\n// you can use append() to merge two slices:\nmySlice = append(mySlice, anotherSlice...)\n```\n\n### Golang testing\n\nCheck the coverage with\n\n```bash\ngo test -cover\n```\n\n## Structs, Methods and Interfaces\n\n### Golang\n\n```go\n// declaring a struct\ntype Rectangle struct {\n\tWidth  float64\n\tHeight float64\n}\n\n// declaring a method for a struct\nfunc (r Rectangle) Area() float64 {\n\treturn r.Height * r.Width\n}\n```\n\nAn interesting thing about interfaces in Go (which makes me remember Duck Typing):\n**interface resolution is implicit**.\n\nHere's an example of an interface:\n\n```go\ntype Shape interface {\n\tArea() float64\n}\n```\n\nOnce this 👆 is declared **any** struct witha method called `Area()` that returns\na `float64` is automatically considered a `Shape`.\n\nWe don't need to explicitly say \"My type Foo implements interface Bar\".\n\n### Golang testing\n\nI learned about Table Driven Tests. It's useful but not that easy to read\n(without some training).\n\nHere's an example:\n\n```go\nfunc TestArea(t *testing.T) {\n\t// using Table Drive Tests \u003chttps://go.dev/wiki/TableDrivenTests\u003e\n\tareaTests := []struct {\n\t\tname    string\n\t\tshape   Shape\n\t\thasArea float64\n\t}{\n\t\t{\n\t\t\tname:    \"Rectangle\",\n\t\t\tshape:   Rectangle{Width: 12, Height: 6},\n\t\t\thasArea: 72.0,\n\t\t},\n\t\t{\n\t\t\tname:    \"Circle\",\n\t\t\tshape:   Circle{Radius: 10},\n\t\t\thasArea: 314.1592653589793,\n\t\t},\n\t\t{\n\t\t\tname:    \"Triangle\",\n\t\t\tshape:   Triangle{Base: 12, Height: 6},\n\t\t\thasArea: 36.0,\n\t\t},\n\t}\n\n\tfor _, tt := range areaTests {\n\t\t// using tt.name to use it as the `t.Run` test name\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot := tt.shape.Area()\n\t\t\tif got != tt.hasArea {\n\t\t\t\t// the `%#v` format string prints the struct with values in its fields\n\t\t\t\tt.Errorf(\"%#v got %g; want %g\", tt.shape, got, tt.hasArea)\n\t\t\t}\n\t\t})\n\t}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeleu%2Flearning-golang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeleu%2Flearning-golang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeleu%2Flearning-golang/lists"}