[go: up one dir, main page]

0% found this document useful (0 votes)
77 views63 pages

Go Essentialspdf

Uploaded by

Parth Arora
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
77 views63 pages

Go Essentialspdf

Uploaded by

Parth Arora
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 63

Sold to

partharora2233@gmail.com
Introduction to Go - Mastering Backend

If you want a breadth- rst view of the Go programming language ecosystem, this

practical guide provides the essential background to write clear and idiomatic Go.

You can follow this guide to learn to Go fast, but that will demand that you are

already a programmer.

Get GIN Ultimate Guide


What you will learn:

Chapter 1. Getting Started with Gin


Chapter 2. Building with Gin: Middleware, Routing, and Controllers
Chapter 3. Data Handling and Advanced Functionality
Chapter 4. Milestone project

Grab Your Copy Now (20% discount)

Introduction to Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 1
Introduction to Go

You are expected to follow this guide with a computer, so you can practice and

understand what you are learning easily. Without wasting much time, let's get

started.

Introduction to Go
If you want a breadth- rst view of the Go programming language ecosystem, this

practical guide provides the essential background to write clear and idiomatic Go.

You can follow this guide to learn to Go fast, but that will demand that you are

already a programmer.

You are expected to follow this guide with a computer, so you can practice and

understand what you are learning easily. Without wasting much time, I think we

should get started.

Benefits of Go in Software Engineering


The Go programming language has gained signi cant popularity recently due to its

simplicity, e ciency, and performance. This section explores some key bene ts of

using Go in software engineering.

Quick Build Time


One of the standout features of Go is its impressively fast build times. The Go

compiler is designed to compile code quickly, making the development work ow

e cient. This is especially important in large projects requiring frequent builds

during development.

Introduction to Go Sold to
partharora2233@gmail.com
Page 2
Introduction to Go

Dependency Management
Go has a built-in dependency management system called "go modules." This

system allows developers to manage their project dependencies e ectively. With

go modules, you can easily version and track the external packages your project

relies on, ensuring that your code remains stable and consistent.

Ease of Understanding
Go is designed to be straightforward to read. It has a simple and clean syntax that

emphasizes clarity and readability. This makes it easier for developers to understand

code, leading to more maintainable and collaborative projects.

Cross Compilation
Go supports cross-compilation, which means you can build executable binaries for

di erent platforms and architectures from a single codebase. This feature is

valuable for building applications on various operating systems or architectures.

Garbage Collection
Go incorporates automatic memory management through a garbage collector. This

feature helps developers avoid common pitfalls related to manual memory

management and reduces the risk of memory leaks.

Introduction to Go Sold to
partharora2233@gmail.com
Page 3
Introduction to Go

Concurrency
Ah, Yes, the Trademark Feature: Concurrency is one of the de ning features of Go.

Go provides native support for concurrency through goroutines and channels.

Goroutines are lightweight threads that allow developers to execute concurrent

tasks e ciently. Channels facilitate communication and synchronization between

goroutines, making it easier to build concurrent systems.

This guide's Advanced Go section will give you a better concurrency introduction.

Introduction to Go Sold to
partharora2233@gmail.com
Page 4
Introduction to Go

Essential Resources for Writing Go Code


To become pro cient in writing the Go language, it's essential to use the various

resources available to Go developers. Some of the important ones are described in

this section.

The Go Playground
The Go Playground is a web-based tool the Go team provides that allows you to

write, run, and share Go code snippets online. It's an excellent resource for quickly

testing and experimenting with Go code without needing a local development

environment. You can access the Go Playground here.

The Go Language Specification


Understanding the o cial Go Language Speci cation is crucial to mastering the

language. The speci cation de nes the Go programming language's syntax,

semantics, and behavior. It is the de nitive source for understanding how Go code

should be written and executed. You can nd the Go Language Speci cation here.

The Package Repository


The Go community maintains a central repository of Go packages called the "Go

Module Repository." It hosts thousands of open-source libraries and packages

contributed by developers worldwide. You can nd useful packages to include in

your projects on the Go Module Repository website here.

Introduction to Go Sold to
partharora2233@gmail.com
Page 5
Introduction to Go

The Standard Library


Go has a robust standard library that o ers a wide range of functions and packages

for common programming tasks. Familiarizing yourself with the standard library is

essential, as it can save you time and e ort when implementing various

functionalities in your projects. You can explore the Go Standard Library

documentation here.

The Official Go Blog


The o cial Go blog is an excellent resource for staying up-to-date with the latest

news, updates, and announcements related to the Go programming language. The

blog regularly publishes informative articles, tutorials, and insights from the Go team

and experienced developers. You can access the o cial Go blog here.

Introduction to Go Sold to
partharora2233@gmail.com
Page 6
Setting up Go Environment - Mastering Backend

Setting up Go Environment
Before writing Go code, you must set up your Go development environment on

your computer. This involves installing Go on your system and con guring it

properly. The process is straightforward, and the Go team provides installation

packages for various operating systems.

Step 1. Downloading Go
Visit the o cial Go download website and download the stable release for your

computer.

Please choose the appropriate installer for your system, download it, and run the

installer. The installation process typically involves accepting the license agreement

and choosing a destination path for the Go installation. Once the installation is

complete, it will be available on your system.

Step 2. Setting Environment Variables


After installing Go, you must set some environment variables to make it functional

in your command-line interface. The most important environment variables are:

Setting up Go Environment - Mastering Backend Sold to


partharora2233@gmail.com
Page 7
Setting up Go Environment - Mastering Backend

