From 791303275280a4fd1cb34c4ae57533e075f4780b Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:35:18 +0000 Subject: [PATCH 01/14] values --- go/01-basics/00-values.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 go/01-basics/00-values.go diff --git a/go/01-basics/00-values.go b/go/01-basics/00-values.go new file mode 100644 index 0000000..2da0a0c --- /dev/null +++ b/go/01-basics/00-values.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + + fmt.Println("go" + "lang") + + fmt.Println("1+1 =", 1+1) + fmt.Println("7.0/3.0 =", 7.0/3.0) + + fmt.Println(true && false) + fmt.Println(true || false) + fmt.Println(!true) +} From c7c856882fd5cbc85128ead2845d9ffb4fa4ab1b Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:35:24 +0000 Subject: [PATCH 02/14] variables --- go/01-basics/01-variables.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 go/01-basics/01-variables.go diff --git a/go/01-basics/01-variables.go b/go/01-basics/01-variables.go new file mode 100644 index 0000000..18d1535 --- /dev/null +++ b/go/01-basics/01-variables.go @@ -0,0 +1,21 @@ +package main + +import "fmt" + +func main() { + + var a = "initial" + fmt.Println(a) + + var b, c int = 1, 2 + fmt.Println(b, c) + + var d = true + fmt.Println(d) + + var e int + fmt.Println(e) + + f := "apple" + fmt.Println(f) +} From 0883a9da01caec02a6b152610c80496ece3b18ab Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:35:32 +0000 Subject: [PATCH 03/14] constants --- go/01-basics/02-constants.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 go/01-basics/02-constants.go diff --git a/go/01-basics/02-constants.go b/go/01-basics/02-constants.go new file mode 100644 index 0000000..c030546 --- /dev/null +++ b/go/01-basics/02-constants.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "math" +) + +const s string = "constant" + +func main() { + fmt.Println(s) + + const n = 500000000 + + const d = 3e20 / n + fmt.Println(d) + + fmt.Println(int64(d)) + + fmt.Println(math.Sin(n)) +} \ No newline at end of file From 3dcfa6b2176ee7c99f1692b22d32b449a2dfefc0 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:35:42 +0000 Subject: [PATCH 04/14] for --- go/01-basics/03-for.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 go/01-basics/03-for.go diff --git a/go/01-basics/03-for.go b/go/01-basics/03-for.go new file mode 100644 index 0000000..912b6c3 --- /dev/null +++ b/go/01-basics/03-for.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +func main() { + + i := 1 + for i <= 3 { + fmt.Println(i) + i = i + 1 + } + + for j := 0; j < 3; j++ { + fmt.Println(j) + } + + for i := range 3 { + fmt.Println("range", i) + } + + for { + fmt.Println("loop") + break + } + + for n := range 6 { + if n%2 == 0 { + continue + } + fmt.Println(n) + } +} From 17198381b01abf3712b7f59d7844492a695002cf Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:35:50 +0000 Subject: [PATCH 05/14] ifelse --- go/01-basics/04-if-else.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 go/01-basics/04-if-else.go diff --git a/go/01-basics/04-if-else.go b/go/01-basics/04-if-else.go new file mode 100644 index 0000000..c4e8f89 --- /dev/null +++ b/go/01-basics/04-if-else.go @@ -0,0 +1,28 @@ +package main + +import "fmt" + +func main() { + + if 7%2 == 0 { + fmt.Println("7 is even") + } else { + fmt.Println("7 is odd") + } + + if 8%4 == 0 { + fmt.Println("8 is divisible by 4") + } + + if 8%2 == 0 || 7%2 == 0 { + fmt.Println("either 8 or 7 are even") + } + + if num := 9; num < 0 { + fmt.Println(num, "is negative") + } else if num < 10 { + fmt.Println(num, "has 1 digit") + } else { + fmt.Println(num, "has multiple digits") + } +} From 7704129817e32a249b70e72d4455378f3647a15a Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:35:55 +0000 Subject: [PATCH 06/14] switch --- go/01-basics/05-switch.go | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 go/01-basics/05-switch.go diff --git a/go/01-basics/05-switch.go b/go/01-basics/05-switch.go new file mode 100644 index 0000000..545f1a6 --- /dev/null +++ b/go/01-basics/05-switch.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + + i := 2 + fmt.Print("Write ", i, " as ") + switch i { + case 1: + fmt.Println("one") + case 2: + fmt.Println("two") + case 3: + fmt.Println("three") + } + + switch time.Now().Weekday() { + case time.Saturday, time.Sunday: + fmt.Println("It's the weekend") + default: + fmt.Println("It's a weekday") + } + + t := time.Now() + switch { + case t.Hour() < 12: + fmt.Println("It's before noon") + default: + fmt.Println("It's after noon") + } + + whatAmI := func(i interface{}) { + switch t := i.(type) { + case bool: + fmt.Println("I'm a bool") + case int: + fmt.Println("I'm an int") + default: + fmt.Printf("Don't know type %T\n", t) + } + } + whatAmI(true) + whatAmI(1) + whatAmI("hey") +} From 5aaff118b964db040dd411964b7a1d32e1132348 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:36:03 +0000 Subject: [PATCH 07/14] arrays --- go/01-basics/06-arrays.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 go/01-basics/06-arrays.go diff --git a/go/01-basics/06-arrays.go b/go/01-basics/06-arrays.go new file mode 100644 index 0000000..ab2ed71 --- /dev/null +++ b/go/01-basics/06-arrays.go @@ -0,0 +1,38 @@ +package main + +import "fmt" + +func main() { + + var a [5]int + fmt.Println("emp:", a) + + a[4] = 100 + fmt.Println("set:", a) + fmt.Println("get:", a[4]) + + fmt.Println("len:", len(a)) + + b := [5]int{1, 2, 3, 4, 5} + fmt.Println("dcl:", b) + + b = [...]int{1, 2, 3, 4, 5} + fmt.Println("dcl:", b) + + b = [...]int{100, 3: 400, 500} + fmt.Println("idx:", b) + + var twoD [2][3]int + for i := 0; i < 2; i++ { + for j := 0; j < 3; j++ { + twoD[i][j] = i + j + } + } + fmt.Println("2d: ", twoD) + + twoD = [2][3]int{ + {1, 2, 3}, + {1, 2, 3}, + } + fmt.Println("2d: ", twoD) +} \ No newline at end of file From 07bc76c3562b5d21832c4530845b165d36ca6351 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:36:09 +0000 Subject: [PATCH 08/14] pointers --- go/01-basics/07-pointers.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 go/01-basics/07-pointers.go diff --git a/go/01-basics/07-pointers.go b/go/01-basics/07-pointers.go new file mode 100644 index 0000000..e5f95f6 --- /dev/null +++ b/go/01-basics/07-pointers.go @@ -0,0 +1,24 @@ +package main + +import "fmt" + +func zeroval(ival int) { + ival = 0 +} + +func zeroptr(iptr *int) { + *iptr = 0 +} + +func main() { + i := 1 + fmt.Println("initial:", i) + + zeroval(i) + fmt.Println("zeroval:", i) + + zeroptr(&i) + fmt.Println("zeroptr:", i) + + fmt.Println("pointer:", &i) +} From 8b5657d026054f648acb2d3a018d867b3ab768f9 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:36:17 +0000 Subject: [PATCH 09/14] slices --- go/01-basics/08-slices.go | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 go/01-basics/08-slices.go diff --git a/go/01-basics/08-slices.go b/go/01-basics/08-slices.go new file mode 100644 index 0000000..8400528 --- /dev/null +++ b/go/01-basics/08-slices.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "slices" +) + +func main() { + + var s []string + fmt.Println("uninit:", s, s == nil, len(s) == 0) + + s = make([]string, 3) + fmt.Println("emp:", s, "len:", len(s), "cap:", cap(s)) + + s[0] = "a" + s[1] = "b" + s[2] = "c" + fmt.Println("set:", s) + fmt.Println("get:", s[2]) + + fmt.Println("len:", len(s)) + + s = append(s, "d") + s = append(s, "e", "f") + fmt.Println("apd:", s) + + c := make([]string, len(s)) + copy(c, s) + fmt.Println("cpy:", c) + + l := s[2:5] + fmt.Println("sl1:", l) + + l = s[:5] + fmt.Println("sl2:", l) + + l = s[2:] + fmt.Println("sl3:", l) + + t := []string{"g", "h", "i"} + fmt.Println("dcl:", t) + + t2 := []string{"g", "h", "i"} + if slices.Equal(t, t2) { + fmt.Println("t == t2") + } + + twoD := make([][]int, 3) + for i := 0; i < 3; i++ { + innerLen := i + 1 + twoD[i] = make([]int, innerLen) + for j := 0; j < innerLen; j++ { + twoD[i][j] = i + j + } + } + fmt.Println("2d: ", twoD) +} From 5f2511d8949a1ee4f0ddd3a1a660c19ce0841444 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:36:20 +0000 Subject: [PATCH 10/14] maps --- go/01-basics/09-maps.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 go/01-basics/09-maps.go diff --git a/go/01-basics/09-maps.go b/go/01-basics/09-maps.go new file mode 100644 index 0000000..0a8eb73 --- /dev/null +++ b/go/01-basics/09-maps.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "maps" +) + +func main() { + + m := make(map[string]int) + + m["k1"] = 7 + m["k2"] = 13 + + fmt.Println("map:", m) + + v1 := m["k1"] + fmt.Println("v1:", v1) + + v3 := m["k3"] + fmt.Println("v3:", v3) + + fmt.Println("len:", len(m)) + + delete(m, "k2") + fmt.Println("map:", m) + + clear(m) + fmt.Println("map:", m) + + _, prs := m["k2"] + fmt.Println("prs:", prs) + + n := map[string]int{"foo": 1, "bar": 2} + fmt.Println("map:", n) + + n2 := map[string]int{"foo": 1, "bar": 2} + if maps.Equal(n, n2) { + fmt.Println("n == n2") + } +} From a8633aa18f03377560b9d7654f1638228a198784 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:36:25 +0000 Subject: [PATCH 11/14] enums --- go/01-basics/10-enums.go | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 go/01-basics/10-enums.go diff --git a/go/01-basics/10-enums.go b/go/01-basics/10-enums.go new file mode 100644 index 0000000..feeb598 --- /dev/null +++ b/go/01-basics/10-enums.go @@ -0,0 +1,45 @@ +package main + +import "fmt" + +type ServerState int + +const ( + StateIdle ServerState = iota + StateConnected + StateError + StateRetrying +) + +var stateName = map[ServerState]string{ + StateIdle: "idle", + StateConnected: "connected", + StateError: "error", + StateRetrying: "retrying", +} + +func (ss ServerState) String() string { + return stateName[ss] +} + +func main() { + ns := transition(StateIdle) + fmt.Println(ns) + + ns2 := transition(ns) + fmt.Println(ns2) +} + +func transition(s ServerState) ServerState { + switch s { + case StateIdle: + return StateConnected + case StateConnected, StateRetrying: + + return StateIdle + case StateError: + return StateError + default: + panic(fmt.Errorf("unknown state: %s", s)) + } +} From 0c032e5c6369635d58fafd37b3b35421ff59de06 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:36:32 +0000 Subject: [PATCH 12/14] functions --- go/01-basics/11-functions.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 go/01-basics/11-functions.go diff --git a/go/01-basics/11-functions.go b/go/01-basics/11-functions.go new file mode 100644 index 0000000..4f51b2d --- /dev/null +++ b/go/01-basics/11-functions.go @@ -0,0 +1,36 @@ +package main + +import "fmt" + +func plus(a int, b int) int { + return a + b +} + +func plusPlus(a, b, c int) int { + return a + b + c +} + +func plusNamed(a, b int) (result int) { + result = a + b + return +} + +func plusDescription(a int, b int) (int, string) { + result := a + b + return result, fmt.Sprintf("%d+%d = %d", a, b, result) +} + +func main() { + + res := plus(1, 2) + fmt.Println("1+2 =", res) + + res = plusPlus(1, 2, 3) + fmt.Println("1+2+3 =", res) + + res = plusNamed(1, 2) + fmt.Println("1+2 =", res) + + _, desc := plusDescription(1, 2) + fmt.Println(desc) +} From 7160d21cdc5f101deed08206d76ca217103d1cf9 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:36:39 +0000 Subject: [PATCH 13/14] structs --- go/01-basics/12-structs.go | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 go/01-basics/12-structs.go diff --git a/go/01-basics/12-structs.go b/go/01-basics/12-structs.go new file mode 100644 index 0000000..4f9756f --- /dev/null +++ b/go/01-basics/12-structs.go @@ -0,0 +1,46 @@ +package main + +import "fmt" + +type person struct { + name string + age int +} + +func newPerson(name string) *person { + + p := person{name: name} + p.age = 42 + return &p +} + +func main() { + + fmt.Println(person{"Bob", 20}) + + fmt.Println(person{name: "Alice", age: 30}) + + fmt.Println(person{name: "Fred"}) + + fmt.Println(&person{name: "Ann", age: 40}) + + fmt.Println(newPerson("Jon")) + + s := person{name: "Sean", age: 50} + fmt.Println(s.name) + + sp := &s + fmt.Println(sp.age) + + sp.age = 51 + fmt.Println(sp.age) + + dog := struct { + name string + isGood bool + }{ + "Rex", + true, + } + fmt.Println(dog) +} From 60893de6b159c8e8fe29d604da342e9942cb55d3 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Tue, 24 Mar 2026 13:01:43 +0000 Subject: [PATCH 14/14] add code comments --- go/01-basics/00-values.go | 3 ++ go/01-basics/01-variables.go | 5 +++ go/01-basics/02-constants.go | 26 +++++++++------ go/01-basics/03-for.go | 52 +++++++++++++++++------------- go/01-basics/04-if-else.go | 39 ++++++++++++----------- go/01-basics/05-switch.go | 7 +++++ go/01-basics/06-arrays.go | 61 +++++++++++++++++++++--------------- go/01-basics/07-pointers.go | 5 +++ go/01-basics/08-slices.go | 14 +++++++++ go/01-basics/09-maps.go | 16 +++++++++- go/01-basics/10-enums.go | 7 ++++- go/01-basics/11-functions.go | 12 +++++++ go/01-basics/12-structs.go | 15 +++++++++ 13 files changed, 187 insertions(+), 75 deletions(-) diff --git a/go/01-basics/00-values.go b/go/01-basics/00-values.go index 2da0a0c..c8bc0a4 100644 --- a/go/01-basics/00-values.go +++ b/go/01-basics/00-values.go @@ -4,11 +4,14 @@ import "fmt" func main() { + //string values and concatenation operator fmt.Println("go" + "lang") + //numeric values and arithmetic operators fmt.Println("1+1 =", 1+1) fmt.Println("7.0/3.0 =", 7.0/3.0) + //boolean values and logical operators fmt.Println(true && false) fmt.Println(true || false) fmt.Println(!true) diff --git a/go/01-basics/01-variables.go b/go/01-basics/01-variables.go index 18d1535..6974634 100644 --- a/go/01-basics/01-variables.go +++ b/go/01-basics/01-variables.go @@ -4,18 +4,23 @@ import "fmt" func main() { + //definition of a single variable var a = "initial" fmt.Println(a) + //definition of multiple variables var b, c int = 1, 2 fmt.Println(b, c) + //definition of multiple variables with implicit type var d = true fmt.Println(d) + //definition of a variable without an initial value, it will be assigned the zero value of its type var e int fmt.Println(e) + //definition of a variable with the short declaration operator, it can only be used inside functions f := "apple" fmt.Println(f) } diff --git a/go/01-basics/02-constants.go b/go/01-basics/02-constants.go index c030546..c93d077 100644 --- a/go/01-basics/02-constants.go +++ b/go/01-basics/02-constants.go @@ -1,21 +1,29 @@ package main import ( - "fmt" - "math" + "fmt" + "math" ) +// Constants are declared like variables, but with the const keyword. const s string = "constant" func main() { - fmt.Println(s) + //A constant is a simple unchanging value. Constants can be character, string, boolean, or numeric values. + fmt.Println(s) - const n = 500000000 + //Constants can be declared as a group, like variables. + const n = 500000000 - const d = 3e20 / n - fmt.Println(d) + //Constant expressions perform arithmetic with arbitrary precision. + const d = 3e20 / n + fmt.Println(d) - fmt.Println(int64(d)) + // A numeric constant has no type until it's given one, such as by an explicit cast. + fmt.Println(int64(d)) - fmt.Println(math.Sin(n)) -} \ No newline at end of file + // A number can be given a type by using it in a context that requires one, + // such as a variable assignment or an argument to a function. + // Here, math.Sin expects a float64, so the untyped constant n is given that type. + fmt.Println(math.Sin(n)) +} diff --git a/go/01-basics/03-for.go b/go/01-basics/03-for.go index 912b6c3..69b3686 100644 --- a/go/01-basics/03-for.go +++ b/go/01-basics/03-for.go @@ -4,29 +4,39 @@ import "fmt" func main() { - i := 1 - for i <= 3 { - fmt.Println(i) - i = i + 1 - } + // For is the only loop statement in Go. No parentheses are needed around the condition, + // but the curly braces are required. - for j := 0; j < 3; j++ { - fmt.Println(j) - } + i := 1 + // The most basic type, with a single condition. + for i <= 3 { + fmt.Println(i) + i = i + 1 + } - for i := range 3 { - fmt.Println("range", i) - } + // Like in C, the first and third components of the for statement are optional. + for j := 0; j < 3; j++ { + fmt.Println(j) + } - for { - fmt.Println("loop") - break - } + // The range form of the for loop iterates over a slice or map. + for i := range 3 { + fmt.Println("range", i) + } - for n := range 6 { - if n%2 == 0 { - continue - } - fmt.Println(n) - } + // Infinite loops are formed by omitting the loop condition; the loop will repeat + // until you break out of it or return from the enclosing function. + for { + fmt.Println("loop") + break + } + + // The range form of the for loop can also be used with arrays, slices, maps, and strings. + for n := range 6 { + if n%2 == 0 { + // Skip even numbers. + continue + } + fmt.Println(n) + } } diff --git a/go/01-basics/04-if-else.go b/go/01-basics/04-if-else.go index c4e8f89..38d1967 100644 --- a/go/01-basics/04-if-else.go +++ b/go/01-basics/04-if-else.go @@ -4,25 +4,28 @@ import "fmt" func main() { - if 7%2 == 0 { - fmt.Println("7 is even") - } else { - fmt.Println("7 is odd") - } + // The if statement is straightforward. + if 7%2 == 0 { + fmt.Println("7 is even") + } else { + fmt.Println("7 is odd") + } - if 8%4 == 0 { - fmt.Println("8 is divisible by 4") - } + // You can have an if statement without an else, and the else is optional. + if 8%4 == 0 { + fmt.Println("8 is divisible by 4") + } - if 8%2 == 0 || 7%2 == 0 { - fmt.Println("either 8 or 7 are even") - } + if 8%2 == 0 || 7%2 == 0 { + fmt.Println("either 8 or 7 are even") + } - if num := 9; num < 0 { - fmt.Println(num, "is negative") - } else if num < 10 { - fmt.Println(num, "has 1 digit") - } else { - fmt.Println(num, "has multiple digits") - } + // A statement can precede conditionals; any variables declared in this statement are available in all branches. + if num := 9; num < 0 { + fmt.Println(num, "is negative") + } else if num < 10 { + fmt.Println(num, "has 1 digit") + } else { + fmt.Println(num, "has multiple digits") + } } diff --git a/go/01-basics/05-switch.go b/go/01-basics/05-switch.go index 545f1a6..d416946 100644 --- a/go/01-basics/05-switch.go +++ b/go/01-basics/05-switch.go @@ -7,11 +7,14 @@ import ( func main() { + // The switch statement is like a multi-way if. It runs the first case whose value is equal to the condition. i := 2 fmt.Print("Write ", i, " as ") switch i { case 1: fmt.Println("one") + //no fallthrough, so the next case will not be executed + //no break statement needed, unlike in C or Java case 2: fmt.Println("two") case 3: @@ -19,6 +22,7 @@ func main() { } switch time.Now().Weekday() { + // You can use commas to separate multiple expressions in the same case statement. case time.Saturday, time.Sunday: fmt.Println("It's the weekend") default: @@ -28,11 +32,14 @@ func main() { t := time.Now() switch { case t.Hour() < 12: + // Switch without an expression is an alternate way to express if/else logic. + // Here we use it to show how the current hour falls into the first or second half of the day. fmt.Println("It's before noon") default: fmt.Println("It's after noon") } + // In Go, a type switch is a construct that permits several type assertions in series. whatAmI := func(i interface{}) { switch t := i.(type) { case bool: diff --git a/go/01-basics/06-arrays.go b/go/01-basics/06-arrays.go index ab2ed71..71277ab 100644 --- a/go/01-basics/06-arrays.go +++ b/go/01-basics/06-arrays.go @@ -4,35 +4,46 @@ import "fmt" func main() { - var a [5]int - fmt.Println("emp:", a) + // Arrays in Go have a fixed size and a specific type. + var a [5]int + fmt.Println("emp:", a) - a[4] = 100 - fmt.Println("set:", a) - fmt.Println("get:", a[4]) + // Set and get a value. + a[4] = 100 + fmt.Println("set:", a) + fmt.Println("get:", a[4]) - fmt.Println("len:", len(a)) + // The builtin len returns the length of an array. + fmt.Println("len:", len(a)) - b := [5]int{1, 2, 3, 4, 5} - fmt.Println("dcl:", b) + // Array literals + b := [5]int{1, 2, 3, 4, 5} + fmt.Println("dcl:", b) - b = [...]int{1, 2, 3, 4, 5} - fmt.Println("dcl:", b) + // An array literal with [...] can be used to let the compiler count the array elements. + b = [...]int{1, 2, 3, 4, 5} + fmt.Println("dcl:", b) - b = [...]int{100, 3: 400, 500} - fmt.Println("idx:", b) + // Array literals with an index can initialize the specified values and any unspecified + // values will be set to the zero value of the array's element type. + b = [...]int{100, 3: 400, 500} + fmt.Println("idx:", b) - var twoD [2][3]int - for i := 0; i < 2; i++ { - for j := 0; j < 3; j++ { - twoD[i][j] = i + j - } - } - fmt.Println("2d: ", twoD) + // Multidimensional arrays + var twoD [2][3]int + for i := 0; i < 2; i++ { + for j := 0; j < 3; j++ { + twoD[i][j] = i + j + } + } + fmt.Println("2d: ", twoD) - twoD = [2][3]int{ - {1, 2, 3}, - {1, 2, 3}, - } - fmt.Println("2d: ", twoD) -} \ No newline at end of file + // Array literals for multidimensional arrays + twoD = [2][3]int{ + {1, 2, 3}, + {1, 2, 3}, + // The comma is required here, even though it's the last element. + // This helps make diffs cleaner when new elements are added. + } + fmt.Println("2d: ", twoD) +} diff --git a/go/01-basics/07-pointers.go b/go/01-basics/07-pointers.go index e5f95f6..74cce91 100644 --- a/go/01-basics/07-pointers.go +++ b/go/01-basics/07-pointers.go @@ -2,10 +2,12 @@ package main import "fmt" +// A pointer holds the memory address of a value. The type *T is a pointer to a T value. Its zero value is nil. func zeroval(ival int) { ival = 0 } +// To change the actual value that a pointer points to, we need to dereference the pointer. func zeroptr(iptr *int) { *iptr = 0 } @@ -14,11 +16,14 @@ func main() { i := 1 fmt.Println("initial:", i) + // zeroval will get a copy of i, so the original i is not affected. zeroval(i) fmt.Println("zeroval:", i) + // zeroptr will get a pointer to i, so it can change the value of i through the pointer. zeroptr(&i) fmt.Println("zeroptr:", i) + // We can also use the & operator to get the pointer of a variable. fmt.Println("pointer:", &i) } diff --git a/go/01-basics/08-slices.go b/go/01-basics/08-slices.go index 8400528..05b17b8 100644 --- a/go/01-basics/08-slices.go +++ b/go/01-basics/08-slices.go @@ -7,12 +7,16 @@ import ( func main() { + // A slice is a dynamically-sized, flexible view into the elements of an array. + // In practice, slices are much more common than arrays. var s []string fmt.Println("uninit:", s, s == nil, len(s) == 0) + // To create an empty slice with non-zero length, use the built-in make function. s = make([]string, 3) fmt.Println("emp:", s, "len:", len(s), "cap:", cap(s)) + // Set and get a value. s[0] = "a" s[1] = "b" s[2] = "c" @@ -21,31 +25,41 @@ func main() { fmt.Println("len:", len(s)) + // Slices can be resliced. This does not copy the slice data. s = append(s, "d") s = append(s, "e", "f") fmt.Println("apd:", s) + // Deep copy a slice. This creates a new slice with the same length and copies the + // elements from the original slice to the new slice. c := make([]string, len(s)) copy(c, s) fmt.Println("cpy:", c) + // Slices support a "slice" operator with the syntax slice[low:high]. + // This selects a half-open range which includes the first element, but excludes the last one. l := s[2:5] fmt.Println("sl1:", l) + // This slices up to (but excluding) index 5. l = s[:5] fmt.Println("sl2:", l) + // This slices from index 2 to the end of the slice. l = s[2:] fmt.Println("sl3:", l) + // You can declare and initialize a slice in a single line as well. t := []string{"g", "h", "i"} fmt.Println("dcl:", t) + // The builtin "slices" package provides a function Equal to compare two slices for equality. t2 := []string{"g", "h", "i"} if slices.Equal(t, t2) { fmt.Println("t == t2") } + // Slices can be composed into multi-dimensional data structures. The length of the inner slices can vary. twoD := make([][]int, 3) for i := 0; i < 3; i++ { innerLen := i + 1 diff --git a/go/01-basics/09-maps.go b/go/01-basics/09-maps.go index 0a8eb73..9dcbb3b 100644 --- a/go/01-basics/09-maps.go +++ b/go/01-basics/09-maps.go @@ -7,33 +7,47 @@ import ( func main() { - m := make(map[string]int) + // A map maps keys to values. The zero value of a map is nil. A nil map has no keys, nor can keys be added. + var m map[string]int + // To create a map, use the builtin make function. The make function allocates and + // initializes a hash map data structure and returns a map value that points to it. + m = make(map[string]int) + + // Set key/value pairs using typical name[key] = val syntax. m["k1"] = 7 m["k2"] = 13 fmt.Println("map:", m) + // Get a value for a key with name[key]. v1 := m["k1"] fmt.Println("v1:", v1) + // If the key is not present in the map, the result is the zero value for the map's value type. v3 := m["k3"] fmt.Println("v3:", v3) fmt.Println("len:", len(m)) + // The builtin delete removes key/value pairs from a map. delete(m, "k2") + delete(m, "k2") // Deleting a non-existent key does not cause an error. fmt.Println("map:", m) + // The builtin "maps" package provides a function Clear to remove all key/value pairs from a map. clear(m) fmt.Println("map:", m) + // The optional second return value when getting a value from a map indicates if the key was present in the map. _, prs := m["k2"] fmt.Println("prs:", prs) + // Map literals are like struct literals, but the keys are required. n := map[string]int{"foo": 1, "bar": 2} fmt.Println("map:", n) + // The builtin "maps" package provides a function Equal to compare two maps for equality. n2 := map[string]int{"foo": 1, "bar": 2} if maps.Equal(n, n2) { fmt.Println("n == n2") diff --git a/go/01-basics/10-enums.go b/go/01-basics/10-enums.go index feeb598..347450f 100644 --- a/go/01-basics/10-enums.go +++ b/go/01-basics/10-enums.go @@ -2,8 +2,11 @@ package main import "fmt" +// Go does not have a native enum type, but you can achieve similar functionality using constants and iota. type ServerState int +// iota is a special identifier that is reset to 0 whenever the word const appears in the source and +// increments by one after each const specification. It is often used to create enumerated constants. const ( StateIdle ServerState = iota StateConnected @@ -11,6 +14,7 @@ const ( StateRetrying ) +// We can use a map to associate the ServerState values with their string representations. var stateName = map[ServerState]string{ StateIdle: "idle", StateConnected: "connected", @@ -18,6 +22,7 @@ var stateName = map[ServerState]string{ StateRetrying: "retrying", } +// By implementing the Stringer interface, we can define how our ServerState values are printed. func (ss ServerState) String() string { return stateName[ss] } @@ -31,11 +36,11 @@ func main() { } func transition(s ServerState) ServerState { + // A simple state machine that transitions between states based on the current state. switch s { case StateIdle: return StateConnected case StateConnected, StateRetrying: - return StateIdle case StateError: return StateError diff --git a/go/01-basics/11-functions.go b/go/01-basics/11-functions.go index 4f51b2d..cc3c6af 100644 --- a/go/01-basics/11-functions.go +++ b/go/01-basics/11-functions.go @@ -2,19 +2,31 @@ package main import "fmt" +// Functions are defined with the func keyword, followed by the function name, +// a list of parameters in parentheses, and the return type. func plus(a int, b int) int { return a + b } +// Function overloading is not supported in Go, but we can achieve similar functionality +// by using different function names or by using variadic functions. +// func plus(a float64, b float64) float64 { // compile error: function plus redeclared in this block +// return a + b +// } + +// A function with multiple parameters of the same type can be shortened by listing the type only once. func plusPlus(a, b, c int) int { return a + b + c } +// Named return values are treated as variables defined at the top of the function. +// A return statement without arguments returns the current values of the named return variables. func plusNamed(a, b int) (result int) { result = a + b return } +// A function can return multiple values. Here we return the sum and a formatted string description of the operation. func plusDescription(a int, b int) (int, string) { result := a + b return result, fmt.Sprintf("%d+%d = %d", a, b, result) diff --git a/go/01-basics/12-structs.go b/go/01-basics/12-structs.go index 4f9756f..9f0b54a 100644 --- a/go/01-basics/12-structs.go +++ b/go/01-basics/12-structs.go @@ -2,11 +2,15 @@ package main import "fmt" +// A struct is a collection of fields. It's useful for grouping data together to form records. type person struct { name string age int } +// A struct literal is a list of field values enclosed in braces. You can specify field names or just provide values in order. +// Instead of constructors, Go often uses factory functions that return a pointer to a struct. +// This allows for more flexible initialization and can encapsulate any setup logic. func newPerson(name string) *person { p := person{name: name} @@ -16,25 +20,36 @@ func newPerson(name string) *person { func main() { + // Here we create a new person struct using a struct literal. We specify the field values in order without field names. fmt.Println(person{"Bob", 20}) + // We can also specify field names in the struct literal. This way, the order of fields does not matter. fmt.Println(person{name: "Alice", age: 30}) + // Omitted fields will be set to their zero value. For example, the age field will be set to 0. fmt.Println(person{name: "Fred"}) + // You can also create a struct using the & operator to get a pointer to the struct. This is often more efficient when passing structs around. fmt.Println(&person{name: "Ann", age: 40}) + // Using a factory function to create a new person struct. This allows us to encapsulate any initialization logic and return a pointer to the struct. fmt.Println(newPerson("Jon")) s := person{name: "Sean", age: 50} + // Struct fields are accessed using a dot. fmt.Println(s.name) + // You can also access fields through a struct pointer. + // The language automatically dereferences the pointer to access the field. sp := &s fmt.Println(sp.age) + // Struct fields can be modified through a struct pointer as well. The following statement + // also changes the value of s.age because sp and s point to the same struct in memory. sp.age = 51 fmt.Println(sp.age) + // Anonymous struct is a struct without a name. It's useful for grouping data together without having to define a new type. dog := struct { name string isGood bool