Beginner's guide to Go



Get Set, Go! Explore the World of Go Programming.
If you’re ready to move on from JavaScript/Node and explore a faster, more efficient language, Go is the way to go. Go Lang offers superior performance and efficiency along with robust concurrency support, efficient compilation, and a powerful standard library. Go emerges as a compelling choice for developers seeking to elevate their coding prowess. So, if you’re seeking a language that not only promises speed but also fosters a seamless development experience, consider embarking on your journey with Go.
Introduction
Go also known as GoLang is an open-source programming language developed by Google. It is known for its simplicity, efficiency, and concurrency amongst other things. Go combines the speed of a compiled language with the ease of use of interpreted languages, making it ideal for building scalable and concurrent applications.
As Go is developed by Google, there’s a huge community supporting the language. Combined with a standard library that provides all the necessary functionalities and several third party packages Go is the ideal language for development.
First Program - Hello Go!
Let’s dive into writing your first Go program! Create a new file named "hello.go" and add the following code:
package main
import "fmt"
func main() {
fmt.Println("Hello Go!")
}
Save the file and run it using the command go run hello.go
. You should see the output "Hello, Go!" printed to the console.
Congratulations! You've just written and executed your first Go program.
Go Output Functions
Go has three functions to output text to the standard output provided by fmt
package - Print()
, Println()
, Printf()
.
- The
Print
function in Go is used to output text without appending a newline character. - The
Println
function in Go is used to output text with an appended newline character, which starts a new line after each call. - The
Printf
function in Go is used for formatted output. It allows you to specify placeholders%s
and%d
for strings and integers respectively, and provides a way to insert variables into the formatted string.
package main
import "fmt"
func main() {
name := "John"
age := 30
fmt.Print("Hello, ")
fmt.Println("World!")
fmt.Println("Happy learning!")
fmt.Printf("Name: %s, Age: %d\n", name, age)
}
- Additionally, the fmt package also contains three functions which are used to format strings or concatenate values into a single string without directly printing them to the standard output. These include
Sprint
,Sprintln
, andSprintf
. - The
Sprint
function in Go is used to concatenate strings without printing them to the standard output. It returns the concatenated string, which can then be stored in a variable or used directly. - The
Sprintln
function in Go is similar to sprint, but it appends a newline character after each string concatenation. It's useful for building multi-line strings without printing them directly. - The
Sprintf
function in Go is similar to printf, but it formats strings with placeholders and returns the formatted string instead of printing it directly. It's useful for generating formatted strings that can be stored in variables or used in further processing.
package main
import "fmt"
func main() {
name := "John"
age := 30
result1 := fmt.Sprint("Hello, ", "World!")
fmt.Println(result1)
result2 := fmt.Sprintln("Hello,")
result2 += fmt.Sprintln("World!")
fmt.Println(result2)
result3 := fmt.Sprintf("Name: %s, Age: %d", name, age)
fmt.Println(result3)
}
Go Input Functions
In Go, input operations typically involve reading user input from the standard input stream and processing it within your program. The fmt package provides several functions for handling input operations - Scan() , Scanln() and Scanf() .
- The
Scan
function reads user input from the standard input stream and stores it in the variable provided as arguments. - The
Scanln
function reads input from standard input, separated by whitespace, and stores it in the specified variables. - The
Scanf
function reads formatted input from standard input, similar to scanf in C. It takes a format string as the first argument, followed by variables where the parsed values will be stored.
package main
import "fmt"
func main() {
var num int
fmt.Scan(&num)
var name string
var age int
fmt.Scanln(&name, &age)
var name string
var age int
fmt.Scanf("%s %d", &name, &age)
}
When dealing with strings that span over multiple words or lines, it’s advisable to use the NewReader
function defined in the bufio
package. This function creates a buffered reader that allows reading input line by line.
- A new buffered reader is created using
bufio.NewReader()
function, which wraps the os.Stdin (standard input) stream. - This
reader
will allow reading input from the user line by line. - The
ReadString('\n')
method is called on thereader
to read input until a newline character('\n')
is encountered. - The input string is stored in the variable
text
, and any error that occurs during reading is stored in theerr
variable. - The
TrimSuffix()
function from thestrings
package is used to remove trailing newline characters('\n')
and carriage return characters('\r')
from the input string text.
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
text, err := reader.ReadString('\n')
if err != nil {
return ""
}
text = strings.TrimSuffix(text, "\n")
text = strings.TrimSuffix(text, "\r")
fmt.Println(text)
}
Variables
In Go, variables are declared using the var keyword followed by the variable name and type, like so:
var message string
message = "Hello, Go!"
var num int = 10
You can also declare a variable using :=
name := "John"
In Go, it is possible to declare multiple variables in the same line.
var a, b, c, d int = 1, 3, 5, 7
Types
Go is a statically typed language, which means that variables must have a specific type. Common types in Go include int
, string
, float
, and bool
.
In Go the variables which are declared without a value are given default values:
- int : 0
- float32/ float64 : 0.0
- bool : false
- string : “”
var a bool = true
var b int = 5
var c float64 = 3.14
var d string = "Go!"
Structs
Structs allow you to create custom data types with multiple fields. To declare a structure in Go, use the type
and struct
keywords:
package main
import "fmt"
type Person struct {
name string
age int
employed bool
}
func main() {
var pers1 Person
pers1.name = "Vibu"
pers1.age = 22
pers1.employed = true
fmt.Println(pers1)
}
To access any member of a structure, use the dot operator (.) between the structure variable name and the structure member.
Arrays
Arrays in Go have a fixed size that is determined at compile time. Once declared, the size cannot be changed. Arrays are used to store multiple values of the same type in a single variable, instead of declaring separate variables for each value.
package main
import "fmt"
func main() {
arr1 := [3]int{1, 2, 3}
var arr2 = [3]int{10, 20, 30}
fmt.Println("Array1:", arr1)
fmt.Println("Array1:", arr2)
}
- You can access a specific array element by referring to the index number. In Go, array indexes start at 0. That means that [0] is the first element, [1] is the second element, etc.
- You can also change the value of a specific array element by referring to the index number.
- If an array or one of its elements has not been initialized in the code, it is assigned the default value of its type.
- The
len()
function is used to find the length of an array. package main
import (
"fmt"
)
func main() {
var numbers [5]int
numbers[0] = 10
numbers[1] = 20
numbers[2] = 30
numbers[3] = 40
numbers[4] = 50
fmt.Println("Element at index 0:", numbers[0])
fmt.Println("Element at index 1:", numbers[1])
numbers[2] = 35
fmt.Println("Element at index 2 after modification:", numbers[2])
fmt.Println("Length of the array:", len(numbers))
}
Slices
Slices are dynamic and flexible. They are like dynamic arrays. Slices are created using square brackets [ ] without specifying a size, or by using the make() function.
package main
import "fmt"
func main() {
myslice := []int{1,2,3}
var slice []int
slice = append(slice, 1)
slice = append(slice, 2)
slice = append(slice, 3)
newslice := make([]int, 5, 10)
fmt.Println("Slice:", slice)
}
The append()
function is used to append elements at the end of the slice. You can access a specific slice element by referring to the index number.
In Go, there are two functions that can be used to return the length and capacity of a slice:
len()
function - returns the length of the slice (the number of elements in the slice)cap()
function - returns the capacity of the slice (the number of elements the slice can grow or shrink to)
The make()
function can also be used to create a slice. The second argument refers to the length of the slice and the third argument refers to its capacity. If the capacity parameter is not defined, it will be equal to length.
If-Else Statements
In Go, if-else
statements are used to control the flow of execution based on certain conditions. They allow you to execute different blocks of code depending on whether a condition evaluates to true or false.
package main
import "fmt"
func main() {
time := 22
if time < 10 {
fmt.Println("Good morning.")
} else if time < 20 {
fmt.Println("Good day.")
} else {
fmt.Println("Good evening.")
}
}
A point to note is that having the else brackets in a different line will raise an error.
Switch Statements
In Go, switch
statements provide a way to execute different blocks of code based on the value of an expression. They offer a concise and efficient alternative to multiple if-else
statements, especially when dealing with multiple conditions.
package main
import "fmt"
func main() {
day := "Saturday"
switch day {
case "Monday":
fmt.Println("It's Monday!")
case "Tuesday", "Wednesday", "Thursday":
fmt.Println("It's a weekday!")
case "Friday":
fmt.Println("TGIF! It's Friday!")
case "Saturday", "Sunday":
fmt.Println("It's the weekend!")
default:
fmt.Println("Invalid day!")
}
}
The default
keyword is optional. It specifies some code to run if there is no case
match. The switch
statement in Go is similar to the ones in C, C++, Java, and JavaScript. The difference is that it only runs the matched case so it does not need a break
statement.
Loops
In Go, loops are used to repeatedly execute a block of code until a specific condition is met. They provide a way to automate repetitive tasks and iterate over collections of data.
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
fmt.Println("Number: ", i)
}
}
- i:=0; — Initialize the loop counter (i), and set the start value to 0
- i < 5; — Continue the loop as long as i is less than 5
- i++ — Increase the loop counter value by 1 for each iteration
The continue
statement is used to skip one or more iterations in the loop. It then continues with the next iteration in the loop.
The break
statement is used to break/terminate the loop execution.
package main
import "fmt"
func main() {
for i:=0; i < 5; i++ {
if i == 3 {
continue
}
if i == 4 {
break
}
fmt.Println(i)
}
}
The range
keyword is used to more easily iterate over an array, slice or map. It returns both the index and the value.
package main
import "fmt"
func main() {
fruits := [3]string{"apple", "orange", "banana"}
for idx, val := range fruits {
fmt.Printf("%v\t%v\n", idx, val)
}
}
Maps
Maps are used to store data values in key:value pairs. Each element in a map is a key:value pair. A map is an unordered and changeable collection that does not allow duplicates. You can create a map like this:
package main
import "fmt"
func main() {
var a = map[string]string{"country": "India", "state": "Karnataka", "city": "Bengaluru"}
b := map[string]float64{"Interstellar": 9.9, "Oppenheimer": 9.4}
fmt.Printf("a\t%v\n", a)
fmt.Printf("b\t%v\n", b)
}
- You can also create a map by using the
make()
function. - Removing elements from a map is done using the
delete()
function.
package main
import "fmt"
func main() {
var a = make(map[string]string)
a["brand"] = "Ford"
a["model"] = "Mustang"
a["year"] = "1964"
delete(a,"model")
fmt.Printf(a["brand"])
}
Functions
Functions in Go are declared using the func keyword. Here's a simple function that adds two numbers: package main
import "fmt"
func add(a int, b int) (int) {
return a + b
}
func main() {
sum := add(5, 10)
fmt.Println(sum)
}
If you want the function to return a value, you need to define the data type of the return value (such as int
, string
, etc), and also use the return
keyword inside the function.
In Go, you can name the return values of a function. It can also return multiple values.
If the type of all the parameters is the same, you can just specify the type once.
If you(for some reason) do not want to use some of the returned values, you can add an underscore (_)
, to omit this value.
package main
import "fmt"
func operation(a, b int) (sum int, diff int, mul int) {
return a + b, a - b, a * b
}
func main() {
sum, diff, _ := operation(5, 10)
fmt.Println(sum, diff)
}
Methods
In Go, methods are functions associated with a particular type. Methods in Go provide a way to attach functions to structs or any other user-defined types. Here’s a brief overview of methods in Go and how to define them:
package main
import "fmt"
type Rectangle struct {
width, height float64
}
func (r Rectangle) area() float64 {
return r.width * r.height
}
func main() {
rect := Rectangle{width: 10, height: 5}
fmt.Println("Area of the rectangle:", rect.area())
}
The method in Go is similar to a function except it has a receiver defined before the name of the method. The receiver can be of any named type or a pointer to a named type. The receiver is similar to this
or self
in other programming languages.
Interfaces
Interfaces in Go allow you to define behavior that a type must implement. They define a set of method signatures, and any type that implements these methods implicitly satisfies the interface. Here’s an example of defining an interface and implementing it:
package main
import "fmt"
type Shape interface {
Area() float64
}
type Rectangle struct {
width, height float64
}
func (r Rectangle) Area() float64 {
return r.width * r.height
}
type Circle struct {
radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.radius * c.radius
}
func main() {
rect := Rectangle{width: 5, height: 3}
circle := Circle{radius: 2}
fmt.Println("Area of Rectangle:", rect.Area())
fmt.Println("Area of Circle:", circle.Area())
}
In this example:
- We define an interface
Shape
with a single method signatureArea()
float64
. - We define two structs
Rectangle
andCircle
, each with methods that satisfy theShape
interface. - We create instances of
Rectangle
andCircle
and call theArea()
method on them. - Both types (
Rectangle
andCircle
) satisfy theShape
interface because they implement theArea()
method, allowing us to treat them interchangeably whereShape
is expected.
Pointers
Pointers allow you to pass references to values rather than the values themselves. They allow you to indirectly access and manipulate the memory where values are stored. Pointers are used extensively in Go for efficient memory management and to avoid unnecessary copying of data. Here’s how you can use pointers in Go:
package main
import "fmt"
func main() {
var num int = 10
var ptr *int
ptr = &num
fmt.Println("Value of num:", num)
fmt.Println("Value of num through pointer:", *ptr)
*ptr = 20
fmt.Println("Modified value of num:", num)
}
In this example:
- We declare a variable
num
and initialize it with the value10
. -We declare a pointer variableptr
of type*int
. - We assign the memory address of
num
to the pointerptr
using the&
operator. - We access the value of num indirectly through the pointer using the
*
operator(*ptr)
. - We modify the value of
num
indirectly through the pointer, and the change is reflected in the original variable.
Packages
In Go, packages are used to organize code into reusable and modular units. They provide a way to encapsulate related functionality, promote code reuse, and simplify maintenance.
To define a package in Go, you create a directory with the same name as the package, and within that directory, you create one or more .go
files containing the package code. Each file in the package directory typically begins with a package
declaration specifying the name of the package.
package math_operations
func Add(a, b int) int {
return a + b
}
func Subtract(a, b int) int {
return a - b
}
- Importing Functions: To use functions from a package in your Go program, you import the package using the import keyword followed by the package path.
- Exporting Functions: In Go, functions and other identifiers are exported from a package if their names begin with a capital letter. So if the functions are to be exported to other packages, the function name must start with a capital letter.
package main
import (
"fmt"
"package/path/math_operations"
)
func main() {
fmt.Println("Addition:", math_operations.Add(5, 3))
fmt.Println("Subtraction:", math_operations.Subtract(10, 3))
fmt.Println("Multiplication:", math_operations.Multiply(4, 6))
}
In this example:
- We import the
math_operations
package and use its exported functionsAdd
andSubtract
. - We import and use the exported function
Multiply
from themath_operations
package. - By organizing code into packages and exporting functions, we achieve code reuse and maintainability in our Go programs.
Conclusion
Trying out new languages can totally level up how you solve problems as a developer because it makes you think in new ways. And being comfy with different tools is key because you never know when you’ll need a fresh approach for a tricky problem.
Now, let’s be real, learning Go might feel like a bit of a rollercoaster compared to JavaScript. But trust me, it’s worth it. Google made Go to handle big-scale stuff, which means it’s perfect for teams dealing with tons of work and heavy-duty server action. With some dedication and practice, you can really grasp the concepts and apply them in real-world situations.
Here are some of the links and courses which helped me in getting started with go:
Thankyou!