GOROOT : This variable should point to the location where Go is installed on


your system. The installer usually sets this automatically, but you can set it
manually if it doesn't.

GOPATH : This variable de nes the workspace directory for your Go projects. All
your Go code and dependencies will be organized within this workspace. You
can choose a directory on your system as your workspace and set the GOPATH
variable accordingly.

PATH : Add the Go binary directory to your system's PATH environment variable
to use the Go tools and binaries from any directory. This allows you to run Go
commands from the command line easily.

Con rm these variables with the Command:

go env

Step 3. Verifying the Installation


Once the environment variables are set, you can verify that Go is installed correctly.

Open your terminal (or Command prompt) and type the following Command:

go version

This Command should display the installed Go version, con rming that Go is

correctly set up on your system.

Step 4. Workspace Structure

Setting up Go Environment - Mastering Backend Sold to


partharora2233@gmail.com
Page 8
Setting up Go Environment - Mastering Backend

Go follows a speci c workspace structure. Inside your GOPATH, create the following

directories:

src : This directory contains the source code of your Go projects and their
packages. When you run a go get Command, the imported package will live
locally in this directory.

bin : Go binaries (executable les) will be placed in this directory when you
build your projects.

pkg : Compiled package les will be stored here after building your projects.

Step 5. IDE or Text Editor


Finally, choose an Integrated Development Environment (IDE) or a text editor to

write your Go code. Some popular options for seamless Go development include:

Visual Studio Code with the o cial "Go" extension

GoLand or any IntelliJ IDE with the Go plugin

Vim with the "vim-go" plugin

If you want a quick and easy build, the GoLand IDE is a more suitable choice for

beginners. With your Go environment properly set up, you can write your rst Go

program and explore the language's features. As you progress through this guide,

use the resources mentioned earlier and practice to become pro cient in Go

programming.

Setting up Go Environment - Mastering Backend Sold to


partharora2233@gmail.com
Page 9
Constructs of Go Lang - Mastering Backend

Constructs of Golang
The Go compiler provides tools or commands for interacting with Go code. Let's

take a look at them in this section.

Go language syntax
Package Declaration

Every Go le belongs to a package and must start with a package declaration. The

package declaration determines whether the code in that le will be part of an

executable or a library. For example:

package main // For executable les

package mypackage // For library les

Importing Packages

To use functionality from other packages, you need to import them. Import

statements are typically placed at the beginning of the le after the package

declaration. For example:

package main

import (
"fmt"
"math"
)

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 10
Constructs of Go Lang - Mastering Backend

Function Declarations

Functions in Go are de ned using the func keyword. The basic syntax for a function

declaration is as follows:

func functionName(parameter1 type1, parameter2 type2) returnType {

// Function body

return result

Control Structures
Go provides standard control structures, such as if , for , switch , and select , which we

will cover later. The syntax for these control structures is similar to other C-like

languages.

Comments
Go supports both single-line and multi-line comments. Single-line comments start

with // , while multi-line comments are enclosed within /* */ . For example:

// This is a single-line comment

/*

This is a

multi-line comment

*/

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 11
Constructs of Go Lang - Mastering Backend

Adding visibility to identifiers


Identi ers include variable names, custom data types, functions, and other

constructs in Go. When writing modular Go code (we will see what that means later.

Go uses capitalization to determine if a package-level identi er is visible outside of

the package where it is declared.

An identi er whose Name starts with an uppercase letter is exported. Conversely, an

identi er whose Name begins with a lowercase letter or underscore can only be

accessed from within the package where it is declared.

var Name string // can be accessed anywhere in the codebase.

var localName string // can only be accessed in the source le it is declared in.

Note that Go developers use camel case for naming identi ers instead of snake

case, as in Python or Rust.

The go Command
The Go command is a fundamental tool in Go that serves various purposes,

including compiling and running Go programs, managing packages, and performing

various development tasks. Here are some common go commands:

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 12
Constructs of Go Lang - Mastering Backend

go build : Compiles the Go program and generates an executable binary. If there


are no errors, this will create an executable le with the same name as the
directory.

go run : Compiles and runs a Go program in a single step. This is useful for
quickly testing small programs.

go install : Compiles and installs the Go package or program. If the package is a


command (an executable), it will be placed in the bin directory de ned in your
GOPATH.

go get : Fetches and installs packages from the remote repository.

go test : Runs tests associated with the current package.

For more details and a full list of go commands, you can execute go help or go help <

Command> in your terminal. However, we will use some of them in the Milestone

Project section in this guide.

Getting Third-Party Go Tools


Go is an open-source language. This means that the Go community has developed

a plethora of third-party tools that enhance the Go development experience. To get

these tools, you can use the go get Command followed by the URL or import path of

the tool.

For example:

go get github.com/golangci/golangci-lint/cmd/golangci-lint

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 13
Constructs of Go Lang - Mastering Backend

This Command will download and install the golangci-lint tool, a popular static code

analysis tool for Go.

Staying Up to Date
To stay up to date with the latest changes and improvements, you should keep

your Go installation updated. Fortunately, updating Go is straightforward:

First, you can check if a new version is available by visiting the Go website or
using the Go version command.

If there is a new version, download the installer for your operating system from
the o cial Go website and run it.

The installer will detect your current Go installation and perform the update.

I'd like to point out that updating your Go environment periodically is essential to

take advantage of bug xes, performance improvements, and new features

introduced in the latest versions.

Variable and Constant Declaration


In Go, you declare variables and constants explicitly, indicating their types. This

strong typing helps ensure type safety and clarity in code. Let's explore how to

declare and use variables and constants in Go:

Variable Declaration

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 14
Constructs of Go Lang - Mastering Backend

To declare a variable, use the var keyword followed by the variable name, its type,

and an optional initial value. If you don't specify the value, the Go compiler will

initialize it to the zero value of that variable type.

You can make a short assignment declaration if you declare the variable in a

function. When you do so, the Go compiler assumes the variable type, allowing you

only to specify the variable Name and the value it stores. For example:

package main
import "fmt"

func main() {

var name string // initialized as an empty string:""

name = "John"// name string now becomes "John"

fmt.println("Name:", name) // Output: Name: John

var age int = 30

fmt.Println("Age:", age) // Output: Age: 30

// You can also use the short variable declaration syntax

City := "New York"

fmt.Println("City:", city) // Output: City: New York

In a backend system, you often need to work with di erent data types. You declare

variables explicitly, indicating their types for clarity and type safety.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 15
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
var databaseURL string
databaseURL = "mongodb://localhost:27017/mydb"
fmt.Println("Database URL:", databaseURL)

var port int = 8080


fmt.Println("Port:", port)

// Using the short variable declaration syntax


serverName := "Backend Server"
fmt.Println("Server Name:", serverName)
}

Multiple Variable Declaration


Go allows you to declare multiple variables in a single statement. You can do

variable declaration in two ways and in both local and global scopes. You can also

do a short assignment declaration with multiple variables.

Software systems frequently deal with multiple variables simultaneously, especially

while initializing settings or con gurations.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 16
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
var (
maxConnections int = 100
timeoutSeconds int = 30
)

fmt.Println("Max Connections:", maxConnections)


fmt.Println("Timeout Seconds:", timeoutSeconds)
}

Constant Declaration
To declare a constant, use the const keyword followed by the constant Name, its

type (optional), and the constant's value. Constants are preferably declared globally

(outside of functions) but can be declared globally. Unlike variables, constants must

be initialized at the time of declaration and cannot be changed later.

In a backend system, you might have xed values that remain constant throughout

the program's execution. Declare these as constants.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 17
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
const (
MaxRetries = 3
Bu erSize = 1024
RequestType = "POST"
)

fmt.Println("Max Retries:", MaxRetries)


fmt.Println("Bu er Size:", Bu erSize)
fmt.Println("Request Type:", RequestType)
}

