diff --git a/src/assets/JourneyWithGo-ABlogSeries/goFundamentals.md b/src/assets/JourneyWithGo-ABlogSeries/goFundamentals.md index aafe141..8208287 100644 --- a/src/assets/JourneyWithGo-ABlogSeries/goFundamentals.md +++ b/src/assets/JourneyWithGo-ABlogSeries/goFundamentals.md @@ -17,7 +17,7 @@ This is the third installment of the series. You are here which means you have m the series. If you haven't, please read them first [Go Basics](https://blog.jankaritech.com/#/blog/Journey%20With%20Go%20-%20A%20Blog%20Series/Go%20Basics%20-%20The%20Starting%20Point "Go Basics"), [Control Statements](https://blog.jankaritech.com/#/blog/Journey%20With%20Go%20-%20A%20Blog%20Series/Control%20Statements%20-%20Control%20Your%20Go "Control Statements"). -In this blog, we will learn about the `Function`, `Array`, `Rune`, `Method`, `Interface`, `String`, and `Struct` (FARMISS) in +In this blog, we will learn about the `Rune`, `String`, `Array`, `Function`, `Struct`, `Method`, and `Interface` in Go. **So, let's get started.** ## **1. Rune** @@ -26,6 +26,8 @@ In Go, a rune is a built-in type that represents a Unicode code point. A rune li characters enclosed in single quotes, as in 'x' or '\n'. Each Unicode code point corresponds to a unique character, which can be a letter, a numeral, a symbol, or an emoji. +**Examples:** + ```go package main @@ -34,22 +36,34 @@ import ( ) func main() { - var om rune = 'ॐ' // rune literal declared using `rune` keyword, use single quotes - fmt.Println(om) // 2384, which is the Unicode code point for the Om symbol - fmt.Printf("%T\n", om) // int32, which is the underlying type of rune - fmt.Println(string(om)) // ॐ, which is the string representation of the Om symbol + var om rune = 'ॐ' // rune literal declared using the `rune` keyword, use single quotes + fmt.Println(om) // prints the Unicode code point for the Om symbol + fmt.Printf("%T\n", om) // prints the underlying type of rune + fmt.Println(string(om)) // prints the string representation of the Om symbol // more examples var heart rune = '♥' - fmt.Println(heart) // 9829 - fmt.Println(string(heart)) // ♥ + fmt.Println(heart) + fmt.Println(string(heart)) var smiley rune = '😀' - fmt.Println(smiley) // 128512 - fmt.Println(string(smiley)) // 😀 + fmt.Println(smiley) + fmt.Println(string(smiley)) } ``` +**Output:** + +```bash +2384 +int32 +ॐ +9829 +♥ +128512 +😀 +``` + It is particularly important when dealing with text in different languages or when working with special symbols and emojis. It ensures that each character is treated as a single entity, regardless of its complexity or language. @@ -61,6 +75,8 @@ create a new string. _Note: The rune is encoded with single quotes, whereas the string is encoded with double quotes._ +**Examples:** + ```go package main @@ -71,33 +87,55 @@ import ( func main() { // declaring a variable `greeting` of type string using `string` keyword var greeting string = "Hello, World!" - fmt.Println(greeting) // Hello, World! - fmt.Printf("%T\n", greeting) // string, which is the underlying type of string - fmt.Println(len(greeting)) // 13, which is the number of bytes in the string - fmt.Println(greeting[0]) // 72, which is the ASCII code for H - fmt.Println(string(greeting[0])) // H, which is the string representation of 72 - fmt.Println("Hello, " + "World!") // Hello, World!, + can be used to concatenate strings + fmt.Println(greeting) // it prints the value of the `greeting` + fmt.Printf("%T\n", greeting) // it prints the type of the `greeting` + fmt.Println(len(greeting)) // it prints the length of bytes in the `greeting` + fmt.Println(greeting[0]) // it prints the byte code of the char in index 0 + fmt.Println(string(greeting[0])) // it prints the string representation of the char in index 0 + fmt.Println("Hello, " + "World!") // it prints the concatenated string `Hello, ` and `World!` with `+` + + // try to change the value at index 1, i.e. `e` to `E` in the `greeting` + greeting[1] = 'E' // it gives an error `cannot assign to greeting[1]` + + // try to assign the new value of the `greeting` to `Hello, Nepal!` + greeting = "Hello, Nepal!" // it creates a new string `Hello, Nepal!` and assigns it to the `greeting` + fmt.Println(greeting) // it prints the new value of the `greeting` } ``` -### **2.1. Slicing of String** +**Output:** + +```bash +Hello, World! +string +13 +72 +H +Hello, World! +cannot assign to greeting[1] +Hello, Nepal! +``` + +### **2.1. Slicing of a String** Slicing is a mechanism to extract a portion of a string. It is done by specifying the start and end indices of the part of the string that you want to extract. The syntax for slicing a string is `string[start:end]`. Taking the above `greeting` variable as example: -| slice | output | description | -|------------------|---------------|------------------------------------------------------------------------------------------------| -| `greeting[7:]` | World! | It gives the sub-string from index 7 to the end | -| `greeting[:5]` | Hello | It gives the sub-string from the beginning to index 5, excludes index 5 value | -| `greeting[7:12]` | World | It gives the sub-string from index 7 to index 12, includes index 7 and excludes index 12 value | -| `greeting[:]` | Hello, World! | It gives the entire string, same as printing `greeting` | +| slice | output | description | +|------------------|---------------|--------------------------------------------------------------------------------------------------| +| `greeting[7:]` | World! | It gives the sub-string from index 7 to the end | +| `greeting[:5]` | Hello | It gives the sub-string from the beginning to index 5, excluding index 5 value | +| `greeting[7:12]` | World | It gives the sub-string from index 7 to index 12, including index 7 and excluding index 12 value | +| `greeting[:]` | Hello, World! | It gives the entire string, same as printing `greeting` | -### **2.2. Iterating over String** +### **2.2. Iterating over a String** Strings are immutable, but you can iterate over them using a for loop with range. +**Examples:** + ```go package main @@ -112,7 +150,9 @@ func main() { } } ``` + **Output:** + ```bash Index: 0, Value: H Index: 1, Value: e @@ -133,6 +173,8 @@ Index: 12, Value: ! The `len` function returns the number of bytes in a string, whereas the `utf8.RuneCountInString` function returns the number of runes in a string. +**Examples:** + ```go package main @@ -144,34 +186,45 @@ import ( func main() { // let's look at the example of English language greeting := "Hello, World!" - fmt.Println(len(greeting)) // 13, it returns the number of bytes in the string - fmt.Println(utf8.RuneCountInString(greeting)) // 13, it returns the number of runes in the string + fmt.Println(len(greeting)) // it prints the number of bytes in the string given by len function + fmt.Println(utf8.RuneCountInString(greeting)) // it prints the number of runes in the string given by utf8.RuneCountInString function - // Now, take an example of Thai language - greeting := "สวัสดี" - fmt.Println(len(greeting)) // 18, it returns the number of bytes in the string - fmt.Println(utf8.RuneCountInString(greeting)) // 6, it returns the number of runes in the string + // Now, take an example of Nepali language + greetingInNepali := "नमस्कार संसार"; + fmt.Println(len(greetingInNepali)) // it prints the number of bytes in the string given by len function + fmt.Println(utf8.RuneCountInString(greetingInNepali)) // it prints the number of runes in the string given by utf8.RuneCountInString function } ``` +**Output:** + +```bash +13 +13 +37 +13 +``` + In the example for the English language, the value returned by the `len` function is same as of the value returned by the `utf8.RuneCountInString` function. -However, for the Thai language, the value returned by the `len` function is different from the value returned by the `utf8.RuneCountInString` function. This is because the Thai language uses the UTF-8 encoding scheme, which uses 3 bytes to represent a single character. Therefore, the string "สวัสดี" has 18 bytes, but only 6 runes. +However, for the Nepali language, the value returned by the `len` function is different from the value returned by the `utf8.RuneCountInString` function. This is because the Nepali language uses the UTF-8 encoding scheme, which uses 3 bytes to represent a single character. Therefore, the string "สวัสดี" has 18 bytes, but only 6 runes. ## **3. Array** -In Go, an array is a fixed-length sequence of elements of the same type. Arrays are useful when you know the number of elements that you want to store in advance. +In Go, an array is a fixed-length sequence of elements of the same type but the content of array is mutable (i.e. can be changed). Arrays are useful when you know the number of elements that you want to store in advance. ### **3.1. Declaration of Array** Declaration of an array can be done using the following syntax: **Syntax:** + ```go var [] ``` **Examples:** + ```go package main @@ -182,32 +235,43 @@ import ( func main(){ // declaring an array of type int with 5 elements var numbers [5]int - fmt.Println(numbers) // [0 0 0 0 0], by default 0 will be assigned to array elements + fmt.Println(numbers) // by default 0 will be assigned to array elements // declaring an array of type string with 3 elements var languages [3]string - fmt.Println(languages) // [ ], by default empty array will be created + fmt.Println(languages) // by default empty array will be created // declaring an array of type bool with 2 elements var truths [2]bool - fmt.Println(truths) // [false false], by default false will be assigned to array elements + fmt.Println(truths) // by default false will be assigned to array elements // declaring an array of type float64 with 4 elements var scores [4]float64 - fmt.Println(scores) // [0 0 0 0], by default 0 will be assigned to array elements + fmt.Println(scores) // by default 0 will be assigned to array elements } ``` +**Output:** + +```bash +[0 0 0 0 0] +[ ] +[false false] +[0 0 0 0] +``` + ### **3.2. Initialization of Array** You can initialize an array using the following syntax: **Syntax:** + ```go var [] = []{} ``` **Examples:** + ```go package main @@ -218,32 +282,43 @@ import ( func main(){ // initialization of an array of type int with 3 elements var numbers [3]int = [3]int{1, 2, 3} - fmt.Println(numbers) // [1 2 3] + fmt.Println(numbers) // prints the value of integer array // initialization of an array of type string with 3 elements var languages [3]string = [3]string{"Go", "Python", "JavaScript"} - fmt.Println(languages) // [Go Python JavaScript] + fmt.Println(languages) // prints the value of string array // initialization of an array of type bool with 2 elements var truths [2]bool = [2]bool{true, false} - fmt.Println(truths) // [true false] + fmt.Println(truths) // prints the value of boolean array // initialization of an array of type float64 with 3 elements var scores [3]float64 = [3]float64{9.5, 8.2, 7.8} - fmt.Println(scores) // [9.5 8.2 7.8] + fmt.Println(scores) // prints the value of float64 array } ``` +**Output:** + +```bash +[1 2 3] +[Go Python JavaScript] +[true false] +[9.5 8.2 7.8] +``` + ### **3.3. Manipulation of Array** You can manipulate an array using the following syntax: **Syntax:** + ```go [] = ``` **Examples:** + ```go package main @@ -253,28 +328,40 @@ import ( func main() { var numbers [3]int = [3]int{1, 2, 3} - fmt.Println(numbers) // [1 2 3] + fmt.Println(numbers) // prints the value of the array // changing the value of the first element numbers[0] = 4 - fmt.Println(numbers) // [4 2 3] + fmt.Println(numbers) // prints the new value of the array // accessing an element of the array - fmt.Println(numbers[0]) // 4, which is the value of the first element + fmt.Println(numbers[0]) // prints the value of the first element // adding a new element to the array is not possible - numbers[3] = 5 // invalid array index 3 (out of bounds for 3-element array) + numbers[3] = 5 // invalid array index 3 (out of bounds for 3-element array) // accessing an element of non-existing index is not possible - fmt.Println(numbers[3]) // invalid array index 3 (out of bounds for 3-element array) + fmt.Println(numbers[3]) // invalid array index 3 (out of bounds for 3-element array) } ``` +**Output:** + +```bash +[1 2 3] +[4 2 3] +4 +invalid argument: index 3 out of bounds +invalid argument: index 3 out of bounds +``` + ### **3.4. Array Length** You can get the length of an array using the `len` function. +**Examples:** + ```go package main @@ -284,14 +371,22 @@ import ( func main() { var numbers [3]int = [3]int{1, 2, 3} - fmt.Println(len(numbers)) // 3, which is the length of the array + fmt.Println(len(numbers)) // prints the length of the array } ``` +**Output:** + +```bash +3 +``` + ### **3.5. Iterating over Array** You can iterate over an array using a for loop with range. +**Examples:** + ```go package main @@ -308,6 +403,7 @@ func main() { ``` **Output:** + ```bash Index: 0, Value: Go Index: 1, Value: Javascript @@ -316,6 +412,8 @@ Index: 2, Value: Python An alternative way to iterate over an array is to use a for loop with the length of the array. +**Examples:** + ```go package main @@ -332,6 +430,7 @@ func main() { ``` **Output:** + ```bash Index: 0, Value: Go Index: 1, Value: Javascript @@ -343,11 +442,13 @@ Index: 2, Value: Python In Go, a function is a block of code that performs a specific task. Functions are useful when you want to reuse the same code multiple times. They also help in organizing your code into smaller chunks, which makes it easier to read and maintain. ### **4.1. Function Definition** -A function must be defined before it can be called. A function definition must have a name, a list of parameters, a return type, and a body. In Go, a `func` keyword is used to define a function. + +A function must be defined before it can be called. A function definition must have a name, and a body with optional list of parameters and a return type. In Go, the `func` keyword is used to define a function. A function can be defined using the following syntax: **Syntax:** + ```go func () { // function body is the code that is executed when the function is called @@ -355,20 +456,11 @@ func () { ``` **Examples:** -```go -package main - -import ( - "fmt" -) -// defining a function named `greet` that takes a string parameter and returns nothing -func greet(name string) { - fmt.Println("Hello, " + name) -} - -func main() { - greet("World") +```go +// defining a function named `greet` +func greet(name string) { // function name is `greet`, parameter is `name` of type string + fmt.Println("Hello, " + name) // function body enclosed in curly braces } ``` @@ -379,11 +471,13 @@ In the above example, we have declared a function named `greet` that takes a str A function can be called using the following syntax: **Syntax:** + ```go () ``` **Examples:** + ```go package main @@ -396,15 +490,22 @@ func greet(name string) { } func main() { - greet("World") // Calling the `greet` function + greet("World") // Calling the `greet` function } ``` +**Output:** + +```bash +Hello, World +``` + ### **4.3. Function Parameters** Function can have zero or more parameters. Parameters are variables that are used to pass values to a function. They are declared in the function definition. The values passed to a function are called arguments. **Examples:** + ```go package main @@ -412,27 +513,35 @@ import ( "fmt" ) -// defining a function named `greet` that takes a string parameter and returns nothing -func greet(name string) { - fmt.Println("Hello, " + name) +// defining a function named `printHelloWorld` without parameters +func printHelloWorld() { + fmt.Println("Hello, World!") } -// defining a function named `add` that takes two integer parameters and returns an integer -func add(a int, b int) int { - return a + b +// defining a function named `add` that takes two integer parameters +func add(a int, b int) { + fmt.Println(a + b) } func main() { - greet("World") // Calling the `greet` function - fmt.Println(add(1, 2)) // Calling the `add` function + printHelloWorld() // Calling the `printHelloWorld` function, without arguments + add(1, 2) // Calling the `add` function, with two arguments } ``` +**Output:** + +```bash +Hello, World! +3 +``` + ### **4.4. Function Return Type** A function can return zero or more values. The return-type of a function is declared in the function definition. If a function returns more than one value, then the return-types are enclosed in parentheses. **Examples:** + ```go package main @@ -447,7 +556,7 @@ func greet(name string) { // defining a function named `add` that takes two integer parameters and returns an integer func add(a int, b int) int { - return a + b // `return` keyword is used to return values from a function + return a + b // `return` keyword is used to return values from a function } // defining a function named `swap` that takes two integer parameters and returns two integers @@ -456,18 +565,19 @@ func swap(a int, b int) (int, int) { } func main() { - greet("World") // Calling the `greet` function - fmt.Println(add(1, 2)) // Calling the `add` function + greet("World") // Calling the `greet` function + fmt.Println(add(1, 2)) // Calling the `add` function - sum := add(3,6) // Calling the `add` function and storing the returned value in a variable `sum` + sum := add(3,6) // Also, the `add` function can be called and store the returned value in variable `sum` fmt.Println(sum) - x, y := swap(1, 2) // Calling the `swap` function and storing the returned values in variables `x` and `y` + x, y := swap(1, 2) // Calling the `swap` function and storing the returned values in variables `x` and `y` fmt.Println(x, y) } ``` **Output:** + ```bash Hello, World 3 @@ -481,11 +591,12 @@ In Go, a struct is a composite data type that represents a collection of fields. ### **5.1. Struct Definition** -`struct` keyword is used to define a struct in Go. +The `struct` keyword is used to define a struct in Go. A struct can be defined using the following syntax: **Syntax:** + ```go type struct { @@ -510,11 +621,13 @@ type Student struct { A struct can be initialized using the following syntax: **Syntax:** + ```go {} ``` **Examples:** + ```go package main @@ -530,16 +643,23 @@ type Student struct { func main() { // initializing a struct named `student` with three fields `name`, `phone number`, `address` - student := Student{"John Doe", 1234567890, "Kathmandu"} // order of values must match the order of fields - fmt.Println(student) // {John Doe 1234567890 Kathmandu} + student := Student{"John Doe", 1234567890, "Kathmandu"} // order of values must match the order of fields + fmt.Println(student) } ``` +**Output:** + +```bash +{John Doe 1234567890 Kathmandu} +``` + ### **5.3. Manipulation of Struct Fields** -A struct can have zero or more fields. Fields are variables that are used to store values in a struct. They are declared in the struct definition. Fields can be manipulated using the dot operator. +The struct fields are variables that are used to store values in a struct. They are declared in the struct definition. Fields can be manipulated using the dot operator. **Examples:** + ```go package main @@ -558,16 +678,26 @@ func main() { fmt.Println(student) // accessing a field of a struct - fmt.Println(student.name) // John Doe - fmt.Println(student.phoneNumber) // 1234567890 - fmt.Println(student.address) // Kathmandu + fmt.Println(student.name) + fmt.Println(student.phoneNumber) + fmt.Println(student.address) // changing the value of a field student.name = "Jane Doe" - fmt.Println(student.name) // Jane Doe + fmt.Println(student.name) } ``` +**Output:** + +```bash +{John Doe 1234567890 Kathmandu} +John Doe +1234567890 +Kathmandu +Jane Doe +``` + ## **6. Method** In Go, a method is a function that is associated with a type. It is useful for grouping related functions together. Methods are useful when you want to model real-world entities that have multiple behaviors. Methods are also known as functions with receivers. @@ -577,6 +707,7 @@ In Go, a method is a function that is associated with a type. It is useful for g A method can be defined using the following syntax: **Syntax:** + ```go func () () { // method body is the code that is executed when the method is called @@ -584,6 +715,7 @@ func () () { ``` **Examples:** + ```go package main @@ -605,11 +737,13 @@ In the above example we have defined a method associated with a struct named `Tr A method can be called using the following syntax: **Syntax:** + ```go .() ``` **Examples:** + ```go package main @@ -628,20 +762,29 @@ func (t Triangle) area() float64 { func main() { triangle := Triangle{base: 10, height: 5} - fmt.Println(triangle) // {10 5} + fmt.Println(triangle) // calling the `area` method - area := triangle.area() // triangle is the receiver - fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) // 25 + area := triangle.area() // triangle is the receiver + fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) } ``` +**Output:** + +```bash +{10 5} +Area of triangle is 25.00 +``` + ### **6.3. Function Vs Method** -A function is a block of code that performs a specific task. A method is a function that is associated with a type. A method is useful for grouping related functions together. A method is also known as a function with a receiver. +A function is a block of code that performs a specific task whereas a method is a function that is associated with a type. We can create multiple methods of same name associated to different types but the function name must be different (see example of [7.2](#L783)). Let's see the difference between a function and a method with the help of an example. +**Examples:** + ```go package main @@ -650,7 +793,7 @@ import ( ) // defining a function named `area` that takes two float64 parameters and returns a float64 -func area(base float64, height float64) float64 { +func getAreaOfTriangle(base float64, height float64) float64 { return 0.5 * base * height } @@ -660,24 +803,32 @@ type Triangle struct { } // defining a method named `area` that takes no parameters and returns a float64 -func (t Triangle) area() float64 { +func (t Triangle) getAreaOfTriangle() float64 { return 0.5 * t.base * t.height } func main() { // calling the `area` function - area := area(10, 5) - fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) // 25 + area := getAreaOfTriangle(10, 5) + fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) - triangle := Triangle{base: 10, height: 5} // creating a new instance of the `Triangle` struct - fmt.Println(triangle) // {10 5} + triangle := Triangle{base: 10, height: 5} // creating a new instance of the `Triangle` struct + fmt.Println(triangle) // calling the `area` method - area = triangle.area() // triangle is the receiver - fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) // 25 + area = triangle.getAreaOfTriangle() // triangle is the receiver + fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) } ``` +**Output:** + +```bash +Area of triangle is 25.00 +{10 5} +Area of triangle is 25.00 +``` + So, in the above example, we have defined a function named `area` that takes two float64 parameters and returns a float64. We have also defined a method named `area` that takes no parameters and returns a float64. The function and the method have the same name, but they are different because the function is not associated with any type, whereas the method is associated with the `Triangle` struct. ## **7. Interface** @@ -686,11 +837,12 @@ In Go, an interface is a collection of method signatures. It is useful for group ### **7.1. Interface Definition** -`interface` keyword is used to define an interface in Go. +The `interface` keyword is used to define an interface in Go. An interface can be defined using the following syntax: **Syntax:** + ```go type interface { @@ -716,6 +868,7 @@ In the above example, we have defined an interface named `Shape` with a method s A type implements an interface by implementing all the methods of the interface. A type can implement more than one interface. **Examples:** + ```go package main @@ -761,30 +914,31 @@ func (r Rectangle) perimeter() float64 { func main() { var triangle Shape = Triangle{base: 10, height: 5} - fmt.Println(triangle) // {10 5} + fmt.Println(triangle) - area := triangle.area() - fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) // 25 + area := triangle.area() // calling the `area` method associated with the `Triangle` struct + fmt.Println("Area of triangle is " + fmt.Sprintf("%.2f", area)) - perimeter := triangle.perimeter() - fmt.Println("Perimeter of triangle is " + fmt.Sprintf("%.2f", perimeter)) // 25 + perimeter := triangle.perimeter() // calling the `perimeter` method associated with the `Triangle` struct + fmt.Println("Perimeter of triangle is " + fmt.Sprintf("%.2f", perimeter)) var rectangle Shape = Rectangle{length: 10, width: 5} - fmt.Println(rectangle) // {10 5} + fmt.Println(rectangle) - area = rectangle.area() - fmt.Println("Area of rectangle is " + fmt.Sprintf("%.2f", area)) // 50 + area = rectangle.area() // calling the `area` method associated with the `Rectangle` struct + fmt.Println("Area of rectangle is " + fmt.Sprintf("%.2f", area)) perimeter = rectangle.perimeter() - fmt.Println("Perimeter of rectangle is " + fmt.Sprintf("%.2f", perimeter)) // 30 + fmt.Println("Perimeter of rectangle is " + fmt.Sprintf("%.2f", perimeter)) // calling the `perimeter` method associated with the `Rectangle` struct } ``` **Output:** + ```bash {10 5} Area of triangle is 25.00 -Perimeter of triangle is 25.00 +Perimeter of triangle is 26.18 {10 5} Area of rectangle is 50.00 Perimeter of rectangle is 30.00 @@ -793,16 +947,19 @@ Perimeter of rectangle is 30.00 ## What we have learned so far In this blog, we have learned how to declare, define, manipulate, and use the following terms in Go language: -- Rune and String +- Rune +- String - Array -- Function and Method -- Struct and Interface +- Function +- Struct +- Method +- Interface In the next blog, we will learn about some advanced topics like Errors, Goroutines, and Channels in Go language. -*Keep learning and keep practicing*. +*Keep learning and keep practicing* -**Stay tuned!!!**. +**Stay tuned!!!** ## References