In software engineering, it is common to see port numbers and environment

variables declared as constants.

Enumerated Constants
Go also supports enumerated constants using the iota keyword. Enumerated

constants are auto-incremented integer values commonly used to de ne a set of

related named constants. For example, say we have a backend system that allows

users to subscribe to services; here is what our subscription model will look like:

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 18
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
const (
Basic = iota // 0
Premium // 1 (automatically incremented from iota)
Gold // 2 (automatically incremented from iota)
Enterprise // 3 (automatically incremented from iota)
)

fmt.Println("Available subscription packages and index:")


fmt.Println("Basic:", Basic)
fmt.Println("Premium:", Premium)
fmt.Println("Gold:", Gold)
fmt.Println("Enterprise:", Enterprise)
}

In this example, the iota keyword creates a series of integer values.

Determining and using variables and constants is essential for writing e ective and

maintainable Go code. Following the explicit type declaration approach can make

your code more robust and easier to understand, especially in large projects.

Data Types and Composite Types


Go provides a range of built-in and composite data types, making working with data

in di erent scenarios easy.

Primitive Data Types


Go o ers several primitive data types that represent basic values. Here are some

commonly used primitive data types in day-to-day Go programming:

Integers

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 19
Constructs of Go Lang - Mastering Backend

Used for representing whole numbers. Depending on the architecture, you have int

and uint types with di erent sizes, such as int8 , int16 , int32 , int64 , uint8 , uint16 ,

uint32 , and uint64 .

package main

import "fmt"

func main() {
var userID int64 = 12345
fmt.Println("User ID:", userID)

var requestCount uint32 = 100


fmt.Println("Request Count:", requestCount)
}

Floating-Point Numbers
Used for representing decimal numbers. You have oat32 and oat64 data types.

package main

import "fmt"

func main() {
var pi oat64 = 3.14159
fmt.Println("Value of Pi:", pi)
}

Strings

Used for representing text and characters.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 20
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
username := "john_doe"
fmt.Println("Username:", username)
}

Boolean

Used for representing true/false values.

package main

import "fmt"

func main() {
isLoggedIn := true
fmt.Println("Logged in?", isLoggedIn)
}

Composite Types
Go provides composite types that allow you to group multiple values together.

Arrays

Fixed-size collections of elements of the same type.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 21
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
var numbers [5]int
numbers = [5]int{1, 2, 3, 4, 5}

fmt.Println("Numbers:", numbers) // Output: Numbers: [1 2 3 4 5]


}

Slices

Dynamic and exible views of underlying arrays.

package main

import "fmt"

func main() {
numbers := []int{1, 2, 3, 4, 5}

fmt.Println("Numbers:", numbers) // Output: Numbers: [1 2 3 4 5]


}

Maps

Unordered collections of key-value pairs.

package main

import "fmt"

func main() {
userAge := map[string]int{
"John": 30,
"Jane": 25,
}

fmt.Println("User Ages:", userAge) // Output: User Ages: map[Jane:25 John:30]


}

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 22
Constructs of Go Lang - Mastering Backend

Structs

Custom data types with named elds that group related data.

package main

import "fmt"

type User struct {


ID int
Name string
Email string
IsActive bool
}

func main() {
user := User{ID: 1, Name: "John Doe", Email: "john@example.com", IsActive: true}

fmt.Println("User:", user) // Output: User: {1 John Doe john@example.com true}


fmt.Println("User Name:", user.Name) // Output: User Name: John Doe
}

It is important to familiarize yourself with Maps, Structs, and Slices, as they are

frequently used in software engineering.

Control Structures
Software systems use control structures to make decisions and control the code

ow. Go provides several control structures to handle di erent scenarios e ciently.

Let's explore these control structures with relevant examples.

If and Else
The if and else statements allow you to perform conditional execution in your code.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 23
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
age := 30

if age >= 18 {
fmt.Println("You are an adult.")
} else {
fmt.Println("You are a minor.")
}
}

For Loops
Go o ers four types of loop, each serving a speci c purpose in backend

development.

Classic For Loop

The classic for loop allows you to iterate over a range of values.

package main

import "fmt"

func main() {
for i := 1; i <= 5; i++ {
fmt.Println("Iteration:", i)
}
}

For Loop with a Single Condition

This type of for loop acts like a while loop, where the loop continues as long as the

condition is true.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 24
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
i := 1

for i <= 5 {
fmt.Println("Iteration:", i)
i++
}
}

For Loop with Range

A for loop with range is commonly used to iterate over elements of an array , slice ,

map , or string .

package main

import "fmt"

func main() {
numbers := []int{1, 2, 3, 4, 5}

for index, value := range numbers {


fmt.Printf("Index: %d, Value: %d\\n", index, value)
}
}

Infinite Loop

An in nite loop continues inde nitely until it encounters a break statement or exits

the program.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 25
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
i := 1

for {
fmt.Println("In nite Loop:", i)
i++

if i > 5 {
break
}
}
}

The for loop with range keyword is usually used in software engineering, as well as

the complete style for loop.

Switch and Case


The switch statement allows you to create multi-way conditionals in your backend

code.

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 26
Constructs of Go Lang - Mastering Backend

package main

import "fmt"

func main() {
day := "Sunday"

switch day {
case "Monday":
fmt.Println("It's the start of the week.")
case "Friday":
fmt.Println("It's the end of the workweek.")
case "Saturday", "Sunday":
fmt.Println("It's the weekend.")
default:
fmt.Println("It's a regular weekday.")
}
}

Constructs of Go Lang - Mastering Backend Sold to


partharora2233@gmail.com
Page 27
Functions in Go - Mastering Backend

Functions in Go
In Go, functions are treated as rst-class citizens, allowing you to pass them as

arguments, return them from other functions, and even create anonymous

functions.

The Go compiler automatically recognizes the main function we have used as the

entry-point function where all relevant functions and operations are carried out.

By the rule of thumb, a project that must be built must have a main function.

Let's see how other functions are written. Below is a basic function that has an

input, an output, and a body. Here's an example:

package main

import "fmt"

// add accepts two input parameters of type int, and returns a single output of type int.
func add(a, b int) int {
return a + b
}

func main() {
// add function is called and used here.
result := add(10, 20)
fmt.Println("Sum:", result) // Output: Sum: 30
}

Just so you know, a function with output speci ed must have a return statement by

the rule of thumb. Also, when calling a function, you must satisfy its required

number of parameters to use it.

Functions in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 28
Functions in Go - Mastering Backend

In Go, you can assign functions to variables and use them like any other variable.

This is particularly useful when passing functions as arguments to other functions.

In this example, we use a function variable to calculate the area of a rectangle:

package main

import "fmt"

type calculate func( oat64, oat64) oat64

func rectangleArea(length, width oat64) oat64 {


return length * width
}

func main() {
var area calculate
area = rectangleArea

length, width := 5.0, 10.0


result := area(length, width)

fmt.Printf("Rectangle Area with length %.2f and width %.2f: %.2f\n", length, width, result)
// Output: Rectangle Area with length 5.00 and width 10.00: 50.00
}

Functions in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 29
Stacks and Pointers in Go

Stacks and Pointers in Go


Understanding the Go language's memory management and pointer behavior is

crucial for writing e cient and performant code. Let's explore the Go language

mechanics related to stacks and pointers.

Stack vs. Heap


Go uses a combination of stack and heap for memory management. The stack is

used for storing local variables and function call frames. It has a xed size and is

managed automatically by the Go runtime. When a function is called, its local

variables are allocated on the stack, and when the function returns, the stack space

is freed.

On the other hand, the heap is used for dynamically allocated memory. Variables

created using new() or make() functions are allocated on the heap. The heap

provides more exibility for managing memory but requires explicit garbage

collection to free memory that is no longer in use.

Pointers in Go
Pointers are variables that store the memory address of another variable. They

indicate mutable parameters. They allow you to directly access and modify the

value of the variable they point to. Pointers are essential for working with large data

structures, avoiding unnecessary memory copies, and passing values by reference.

Stacks and Pointers in Go Sold to


partharora2233@gmail.com
Page 30
Stacks and Pointers in Go

In Go, you can declare a pointer using the symbol followed by the variable type it

points to. To access the value stored at the memory address pointed by a pointer,
use the symbol again.

package main

import "fmt"

func main() {
x := 10
ptr := &x // ptr is a pointer to the memory address of x

fmt.Println("Value of x:", x) // Output: Value of x: 10


fmt.Println("Value at ptr:", *ptr) // Output: Value at ptr: 10

*ptr = 20 // Change the value at the memory address


fmt.Println("Updated x:", x) // Output: Updated x: 20
}

Pointers in Function Arguments


Passing pointers as function arguments allows you to modify the original values

directly rather than working with a copy of the data.

Stacks and Pointers in Go Sold to


partharora2233@gmail.com
Page 31
Stacks and Pointers in Go

package main

import "fmt"

func double(number *int) {


*number *= 2
}

func main() {
x := 10
fmt.Println("Original value of x:", x) // Output: Original value of x: 10

double(&x)
fmt.Println("Doubled value of x:", x) // Output: Doubled value of x: 20
}

Pointers and Slices


Slices in Go are references to an underlying array. When you pass a slice to a

function, you're passing a reference to the same underlying array, not a copy of the

data.

package main

import "fmt"

func modifySlice(slice []int) {


slice[0] = 100
}

func main() {
numbers := []int{1, 2, 3, 4, 5}
fmt.Println("Original Slice:", numbers) // Output: Original Slice: [1 2 3 4 5]

modifySlice(numbers)
fmt.Println("Modi ed Slice:", numbers) // Output: Modi ed Slice: [100 2 3 4 5]
}

Stacks and Pointers in Go Sold to


partharora2233@gmail.com
Page 32
Stacks and Pointers in Go

You should learn deeply about memory management in Go as it is crucial in real-

world systems. This is because if pointers are not used carefully, they can hinder

the application's performance and overload the Go garbage collector.

Stacks and Pointers in Go Sold to


partharora2233@gmail.com
Page 33
Go Custom Types, Methods, and Interfaces

Go Custom Types, Methods, and Interfaces


In Go, custom types, methods, and interfaces are crucial in designing well-

organized and reusable code. They allow you to de ne abstractions and behaviors

that t your application requirements. Let's explore these concepts while handling

user authentication to demonstrate custom types, methods, and interfaces in Go.

Custom Types
We may use custom types to provide more context and safety when working with

user-related data in user authentication.

package main

import "fmt"

type UserID int64 //


type UserName string

type User struct {


ID UserID
Name UserName
}

func main() {
user := User{
ID: 123456,
Name: "john_doe",
}

fmt.Println("User ID:", user.ID)


fmt.Println("Username:", user.Name)
}

Go Custom Types, Methods, and Interfaces Sold to


partharora2233@gmail.com
Page 34
Go Custom Types, Methods, and Interfaces

Methods
Go allows you to de ne methods on types, including custom types. Methods are

functions that have a receiver argument, which speci es the type the method

operates on. This enables you to de ne behaviors that are closely associated with

the type.

For ease of explanation, let's de ne a method for calculating the area of a circle:

package main

import "fmt"

type Circle struct {


radius oat64
}

func (c Circle) calculateArea() oat64 {


return 3.14 * c.radius * c.radius
}

func main() {
circle := Circle{radius: 5}

fmt.Printf("Circle Area with radius %.2f: %.2f\n", circle.radius, circle.calculateArea())


}

In simple terms, we made the area function to be a property of a type of object

called a Circle with a radius. The (c Circle) declaration before the function name is

called the receiver, which shows us that the Circle type supports the function

calculateArea .

Methods can be useful for implementing user-related behaviors, such as hashing

passwords for secure storage. Let's see a more practical example:


Go Custom Types, Methods, and Interfaces Sold to
partharora2233@gmail.com
Page 35
Go Custom Types, Methods, and Interfaces

package main

import (
"fmt"
"golang.org/x/crypto/bcrypt"
)

type User struct {


ID int64
Username string
Password string
}

func (u *User) HashPassword() error {


hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}

func main() {
user := User{
ID: 1,
Username: "john_doe",
Password: "secretpassword",
}

err := user.HashPassword()
if err != nil {
fmt.Println("Error hashing password:", err)
return
}

fmt.Println("Hashed Password:", user.Password)


}

Go Custom Types, Methods, and Interfaces Sold to


partharora2233@gmail.com
Page 36
Go Custom Types, Methods, and Interfaces

Here, we made HashPassword a function attributed to a User. Notice that in the

shapes code, an asterisk is absent before the function name, but an asterisk is

present in the password hashing code.

Go uses parameters of pointer type to indicate the function might modify that

parameter. The same rules apply to method receivers, too. They can be pointer

receivers (the type is a pointer) or value receivers (the type is a value type). The
following rules help you determine when to use each kind of receiver:

If your method modi es the receiver, you must use a pointer receiver.

If your method needs to handle nil instances, it must use a pointer receiver.

You can use a value receiver if your method doesn't modify the receiver.

Whether or not you use a value receiver for a method that doesn't modify the

receiver depends on the other methods declared on the type. When a type

has any pointer receiver methods, a common practice is to be consistent and use

pointer receivers for all methods, even the ones that don't modify the receiver.

Interfaces
Interfaces in Go provide a way to de ne a set of methods that a type must

implement to be considered as implementing that interface. This enables

polymorphism and allows you to write more generic and exible code. Let's extend

our calculateArea code to use an interface:

Go Custom Types, Methods, and Interfaces Sold to


partharora2233@gmail.com
Page 37
Go Custom Types, Methods, and Interfaces

package main

import "fmt"

// Shape interface stores the functions/operations possible on Shapes.


type Shape interface {
calculateArea() oat64
}

// Circle is a shape with a radius.


// It inherits Shape properties, meaning it's calculateArea can be performed on it.
type Circle struct {
radius oat64
}

// calculateArea extends all properties of Shape interface on an instance of a Circle.


// It calculates the area of the instance.
func (c Circle) calculateArea() oat64 {
return 3.14 * c.radius * c.radius
}

// Square is another shape with side.


// Likewise, it inherits Shape properties.
type Square struct {
side oat64
}

// calculateArea extends all properties of Shape interface on an instance of a Square.


// It calculates the area of the instance.
func (s Square) calculateArea() oat64 {
return s.side * s.side
}

// printArea is a function that accepts any shape, doesn't modify it, but prints out it's area.
func printArea(shape Shape) {
fmt.Printf("Area: %.2f\n", shape.calculateArea())
}

Go Custom Types, Methods, and Interfaces Sold to


partharora2233@gmail.com
Page 38
New project

func main() {
circle := Circle{radius: 5}
square := Square{side: 4}

printArea(circle) // Output: Area: 78.50


printArea(square) // Output: Area: 16.00
}

New project Sold to


partharora2233@gmail.com
Page 39
Go Custom Types, Methods, and Interfaces

Interfaces can be used to create a common authentication service for di erent

authentication providers.

package main

import "fmt"

type AuthProvider interface {


Authenticate(username, password string) (bool, error)
}

type LocalAuthProvider struct{}

func (a *LocalAuthProvider) Authenticate(username, password string) (bool, error) {


// Logic for authenticating against a local user database
return true, nil
}

type ExternalAuthProvider struct{}

func (a *ExternalAuthProvider) Authenticate(username, password string) (bool, error) {


// Logic for authenticating against an external authentication service
return true, nil
}

func AuthenticateUser(authProvider AuthProvider, username, password string) (bool, error) {


return authProvider.Authenticate(username, password)
}

func main() {
localAuthProvider := &LocalAuthProvider{}
externalAuthProvider := &ExternalAuthProvider{}

username, password := "john_doe", "secretpassword"

localAuthResult, _ := AuthenticateUser(localAuthProvider, username, password)


fmt.Println("Local Authentication Result:", localAuthResult)

externalAuthResult, _ := AuthenticateUser(externalAuthProvider, username, password)


fmt.Println("External Authentication Result:", externalAuthResult)
}

Go Custom Types, Methods, and Interfaces Sold to


partharora2233@gmail.com
Page 40
Go Custom Types, Methods, and Interfaces

In this example, we create two authentication providers, LocalAuthProvider and

ExternalAuthProvider , that implement the AuthProvider interface.

Using the same function call, we can use the AuthenticateUser function to authenticate

users against di erent providers. Running this code on the Go Playground will print

out a hashed form of the password.

In general, remember that your code should accept interfaces and return structs.

Go Custom Types, Methods, and Interfaces Sold to


partharora2233@gmail.com
Page 41
Error Handling in Go - Mastering Backend

Error Handling in Go
Error handling is a critical aspect of software engineering, as it helps ensure the

reliability and stability of your applications. Go promotes a simple yet e ective error-

handling approach, making identifying and handling errors consistently easier. Let's

explore error handling in Go:

Error Type
In Go, errors are represented by the built-in error type, which is an interface that

includes a single method:

type error interface {


Error() string
}

To create an error, you can use the errors.New function, which returns an error with

the given error message:

Error Handling in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 42
Error Handling in Go - Mastering Backend

package main

import (
"errors"
"fmt"
)

func divide(x, y int) (int, error) {


if y == 0 {
return 0, errors.New("division by zero")
}
return x / y, nil
}

func main() {
result, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err) // Output: Error: division by zero
} else {
fmt.Println("Result:", result) // Output: Result: 5
}
}

Custom Errors
You can also create custom error types by implementing the error interface for a

struct.

Error Handling in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 43
Error Handling in Go - Mastering Backend

package main

import "fmt"

type CustomError struct {


message string
}

func (ce CustomError) Error() string {


return ce.message
}

func process() error {


return CustomError{message: "custom error occurred"}
}

func main() {
err := process()
if err != nil {
fmt.Println("Error:", err) // Output: Error: custom error occurred
}
}

Error Wrapping
Go 1.13 introduced the errors.Wrap function from the "errors" package allows you to

add context to errors, making them more informative.

Error Handling in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 44
Error Handling in Go - Mastering Backend

import (
"fmt"
"github.com/pkg/errors"
)

func process() error {


return errors.Wrap(cause(), "error occurred while processing data")
}

func cause() error {


return errors.New("root cause error")
}

func main() {
err := process()
if err != nil {
fmt.Println("Error:", err) // Output: Error: error occurred while processing data: root cause error
}
}

Using errors.Wrap , you can wrap an error with additional context at di erent

application levels, providing more useful information for debugging and

understanding the error's origin.

Error Handling with Multiple Returns


In Go, it is common to use multiple return values, where the last value is typically an

error. This approach allows you to handle both the result and the error

simultaneously.

Error Handling in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 45
Error Handling in Go - Mastering Backend

package main

import (
"fmt"
"os"
)

func readFile( lePath string) ([]byte, error) {


le, err := os.Open( lePath)
if err != nil {
return nil, err
}
defer le.Close()

data := make([]byte, 1024)


n, err := le.Read(data)
if err != nil {
return nil, err
}
return data[:n], nil
}

func main() {
content, err := readFile("sample.txt")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("File Content:", string(content))
}

Using this multiple return value pattern lets you quickly detect and handle errors at

each stage of your code, making it easier to recover from unexpected situations

and providing better feedback to users and developers.

Panic and Recover

Error Handling in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 46
Error Handling in Go - Mastering Backend

Go has the panic and recovery mechanisms for exceptional cases. panic is used to halt

the normal ow of the program and trigger a panic. In contrast, recover is used to

catch and handle panics, allowing the program to continue execution gracefully.

It is important to use panic and recover sparingly and only for exceptional situations,

such as unrecoverable errors.

package main

import "fmt"

func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()

// Example of triggering a panic


panic("something went wrong")

fmt.Println("This line will not be executed.")


}

Error handling in Go follows a pragmatic and straightforward approach, allowing you

to create reliable and robust backend systems.

Error Handling in Go - Mastering Backend Sold to


partharora2233@gmail.com
Page 47
Essentials on Packaging Go Code

Essentials on Packaging Go Code


Properly organizing and packaging Go code is essential for creating maintainable

and reusable backend applications. This section explores the key concepts related

to packaging Go code, including the go.mod le, imports and exports, Go's naming

conventions, and organizing Go codebases e ectively.

The go.mod File


The go.mod le is the centerpiece of Go's module system, introduced in Go 1.11. It

serves as the project's dependency management le and helps in versioning and

resolving dependencies. When you create a new Go module, the go.mod le is

automatically generated, containing the module's name and its dependencies.

module github.com/happycoder/demodependency

go 1.17

require (
github.com/somepackage v1.2.3
github.com/anotherpackage v0.4.0
)

Imports and Exports


Go uses imports to reference code from other packages or modules. To use

functions, types, or variables from another package, you need to import it. Import

paths are based on the package's URL.

Essentials on Packaging Go Code Sold to


partharora2233@gmail.com
Page 48
Essentials on Packaging Go Code

package main

import (
"fmt"
"github.com/somepackage"
)

func main() {
fmt.Println(somepackage.SomeFunction())
}

As we discussed earlier, identi ers starting with an uppercase letter are exported

and accessible from other packages. Identi ers starting with a lowercase letter are

unexported and can only be used within the same package.

Go's Naming Conventions


Go follows speci c naming conventions to ensure consistency and readability

across projects. The general guidelines are as follows:

Package names should be lowercase, single words, and descriptive (e.g., utils ,
models ).

Variable and function names should use camelCase (e.g., userID , getUserInfo() ).

Constants should be in uppercase with underscores (e.g., MAX_RETRIES ).

Structs and types should be in UpperCamelCase (e.g., type User struct { ... } ).

Essentials on Packaging Go Code Sold to


partharora2233@gmail.com
Page 49
Essentials on Packaging Go Code

Adhering to these conventions makes your code more approachable to other Go

developers and helps maintain a consistent style within your project.

Organizing Go Codebases
Organizing Go codebases e ectively is crucial to avoid chaos as your project grows.

A recommended approach is to use the following directory structure:

demoproject/
|- cmd/
| |- main.go
|
|- internal/
| |- somepackage/
| |- source le.go
|
|- pkg/
| |- yourpackage/
| |- source le.go
|
|- go.mod

cmd : The cmd directory contains the main entry point of your application. It
should be minimal and act as a glue to connect di erent parts of your
application.

interna l: The internal directory is used for code that should not be imported by
code outside your project. It provides encapsulation and keeps internal code
private.

pkg : The pkg directory contains code that can be imported and used by other
projects. It should expose functionality that can be reused.

Essentials on Packaging Go Code Sold to


partharora2233@gmail.com
Page 50
Essentials on Packaging Go Code

Following a well-de ned directory structure helps maintain clarity, isolates

concerns, and makes it easier to scale your application as it grows. This proves that

Go is a suitable language for writing Domain-Driven code.

Essentials on Packaging Go Code Sold to


partharora2233@gmail.com
Page 51
Advanced Go Constructs - Mastering Backend

Advanced Go Constructs
As a Golang developer, exploring advanced Go constructs allows you to tackle

more complex challenges and design more sophisticated software systems. Let's

look at three essential advanced Go constructs: Context, Concurrency, and Generics.

Context
Go's context package provides a powerful mechanism for managing the lifecycle

and cancellation of operations. It allows you to pass context between di erent

goroutines to handle cancellations, timeouts, and request-scoped values.

The context.Context type typically carries deadlines, cancellation signals, and request-

scoped data across API boundaries. It is especially crucial when you need to

manage the ow of operations in concurrent systems or distributed applications.

Advanced Go Constructs - Mastering Backend Sold to


partharora2233@gmail.com
Page 52
Advanced Go Constructs - Mastering Backend

package main

import (
"context"
"fmt"
"time"
)

func worker(ctx context.Context) {


for {
select {
case <-ctx.Done():
fmt.Println("Worker: Received cancellation signal.")
return
default:
// Do some work...
fmt.Println("Worker: Working...")
time.Sleep(1 * time.Second)
}
}
}

func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

go worker(ctx)

time.Sleep(5 * time.Second)
fmt.Println("Main: Timeout reached. Cancelling worker...")
}

Concurrency
Go's support for concurrent programming using goroutines and channels is one of

its most powerful features. Goroutines allow you to run functions concurrently,

while channels facilitate communication and synchronization between goroutines.

Advanced Go Constructs - Mastering Backend Sold to


partharora2233@gmail.com
Page 53
Advanced Go Constructs - Mastering Backend

Concurrency enables you to achieve parallelism and perform tasks concurrently,

leading to improved performance and resource utilization in software systems.

package main

import (
"fmt"
"sync"
)

func printMessages(messages chan string, wg *sync.WaitGroup) {


for msg := range messages {
fmt.Println("Received:", msg)
}
wg.Done()
}

func main() {
messages := make(chan string)
var wg sync.WaitGroup

wg.Add(2)
go printMessages(messages, &wg)
go printMessages(messages, &wg)

messages <- "Hello"


messages <- "World"

close(messages)
wg.Wait()
}

Generics: Do We Really Need Them?


Generics in Go have been a long-awaited feature to enable writing more generic

and reusable code. As of Go 1.18, generics have been introduced, allowing

developers to de ne functions and data structures that work with di erent types.

Advanced Go Constructs - Mastering Backend Sold to


partharora2233@gmail.com
Page 54
Advanced Go Constructs - Mastering Backend

Generics o er more exibility and expressiveness, but Go's simplicity and lack of

generics have been part of its charm. The introduction of generics may come with

language complexity and maintainability trade-o s.

package main

import "fmt"

func ndIndex[T any](slice []T, element T) int {


for i, item := range slice {
if item == element {
return i
}
}
return - 1
}

func main() {
numbers := []int{1, 2, 3, 4, 5}
index := ndIndex(numbers, 3)
fmt.Println("Index of 3:", index)

strings := []string{"apple", "banana", "orange"}


index = ndIndex(strings, "banana")
fmt.Println("Index of 'banana':", index)
}

As you explore these advanced constructs, you'll be better equipped to design

scalable, e cient, and maintainable applications.

Advanced Go Constructs - Mastering Backend Sold to


partharora2233@gmail.com
Page 55
Building an HTTP Server in Go

Building an HTTP Server in Go


Congratulations on reaching this milestone! Let's apply everything we've learned to

build a simple HTTP server using Go. We'll create an HTTP server that handles basic

user registration requests. For simplicity, we won't use databases and store the user

data in memory.

Let's start by creating the project structure:

user-registration/
|- main.go
|- user.go
|- go.mod

Run these commands to initialize the new repository for Go and add any

requirements:

go mod init
go mod tidy

If you check the content of the generated le, you will nd something like the

following:

go.mod
module user-registration

go 1.19

Now, paste this in the main.go le:

Building an HTTP Server in Go Sold to


partharora2233@gmail.com
Page 56
Building an HTTP Server in Go

main.go
package main

import (
"encoding/json"
"fmt"
"net/http"
)

type User struct {


ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}

var users = []User{


{
ID: 1,
Username: "john_doe",
Email: "john@test.com",
}, {
ID: 2,
Username: "jane_smith",
Email: "jane@test.com",
},
}

func handleUserRegistration(w http.ResponseWriter, r *http.Request) {


if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var newUser User
err := json.NewDecoder(r.Body).Decode(&newUser)
if err != nil {
http.Error(w, "Invalid request payload", http.StatusBadRequest)
return
}

users = append(users, newUser)


w.WriteHeader(http.StatusCreated)
}

Building an HTTP Server in Go Sold to


partharora2233@gmail.com
Page 57
New project

func handleGetAllUsers(w http.ResponseWriter, r *http.Request) {


if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}

response, err := json.Marshal(users)


if err != nil {
http.Error(w, "Failed to retrieve users", http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
w.Write(response)
}

func main() {
http.HandleFunc("/register", handleUserRegistration)
http.HandleFunc("/users", handleGetAllUsers)

fmt.Println("Server started at <http://localhost:8080>")


http.ListenAndServe(":8080", nil)
}

New project Sold to


partharora2233@gmail.com
Page 58
Building an HTTP Server in Go

JSON is actually outside the scope of this guide, but please know that it is a data

formatting system. Next, we can have a user.go le to handle all user operations, but

we don’t need one for this short demo:

user.go
package main

// You can de ne additional User-related functions or types here if needed.

Now, let's run the server and test our endpoints using curl :

1. Run the server:

go run main.go

2. Register a new user by opening a new terminal and pasting this shell script:

curl -X POST -d '{"id": 3, "username": "backendcoder", "email": "test@test.com"}' <http://localhost:8080/register>

3. Get all users:

curl <http://localhost:8080/users>

You should see the list of users, including the newly registered user:

Building an HTTP Server in Go Sold to


partharora2233@gmail.com
Page 59
Building an HTTP Server in Go

This simple HTTP server demonstrates how to handle HTTP requests for user

registration and retrieval using Go. Of course, in a real-world scenario, you would

use a database to persist the user data and implement proper error handling and

validation. But this project is a great starting point to understand the basics of

building backend HTTP servers with Go.

Congratulations on completing this milestone project! Continue exploring Go's

features and building more advanced applications to become a pro cient Go

backend engineer.

Where to go from here


You just learned the basics of Go. If you understand the logic of the milestone

project, great! You can scale it by adding features like deleting and modifying user

details and storing users in a repository. You can also split the logic into di erent

packages, as we saw in the guide, and add to the logic. You can also Dockerize the

application and deploy it with practice. Read our Ultimate Guide to Docker article

here.

If you don’t understand the logic in the milestone project, you should engage in

research to try to understand everything that happened. Then when you do, you

can follow the steps above to scale the project.


Building an HTTP Server in Go Sold to
partharora2233@gmail.com
Page 60
Building an HTTP Server in Go

Get Gin Ultimate Guide


What you will learn:

Chapter 1. Getting Started with Gin


Chapter 2. Building with Gin: Middleware, Routing, and Controllers
Chapter 3. Data Handling and Advanced Functionality
Chapter 4. Milestone project

At 25% Discount

Building an HTTP Server in Go Sold to


partharora2233@gmail.com
Page 61
Want to become a
great Backend
Engineer?

Join the Academy


Mastering Backend is a great resource for backend engineers.
Next-level Backend Engineering training and Exclusive
resources.

Sold to
partharora2233@gmail.com

You might also like