Go Programming For Beginners An Introduction
Go Programming For Beginners An Introduction
Beginners
An Introduction to Learn the Go Programming
Language with Tutorials and Hands-On Examples
Text Copyright © Light Bulb Publishing
All rights reserved. No part of this guide may be reproduced in any form without permission in writing
from the publisher except in the case of brief quotations embodied in critical articles or reviews.
Legal & Disclaimer
The information contained in this book and its contents is not designed to replace or take the place of
any form of medical or professional advice; and is not meant to replace the need for independent
medical, financial, legal or other professional advice or services, as may be required. The content and
information in this book has been provided for educational and entertainment purposes only.
The content and information contained in this book has been compiled from sources deemed reliable,
and it is accurate to the best of the Author's knowledge, information, and belief. However, the Author
cannot guarantee its accuracy and validity and cannot be held liable for any errors and/or omissions.
Further, changes are periodically made to this book as and when needed. Where appropriate and/or
necessary, you must consult a professional (including but not limited to your doctor, attorney, financial
advisor or such other professional advisor) before using any of the suggested remedies, techniques, or
information in this book.
Upon using the contents and information contained in this book, you agree to hold harmless the Author
from and against any damages, costs, and expenses, including any legal fees potentially resulting from
the application of any of the information provided by this book. This disclaimer applies to any loss,
damages or injury caused by the use and application, whether directly or indirectly, of any advice or
information presented, whether for breach of contract, tort, negligence, personal injury, criminal intent,
or under any other cause of action.
You agree to accept all risks of using the information presented in this book.
You agree that by continuing to read this book, where appropriate and/or necessary, you shall consult a
professional (including but not limited to your doctor, attorney, or financial advisor or such other
advisor as needed) before using any of the suggested remedies, techniques, or information in this book.
Table of Contents
1. Introduction
2. Scope
3. Getting Started
3.1 Install Go on Windows
3.2 Install Go on Unix-like Operating Systems
3.3 Compile and Execute Go Programs
3.3.1 On Windows
3.3.2 On Unix-like operating systems
3.3.3 Compile and Execute Demo
3.3.4 Compilation Errors
3.3.4 Go Playground
4. Syntax
4.1 Statements
4.2 Comments
4.3 Identifiers
4.4 Keywords
4.5 Tokens
4.6 Basic Program Constituents
5. Hello World! Go Program
6. Data Types
6.1 Boolean Data Type
6.2 Numeric Data Types
6.2.1 Integers
6.2.2 Floats
6.2.3 Complex
6.3 String Data Type
6.4 Other Data Types
7. Variables
7.1 Variable Initialization
7.2 Short Variable Declaration
7.3 Variable Assignment
7.4 Printing Variables
8. Output Formatting
9. Operators
9.1 Arithmetic Operators
9.2 Relational Operators
9.3 Logical Operators
9.4 Bitwise Operators
9.5 Assignment Operators
10. User Interaction
10.1 Scanln Function
10.2 Scanf Function
10.3 Reading Sentences
11. Control Structures
11.1 Decision Making
11.1.1 If-Else construct
11.1.2 Switch-Case construct
11.2 Loops
11.2.1 for Loop
11.2.2 Control Statements
12. Arrays
13. Functions
13.1 Function Definition
13.2 Function Call
13.3 Passing Arguments to Functions
13.4 Returning Values
13.5 Passing Arrays as Arguments
14. Strings
14.1 Concatenating strings
14.2 Compare strings
14.3 Search for a string inside another string
14.4 Trimming a string
14.5 Case conversion
15. Pointers
16. Structures
17. Programming Examples
17.1 Sum of digits of a number
17.2 Fibonacci series
17.3 Reverse a given number
17.4 String Palindrome
17.5 Bubble Sort
18. Final Words
1. Introduction
There are legendary programming languages such as C and C++ which
are used to build platform and architecture specific and native software
applications where the emphasis is usually on performance; and then there
are all purpose scripting languages such as Ruby and Python which can do
just about anything ranging from simple desktop applications to complex
cloud applications. While languages such as Python and Ruby are easy to
learn, easy to code and offer a super wide range of functionalities and
libraries as compared to C/C++, the performance is not as good as C/C++
(sorry Python fans, but it’s true!) unless there is dedicated hardware support
for accelerating the applications. This is because a script is usually executed
by a special software called as an interpreter which executes a script line by
line where as a program written in C/C++ is compiled to generate executable
code which is native to a hardware platform and then the executable code is
run. Go programming language combines the performance of languages
such as C/C++ and the ease of use of languages like Python.
Go programming language also known as golang or simply Go is a
multi-paradigm programming language designed by Robert Griesemer, Rob
Pike, and Ken Thompson at Google. It is a statically typed, compiled
programming language that supports programming paradigms such as object
oriented, functional, imperative and concurrent programming.
The development of Go began at Google in 2007 and the first stable
version was released in 2012 following a public announcement in late 2009.
The developers used C++, Assembly language and Go (self-hosted) to
implement Go programming language. There are two major implementations
of Go – gccgo which is the front end for GCC compiler and Google’s Go
compiler which targets operating systems such as Windows, Linux, macOS
and other Unix/BSD-like operating such as DragonFly BSD, FreeBSD,
NetBSD, etc.
2. Scope
With Go language, you can build desktop applications, web applications,
web services and much more. Google’s Go language compiler toolchain is
available for Windows, macOS, Linux and other Unix-like operating
systems. With that toolchain, you can build applications targeted for
Windows/Unix-like operating systems-based desktops and servers, embedded
platforms, WebAssembly, etc. At present, there is not a stable GUI
development framework available for Go, most of them are made available
using wrappers and are still under development. But this is under no
circumstances a turn-off because Go can do a lot of things. Containerization
tool Docker which is revolutionizing cloud computing and virtualization
space is entirely written in Go.
It is possible to access databases such as MySQL, PostgreSQL, SQLite,
etc. with Go. You can even develop applications targeting some of the
relatively newer technologies such as blockchain, data science, machine
learning, etc.
One of the key selling points of Go is that it can build WebAssembly
applications. WebAssembly is a type of code that can be run inside supported
browsers. It is an open standard for executable binary code format targeted at
web applications. This enables near native performance. With this feature,
you can build a high performance web application written in Go language.
With so much flexibility and such a wide use case scenario, Go is quickly
becoming one of the most enterprise friendly languages with companies such
as Uber, Twitch, Google, Dailymotion, etc. making use of it to implement
some of their applications and services.
Is prior programming knowledge needed to learn Go
Programming language?
The short answer to that question is No. The long answer is – any prior
programming experience will definitely help. Go combines the efficiency of
languages like C/C++ and ease of use and code readability of languages such
as Python or Javascript. If you know any of these languages, you will be able
to relate to the concepts really well. But even if you are a complete beginner
to programming or this is the first language you are learning, you should be
able to learn Go with the right kind of mind set appropriate efforts. Having
said that, you should be comfortable with using your computer. That is, you
should know the way around your system, be comfortable with
installing/removing software, using Command Prompt, PowerShell,
Terminal, Shell, etc.
Who is this book for? What will I learn?
This book is for anybody who wants to learn the basics of Go
programming language. The content has been carefully designed to suit
complete beginners as well as experienced programmers. You will learn to
build and execute simple console applications for desktops.
3. Getting Started
A PC with Windows/Linux or a MAC machine will be required to build
Go applications. Go programs are plain text files (carrying the extension
“.go”) and hence you will need a text editor to write Go programs. Any text
editor will do the job including Notepad, Wordpad, vi, emacs, Notepad++,
etc. Chose an editor that you are the most comfortable with. You can
alternatively use IDEs such as Eclipse, IntelliJ, etc. I prefer keeping it simple
for learning basics, sticking to a simple text editor instead of an IDE. You
will need to install Go compiler toolchain on your machine in order to build
Go applications.
import "fmt"
func main() {
fmt.Printf("\nIf you see this, you did a great job so far!\n")
}
Note: You do not have to understand what the above code does or how it
works, the only purpose of this section was to teach you how to compile and
execute a Go program.
3.3.4 Compilation Errors
Compilation errors occur when there are mistakes in the source file. These
are usually syntax related issues. If you try to compile a Go program which
has problems, the compiler will throw an error and the compilation process
will not complete successfully and hence, the executable file will not be
generated. Sometimes, the error message returned by the compiler will tell
you exactly what has gone wrong where and sometimes it will not. Hence it
is a good idea to check every program manually before compiling. Here is
what a sample compilation error looks like:
3.3.4 Go Playground
Go Playground is a web based tool used to compile and execute Go
programs online. Of course, full functionality of Go will not be available
through this tool but nonetheless, it is a very useful tool to try out small
programs and learn concepts especially when you do not have access to a
PC/Laptop with Go environment. Open your favourite web browser and visit
https://play.golang.org/. You will see something like this:
Clear the existing code, copy-paste the code from Section 3.3.3 and click
Run. You should see the output right below the code area:
4. Syntax
Now that we know how to compile and execute a program, let us begin
learning the actual programming concepts of Go language. Go is a case
sensitive language. We may say that the words “programming”,
“Programming” and “PROGRAMMING” are the same but Go compiler
treats all of them differently.
4.1 Statements
A statement is used to perform a task or a combination of tasks. It can be
made up of anything such as operators, function calls, variable assignments,
etc. In simple terms, a statement is a line of code that executes one or more
instructions such as printing something on the screen, performing arithmetic
operations, reading from a file, etc. In Go, one statement is placed on one
line. Here are a few examples of statements:
fmt.Printf (“Hello”)
var x int = 51
msg = “Go book”
4.2 Comments
Comments are used to mark or explain a piece of code. These are ignored
by the compiler and have no outcome on the execution of a program. Hence,
comments are only relevant to us humans. A comment begins with /*
character sequence and ends with */ character sequence. Here are a few
examples:
/*This is a comment*/
/* You can have any text within this character sequences */
This book contains several programming examples. Each program
contains comments which explain what a particular section of code does.
Whenever you stumble upon programs in this book, make sure you read the
comments well.
4.3 Identifiers
An identifier is a name given to a variable, class, object, function or
anything else that is identifiable. Identifier names can contain alphanumeric
characters but the first character has to be an alphabet. The only permitted
special character is underscore (_).
4.4 Keywords
Keywords are reserved words that cannot be used as identifier names.
Here is a list of keywords in Go:
break default func interface select
case defer Go map Struct
chan else Goto package Switch
const fallthrough if range Type
continue for import return Var
4.5 Tokens
A token is any meaningful item in a program. Keywords, identifiers,
constants, symbols, string literals, etc. can all be called as tokens.
Package Declaration
- Go organizes source files inside the system as packages. A Go
program can be used to build a library and also a standalone
application. A standalone application is the one which executes on its
own while a library cannot execute on its own, it has to be used in
some other application. In this book, we will mostly be building
standalone applications. The package name for standalone
applications should be “main”. This tells the compiler that the Go
program it is dealing with is supposed to be built as a standalone
applications and not a library. This is how you would write a
package statement:
package <package name>
Example:
package main
Import Packages
- Packages are pre-built libraries which can perform various tasks. Go
offers a rich set of packages for different things. Here is general
syntax to import packages:
import (
<package 1>
<package 2>
<package 3>
…
…
<package n>
)
- For handling formatted I/O operations, “fmt” package is used. If you
want to write a program to print something on the console, it is
considered as a formatted output operation. You would be importing
“fmt” package as follows:
import (“fmt”)
Main Function
- A main function serves as an entry point of a program. A program
will start executing from the first statement inside the main function.
Here is how you would write a main function:
func main ( ) {
/*Statements Here*/
}
Let us combine these program constituents and write a Go program that
builds but does not do anything. It will have a package declaration statement
and an empty main function. We will not be including import “fmt”
statement because we are not going to perform any I/O operations:
/*Package Declaration Statement*/
package main
/*Mandatory main function*/
func main() {
}
Compile and Execute:
As seen, the program is built and run successfully. Nothing significant
happens on the console as we are not doing anything inside the program. The
program starts executing from the empty main function.
5. Hello World! Go Program
In the previous chapter, we saw what are the basic constituents of a
standalone Go program. We also saw how to write a basic Go program that
builds and executes but does not do anything. In this chapter, we will write a
program to print something on the console. Printing something on the console
is considered as an Output operation. We will be using a function called a
Printf from the fmt package. It can be accessed as fmt.Printf. General syntax
of using this function is:
fmt.Printf(<string>)
The Printf function should be given a string to print. A string is a
sequence of characters. While giving a string to this function, the sequence of
characters should be enclosed within double quotes. This function actually
accepts a formatted string but for simplicity sake, let us only focus on a
normal string and worry about formatted string later. If you want to print
something on the console, the fmt.Printf statement will look something like:
fmt.Printf(“Let us print something”)
Let us combine whatever we have learnt and write a program to print
“Hello World!” on the console:
/*Package Declaration Statement*/
package main
/*Import statement, import fmt package*/
import "fmt"
/*Mandatory main function*/
func main() {
/*Print Hello World! using fmt.Printf function*/
fmt.Printf("Hello World!")
}
Output:
As seen, there is an extra line of space left after printing Hello World.
If you want to insert a new line anywhere in the string, you can use the
escape character sequence \n inside the string. This will work with Printf as
well as Println functions. Here is an example:
/*Package Declaration Statement*/
package main
/*Import statement, import fmt package*/
import "fmt"
/*Mandatory main function*/
func main() {
/*Print Hello World! using fmt.Printf function*/
fmt.Printf("\nHello \nWorld!\n")
}
Output:
There are many more escape character sequences. Another useful one is \t
which will insert one tab-space in the output string. This will again work
with Printf and Println functions. Here is an example:
/*Package Declaration Statement*/
package main
/*Import statement, import fmt package*/
import "fmt"
/*Mandatory main function*/
func main() {
/*Print Hello World! using fmt.Println function*/
fmt.Println("\nHello\tWorld!")
}
Output:
Note: If you simply need a data type for integer, you should either use int
or uint. The size will be decided depending on what kind of system you use.
If you use a 32-bit system, the size will be 32-bits and for 64-bit systems, the
size will be 64-bits. If you are specific with the size requirements of the data
you are dealing with, you can use the data type of appropriate size.
6.2.2 Floats
This sub-category of numeric data types is used for floating point values.
Data Type Description
float32 32-bit IEEE 754 floating-point number
float64 64-bit IEEE 754 floating-point number
6.2.3 Complex
Complex data types are used to deal with complex numbers having real
and imaginary parts.
Data Type Description
64-bit Complex Number having float32 (32-bit) type real and
complex64
imaginary parts. Two 32-bit float32 types add up to 64-bits in total.
128-bit Complex Number having float64 (64-bit) type real and
complex128
imaginary parts. Two 64-bit float64 types add up to 128-bits in total.
/*Package Declaration*/
package main
Output:
Note:
1. It is always a good idea to use meaningful variable names. For
example, if you want to store the name of a person, you are better
off naming that variable as name as opposed to something random
such as xyz.
2. Declare the variables only if you need them. If you declare a
variable and do not use it anywhere in your program, the compiler
will give you a “declared but not used” error. This will prevent the
program from building. If you somehow happen to declare the
variable and not use it and want to avoid this error, you can assign
the unused variables to the blank identifier given by the underscore
sign (_).
8. Output Formatting
In the previous section, we learned to use Println function to print
variables. This function automatically leaves one line at the end, leaves a
space between items when multiple items are printed. There is not much
control although it does a good enough job if your objective is to simply print
variables. For proper output formatting, we can use Printf function from the
fmt package. This gives a much better control over the output; you will see
why in a while.
The Printf function accepts a formatted string as an argument. A
formatted string is made up of string literals and format specifiers called
verbs. A verb is a character sequence which starts with a percentage (%)
symbol. Different verbs are used for different data types. For example, for
strings %s is used, for integers %d is used, etc. If a formatted string is given
to a Printf function, variables, constants or expressions must also be given as
arguments following the formatted string. At the time of printing, verbs will
be substituted by the corresponding variables, constants or values resulting
from the evaluation of a given expression. General syntax:
fmt.Printf (<formatted string>, <variables/constants/expressions>)
Example:
fmt.Printf (“Name: %s, Number: %d”, name, num)
In the above example, first verb %s will be substituted by the value of
name and second verb %d will be substituted by the value of num in the
output. The following illustration will make things clearer.
import "fmt"
func main() {
/*Initialize string variables*/
var first_name, last_name, city string = "Samantha", "Hudson", "Denver"
/*Initialize integer variable*/
var age int = 33
fmt.Printf("\nFirst Name: %s \nLast Name: %s \nAge: %d \nCity: %s \n", first_name, last_name,
age, city)
}
Output:
Verb Description
%v Value in default format
%T Data type of the value
%t Boolean values – true or false
%d Integers
%b Binary (Base 2)
%o Octal (Base 8)
%O Octal (Base 8) with 0o prefix
%x Hexadecimal (Base 16) with (a-f) in lower case
%X Hexadecimal (Base 16) with (A-F) in upper case
%c Character
%f Floating point value with no exponent
%F Same as %f
%e Scientific notation – floating point with exponent. e will be in lower case
%E Scientific notation – floating point with exponent. E will be in lower case
%s String
%p Pointer
Here is a Go program that makes use of different verbs for different data
types:
package main
import "fmt"
func main() {
/*Declare and initialize a few variables*/
var x, y, z = 75, -6.872, 3+2i
var flag = true
msg := "Go Programming"
/*Print various things using Printf*/
fmt.Printf("\nx = %v Type: %T", x, x)
fmt.Printf("\nx (decimal): %d\nx (binary): %b\nx (octal): %O\nx (hexadecimal): %X", x, x, x, x)
fmt.Printf("\ny = %f Type: %T \nz = %f Type: %T", y, y, z, z)
fmt.Printf("\nflag = %t Type: %T", flag, flag)
fmt.Printf("\nmsg = %s Type: %T\n", msg, msg)
}
Output:
Note:
Note:
/*Package Declaration*/
package main
Output:
Let us see how arithmetic operators work with floating point numbers.
We have used the verbs %f for printing normal floating point values and %E
for printing values in scientific notation format:
/*Arithmetic Operators Demo 2 - Floating point arithmetic*/
/*Package Declaration*/
package main
Output:
Arithmetic operators will also work on complex numbers. You can create
complex number variables using the complex64 or complex128 data types. A
complex64 data type is made up of two float32 data types, one each for real
and imaginary parts and a complex128 data type is made up of one float64
data type for the real part and another float64 data type for the imaginary
part. The verb to be used is %f as a complex number is made up of two
floating point numbers in Go. Alternatively, you can use %v too which will
display a value using the original data type. A complex number variable can
be initialized directly by specifying the real and imaginary part or by using a
function called complex as follows:
<variable> := complex (<real part>, <imaginary part>)
Num := complex (1,8)
Here is a Go program that demonstrates the use of arithmetic operators on
complex numbers:
/*Arithmetic Operators Demo 3 - Complex numbers' arithmetic*/
/*Package Declaration*/
package main
/*Package Declaration*/
package main
Output:
/*Package Declaration*/
package main
/*Package Declaration*/
package main
Output:
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
Output:
10. User Interaction
Up to this point, we have seen several programming examples. All those
programs had hard coded values. None of the programs gave the user an
opportunity to enter values manually. In this section, we will learn how to
accept input from the user.
There are many ways to interact with the user. We will learn about two
simple functions from the fmt package used for reading input from the user –
Scanln and Scanf.
10.1 Scanln Function
Here is how to use the Scanln fucntion:
fmt.Scanln ( &<string variable> )
Example:
var str string;
smt.Scanln (&str )
The Scanln function requires a string variable to be specified to store
user’s input marked by <string variable> in the above code snippet. This
function implements a blocking I/O operation. That is, when the execution
control will reach a Scanln statement, the execution of the program will halt
to give the user an opportunity to enter something through the keyboard (and
press Enter). Once the user enters something and hits Enter, whatever the
user has entered through the keyboard will be fetched and stored in the
specified string variable. The ampersand sign (&) before the variable is used
to fetch the memory address of the variable so that the Scanln function can
directly set the contents of the specified variable. This concept will be clearer
in the Pointers chapters. Let us write a simple Go program to prompt the user
to enter something and display it back:
/*User Interaction Demo 1*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Create a variable to store input*/
var str string;
/*Prompt the user to enter something*/
fmt.Printf("\nEnter something: ")
/*Read user input using Scanln function*/
fmt.Scanln(&str)
/*Display whatever has been read*/
fmt.Printf("\nYou have entered: %s \n", str)
}
Output:
The Scanln function has its own limitations. To start with, it can only
read the input in a string format. That means, even if you enter a number, it
will be treated as a string. Second, it reads input as a space-separated
tokenized string. That is, if you enter a sentence, each word will be treated as
a token and those many variables will be needed to store the input. If you
specify only one variable and enter a sentence, only the first word will be
read. Let us run the same program and try to enter a sentence:
As seen, only the first word is read. The above input had four words and
hence the Scanln statement should have had 4 variables specified to store
those 4 words as follows:
fmt.Scanln(&str1, &str2, &str3, &str4)
Similarly, the Printf statement should look like:
fmt.Printf("\nYou have entered: %s %s %s %s\n ", str1, str2, str3, str4)
Here is the full program:
/*User Interaction Demo 2*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Create variables to store input*/
var str1, str2, str3, str4 string;
/*Prompt the user to enter something*/
fmt.Printf("\nEnter something: ")
/*Read user input using Scanln function*/
fmt.Scanln(&str1, &str2, &str3, &str4)
/*Display whatever has been read*/
fmt.Printf("\nYou have entered: %s %s %s %s\n ", str1, str2, str3, str4)
}
Output:
Although the program works correctly now, this is not the best way to
read a sentence as we do not know how big a sentence a user will enter. One
variable will be required to store one word. This is not at all practical. There
is a better way to read sentences using the bufio package discussed later in
this chapter. We will use the Scanln function only when we want to read one
word or one number at a time. If the user enters a number and you try to read
it using Scanln, it will be in the string format. In order to convert a number in
string format to the appropriate numeric format, we will use functions from
the strconv package. The first thing you will have to do is import this
package in your program and use the following conversion functions:
Convert a number in string format to integer:
<number variable>, <error variable> = strconv.Atoi(<number in string
format>)
Example:
num, err := strconv.Atoi(“55”)
In the above example, “55” in string format will be converted to 55 in
integer format and stored in the variable num which is short declared here.
Along with that, err has also been short declared which will be used to store
conversion error if any.
Convert a number in string format to float:
<variable> = strconv.ParseFloat(<number in string format>, <number
of bits>)
Example:
numS := “-46.2343”
numF, err := strconv.ParseFloat(numS, 64)
In the above example, the ParseFloat function will convert “-46.2343” in
string format to -46.2343 in 64-bit float format and return it to the numF
variable where it will be stored.
Let us write a Go program to accept 4 numbers from the user – two
integers and two floats. We will use Scanln function to read these inputs and
hence all 4 numbers will be stored in string format. We will convert these
numbers to the appropriate formats and perform addition, subtraction,
multiplication and division:
/*User Interaction Demo 3 - Work with numbers */
/*Package Declaration*/
package main
/*Import Statement - import fmt and strconv package*/
import (
"fmt"
"strconv"
)
/*Mandatory main function*/
func main () {
/*Declare variables to store input*/
var num1_str, num2_str, num3_str, num4_str string
/*Declare variables to store int and float64equivalents*/
var num1, num2, sum, diff int
var num3, num4, prod, quo float64
/*Prompt the user to enter two integers*/
fmt.Printf("\nEnter two inegers: ")
/*Read user input using Scanln function*/
fmt.Scanln(&num1_str, &num2_str)
/*Prompt the user to enter two floats*/
fmt.Printf("\nEnter two floats: ")
/*Read user input using Scanln function*/
fmt.Scanln(&num3_str, &num4_str)
/*Convert num1_str and num2_str to integer*/
num1, err1 := strconv.Atoi(num1_str)
num2, err2 := strconv.Atoi(num2_str)
/*Convert num3_str and num4_str to float64*/
num3, err3 := strconv.ParseFloat(num3_str, 64)
num4, err4 := strconv.ParseFloat(num4_str, 64)
/*Assign err to blank identifiers*/
_ = err1
_ = err2
_ = err3
_ = err4
/*Perform arithmetic operations*/
sum = num1 + num2
diff = num1 - num2
prod = num3 * num4
quo = num3 / num4
/*Print everything*/
fmt.Printf("\nnum1 + num2 = %d", sum)
fmt.Printf("\nnum1 - num2 = %d", diff)
fmt.Printf("\nnum3 * num4 = %f", prod)
fmt.Printf("\nnum3 / num4 = %f \n", quo)
}
Note: We have used 4 different error variables – err1, err2, err3 and err4
for 4 different conversions. There is no need to use them. However, if you do
not use them, the compiler will return a “declared but not used” error and the
program will not build. To circumvent this problem, each of these error
variables can be assigned to the blank identifier _.
Output:
In the above example, “Liev” is read as string, 18 is read as int and 152 is
read as float32. This is how the assignment of input to variables happens:
As mentioned earlier, the input is read according to the data type specified
by verbs, no need arises to convert input from one form to another. Let us
cross check this by writing a program to add two numbers. This time, we will
insert \n between two verbs and hence, the user will have to hit enter after
entering each number:
/*Scanf Add Two Numbers Demo*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Declare Variables*/
var num1, num2, sum int
/*Prompt the user to enter 2 numbers*/
fmt.Printf("\nEnter two numbers: ")
/*Read 2 numbers*/
fmt.Scanf("%d\n%d", &num1, &num2)
/*Calculate sum*/
sum = num1 + num2
/*Display everything*/
fmt.Printf("\nSum = %d\n", sum)
}
Output:
As seen, the statements inside the if block do not get executed when the
given condition evaluates to false. It is possible to execute a different block
of code when the given condition evaluates to false using an else block. The
else block should immediately follow the if block. General syntax:
if (<condition>) {
/*Statements to be executed if <condition> is true*/
} else {
/*Statements to be executed if <condition> is false*/
}
Example:
if (num == 0) {
fmt.Println(“num is 0”)
} else {
fmt.Println(“num is NOT 0”)
}
The working of if-else construct is simple – if the condition evaluates to
true, the if block will be executed and the else block will be skipped and if it
evaluates to false, the if block will be skipped and the else block will be
executed. Let us write a program using if and else blocks and see what
happens when the given condition of the if block evaluates to false.
/*If Else Demo*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
var a int = 5
fmt.Printf("\nProgram execution begins. This statement is before the if block.\n")
/*Check if a is greater than 10*/
if (a > 10) {
fmt.Printf("\nInside if block.\n%d is greater than 10.\n", a)
} else {
fmt.Printf("\nInside else block.\n%d is NOT greater than 10.\n", a)
}
fmt.Printf("\nOutside if/else blocks. Program coming to an end.\n")
}
Output:
In the above program, there are 3 cases and the variable Option is used to
switch. This variable has been assigned to 3, let us change Option to 1 and 9
and see what happens:
Output (Option = 1):
The variable used to switch can also be set in the switch statement itself
as follows:
switch <optional statement, set variable>
(<variable/expression>) {
case <constant expression 1>:
/*Statements to be executed if <expression> matches <constant
expression 1>*/
...
case <constant expression n>:
/*Statements to be executed if <expression> matches <constant
expression n>*/
default:
/*Statements to be executed if <expression> finds no match*/
}
Let us re-write the previous program and set Option to 2 in the switch
statement itself:
/*Switch Demo 1*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Switch Option, where Option is int variable short-declared and assigned to 2*/
switch Option := 2
(Option) {
/*Various cases to match Option*/
case 1:
fmt.Printf("\nOption is 1.\n")
case 2:
fmt.Printf("\nOption is 2.\n")
case 3:
fmt.Printf("\nOption is 3.\n")
/*Default case incase there is no match*/
default:
fmt.Printf("\nOption does not match any of the cases.\n")
}
}
Output:
Here is an example where the loop variable has been previously declared:
/*For Demo 3*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Declare an int variable*/
var count int
fmt.Printf("\nMultiples of 3\n\n")
/*Run for loop from 1 to 20*/
for count = 1 ; count <= 20 ; count++ {
/*Print count * 3*/
fmt.Printf("%d\n", count * 3)
}
}
Output:
11.2.2 Control Statements
As long as the given condition is true, a loop will go on executing. This is
the normal execution process of a loop. It is possible to alter this flow of
execution of a loop using control statements such as continue and break.
11.2.2.1 continue statement
When a continue statement is encountered, the execution control jumps to
the beginning of the loop thereby skipping all the statements after the
continue statement. In other words, the loop moves to the next iteration. Let
us write a program to print only odd numbers between 1 and 30:
/*For Demo -- continue */
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
fmt.Printf("\nOdd numbers between 1 and 30\n\n")
/*Run for loop from 1 to 30*/
for count := 1 ; count <= 30 ; count++ {
if (count % 2 == 0) {
continue
}
fmt.Printf("%d\n", count)
}
}
Output:
A more practical use of the break statement can be understood with the
help of the following program where we ask the user to enter a number and
determine whether it is prime or composite:
/*Prime or composite - using break*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Declare variable to store user input and to serve as loop counter*/
var i, num int
/*Prompt the user to enter a number and read using Scanf*/
fmt.Printf("\nEnter a number: ")
fmt.Scanf("%d", &num)
/*Run loop from 2 to num as every number is divisible by 1*/
for i = 2 ; i <= num ; i ++ {
if (num % i == 0) {
break
}
}
if (num != i) {
fmt.Printf("\n%d is a composite number.\n", num)
} else {
fmt.Printf("\n%d is a prime number.\n", num)
}
}
Output:
Let us write another program using loops where we will calculate the sum
of first n even numbers.
/*Sum of n even numbers*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Declare variable to store n, loop counter and sum*/
var i, n int
var even_num, sum int = 1, 0
/*Prompt the user to enter a number and read using Scanf*/
fmt.Printf("\nEnter n: ")
fmt.Scanf("%d", &n)
fmt.Printf("\nFirst %d even numbers: \n\n", n)
for i = 1 ; even_num <= n ; i ++ {
if (i % 2 == 0) {
fmt.Printf("%d ", i)
sum += i
even_num++
}
}
fmt.Printf("\n\nSum of above even numbers: %d\n", sum)
}
Output:
12. Arrays
An array is a collection of similar items. In programmatic terms, an array
in Go language is a data structure which contains items of the same data type.
Each item inside an array is known as an array element (or just an element).
An element can be referred to using its position in the array which is known
as an index. An array index begins at 0 and ends at one less than the size of
the array (size – 1). For example, if we had an array of 10 elements, the first
element of that array would be present at 0, the second one at index 1, the
third one at index 2, ..., and the last element would be present at index 9.
In Go programming language, an array can be declared using the
following syntax:
var <array variable> [<size of the array>] <data type>
Example:
var array1 [5] int
var msg [3] string
var x [10] float64
Once an array is declared, its elements will get zero-values (numeric
arrays will hold 0 and string arrays will hold empty strings). Individual
elements can be accessed using their indexes enclosed with the access
operator ( [ ] ). This way, you can set (and also retrieve/print) individual
elements of an array. Here is an example:
/*Declaring an int array of size 5. First index is 0, last index is 4*/
var num_array [5] int
/*Setting element at index 0 to 15*/
num_array[0] = 15
/*Setting element at index 1 to -35*/
num_array[1] = -35
/*Setting element at index 2 to 0*/
num_array[2] = 0
/*Setting element at index 3 to 68*/
num_array[3] = 68
/*Setting element at index 4 to 18*/
num_array[4] = 18
This is how num_array will look inside memory:
We will now write a program where in we will create an integer array, set
element values and print them back. The whole array can be printed using the
verbs %v or %d. Printing individual elements would be the same as printing
any other integer variable:
/*Array Demo 1*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Declare an array of 7 integers*/
var arr [7] int
/*Set values of all elements*/
arr[0] = 83
arr[1] = -34
arr[2] = 55
arr[3] = 97
arr[4] = -24
arr[5] = -11
arr[6] = 46
/*Print the whole array*/
fmt.Printf("\nArray arr:\n\n%v\n", arr)
/*Print index and corresspoiding values*/
fmt.Printf("\nValue at index: 0 ==> %d", arr[0])
fmt.Printf("\nValue at index: 1 ==> %d", arr[1])
fmt.Printf("\nValue at index: 2 ==> %d", arr[2])
fmt.Printf("\nValue at index: 3 ==> %d", arr[3])
fmt.Printf("\nValue at index: 4 ==> %d", arr[4])
fmt.Printf("\nValue at index: 5 ==> %d", arr[5])
fmt.Printf("\nValue at index: 6 ==> %d\n", arr[6])
}
Output:
An array can be of any data type. When initializing an array, the size may
or may not be specified. It will be taken automatically depending on the
number of elements you set at the time of initialization. At any point in the
program, you can use the function len(<array variable) to determine the size
of an array. Also, accessing elements every time manually may not be the
best way – loops do a great job working with arrays. Here is an example that
demonstrates these concepts:
/*Array Demo 3*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
/*Declare an array of 10 strings and initialize*/
var country = [] string {"USA", "UK", "India", "Brazil", "South Africa", "Argentina", "New
Zealand", "Russia", "Morocco", "Latvia"}
/*Print the whole array*/
fmt.Printf("\nArray country:\n\n%v\n", country)
/*Print index and corresponding values using for loop*/
/*Use len function to retrieve the size of the array*/
size := len(country)
for i := 0 ; i < size ; i ++ {
fmt.Printf("\nValue at index: %d ==> %s", i, country[i])
}
fmt.Printf("\n")
}
Output:
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import (
"fmt"
"strconv"
)
/*Mandatory main function*/
func main () {
/*Declare variables*/
var arr [5] int
var sum int = 0
var num_str string
/*Declare a variable to store average*/
var avg float32
/*Prompt the user to enter 5 elements, use for loop*/
for i := 0 ; i < 5 ; i++ {
fmt.Printf("\nEnter element at index %d: ", i)
fmt.Scanln(&num_str)
/*Convert num_str to integer*/
num, err := strconv.Atoi(num_str)
/*Assign num to arr[i]*/
arr[i] = num
/*Assign err to blank identifier*/
_ = err
/*Keep calculating sum*/
sum += arr[i]
}
/*Calculate average*/
avg = float32 (sum) / 5.0
fmt.Printf("\nArray arr:\n%v\nSum: %d\nAverage: %f\n", arr, sum, avg)
}
Output:
Let us write a program to take 5 integers as input from the user, save them
in an array and reverse the array:
/*Reverse an array*/
/*Package Declaration*/
package main
Function Name
- A function name is the name given to a function marked by
<function name> in the above code snippet. This name is used to
identify and call the function. Function naming rules are the same as
identifier/variable naming rules.
Arguments
- Arguments (marked by <arguments> in the above code snippet) are
the values that a function “accepts” into local variables. These
values are passed to a function at the time of function call. A
function may accept zero or more arguments. When there are more
than one arguments, they should be separated using comma.
Arguments are also called Parameters.
Return Type
- A function can optionally return a value back to the calling function.
The data type of the value that a particular function is returning
should be specified in the return type field marked by <return type>
in the above code snippet.
Function Body
- Function body is the core part of a function where the actual work
gets done. If you have a function to calculate the factorial of a given
number, the code that is responsible for calculating factorial of a
number goes in this part of the definition.
Here are a few code snippets that show different types of functions:
/*Function that accepts no arguments and returns no value*/
func sayHello () {
fmt.Printf(“\nJust a function that prints Hello on the console.”)
}
/*Function that accepts one augment and returns no value*/
func showValue (name string) {
fmt.Printf(“\nReceived name = %s”, name)
}
/*Function that accepts one argument and returns one value*/
func doubleIt(x int) int {
return (x * 2)
}
/*Function that accepts three arguments and returns two values*/
func doMath (a int, b int, c int) (int, float32) {
sum := a + b + c
avg = float32 (sum) / 3.0
return sum, avg
}
13.2 Function Call
A defined function will not execute on its own. It needs to be called (from
another function, perhaps from the main function). A function is called with
the help of its name while passing the exact number of arguments (in correct
order) as defined in the function definition. Here is the general syntax:
<function name>(<arguments>)
Example:
myFunction( )
Let us make calls to each of the functions defined in the previous section:
sayHello()
showValue(“Sarah”)
x = doubleIt(100)
sum, avg = doMath (1, 2, 3)
Here is a simple function that accepts no arguments and returns no value:
/*Function Demo 1*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*User defined function*/
/*This function accepts no arguments and returns no value*/
func myFunction () {
fmt.Printf("\n[Inside myFunction] - Hello! from myFunction\n")
}
/*Mandatory main function*/
func main () {
fmt.Printf("\n[Inside main] - now calling myFunction\n")
/*Call myFunction*/
myFunction()
fmt.Printf("\n[Inside main] - reaching the end of main function/program\n")
}
Output:
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*User defined function*/
/*This function accepts 3 arguments and returns one value*/
func findAverage (a int, b int, c int) float32 {
fmt.Printf("\n[Inside findAverage] - Received three arguments: \n\na = %d, b = %d, c = %d\n\n",
a, b, c)
/*Calculate sum*/
sum := a + b + c
/*Calculate average, use type casting to convert from int to float*/
avg := (float32 (sum) / 3.0)
fmt.Printf("\n[Inside findAverage] - Returning avg back to main\n")
return avg
}
/*Mandatory main function*/
func main () {
fmt.Printf("\n[Inside main] - now calling findAverage, passing 2, 8 and -3 as arguments\n")
/*Call findAverage, receive returned value in average variable (short declared)*/
average := findAverage(2, 8, -3)
fmt.Printf("\n[Inside main] - average = %f\n", average)
fmt.Printf("\n[Inside main] - reaching the end of main function/program\n")
}
Output:
Output:
Individual characters of a string can be fetched into a character array
using the rune functions as follows:
<character array var> = []rune(<String>)
Example:
c_arr = []rune(str)
An array of characters can be converted to a string using the string
function as follows:
<string> = string (<character array variable>)
str = string (char_array)
Here is a program that demonstrates the working of this function:
/*Rune demo*/
/*Package Declaration*/
package main
/*Import Statement - import fmt package*/
import ("fmt")
/*Mandatory main function*/
func main () {
str := "Excelsior"
str_length := len(str)
/*Use rune to fetchs characters in an array*/
str_char := []rune(str)
fmt.Printf("\nstr: %s, length: %d", str, str_length)
fmt.Printf("\n\nCharacter array: %c\n", str_char)
fmt.Printf("\nstr_char character array elements: \n")
for i:= 0 ; i < str_length ; i++ {
fmt.Printf("\nCharacter at index %d ==> %c\n", i, str_char[i])
}
}
Output:
There is a package called strings which has many built-in functions that
help in string manipulations. Let us take a look at a few important ones:
14.1 Concatenating strings
Two or more strings can be concatenated using the strings.Join function.
In order to do so, the strings to be concatenated should be placed inside a
string array. Here is the general syntax:
strings.Join(<string array>, <separator>)
Example:
big_string := strings.Join(arr, “ “)
There is an even simpler way of concatenating two or more strings –
using the + operator. General syntax:
<concatenated string variable> = <string 1> + <string 2> + ... <string
n>
Example:
big_str := “hello” + “ “ + “world!”
Let us write a program that demonstrates both these concatenation methods:
/*String Demo 2 - Concatenation*/
/*Package Declaration*/
package main
/*Import Statement - import fmt, strings packages*/
import (
"fmt"
"strings"
)
/*Mandatory main function*/
func main () {
/*Declare and initialize a string array*/
var words = [] string {"This", "is", "an", "array", "of", "7", "strings"}
/*Display the string array*/
fmt.Printf("\nwords array: %s\n", words)
/*Concatenate using strings.Join*/
words_str := strings.Join (words, " ")
fmt.Printf("\nConcatenated string (using strings.Join): %s\n", words_str)
/*Short declare some strings*/
str1 := "Go"
str2 := "Programming"
str3 := "Language"
/*Concatenate str1, str2 and str3*/
str4 := str1 + " " + str2 + " " + str3
fmt.Printf("\nstr1 = %s\nstr2 = %s\nstr3 = %s\n\nConcatenated string (using + operator)\n\nstr4 =
%s\n", str1, str2, str3, str4)
}
Output:
14.2 Compare strings
The Compare function from the strings package is used to compare two
strings. Syntax:
strings.Compare(<string1>, <string2>)
Example:
result := (string1, string2)
This function returns 0 is both strings are the same, returns -1 if string1 is
lexicographically less than string2 and returns 1 if string1 is
lexicographically greater than string2. Let us write a program to read two
strings from the user and compare them:
/*Compare two strings*/
/*Package Declaration*/
package main
/*Import Statement - import fmt, bufio, os, strings package*/
import (
"fmt"
"bufio"
"os"
"strings"
)
/*Mandatory main function*/
func main () {
/*Create an input reader variable of type NewReader using stdin*/
inputReader := bufio.NewReader(os.Stdin)
/*Prompt the user to enter something*/
fmt.Printf("\nEnter a string: ")
/*Read string using ReadString function*/
str1, _ := inputReader.ReadString('\n')
fmt.Printf("\nEnter another string: ")
/*Read string using ReadString function*/
str2, _ := inputReader.ReadString('\n')
/*Compare str1 and str2 using strings.Compare*/
result := strings.Compare(str1, str2)
if (result == 0) {
fmt.Printf("\nBoth strings are the same.\n")
} else if (result > 0) {
fmt.Printf("\nFirst string is lexicographically greater than the second string.\n")
} else {
fmt.Printf("\nSecond string is lexicographically greater than the first string.\n")
}
}
Output:
} else {
fmt.Printf("\nThe given string is not present in the main string.\n")
}
}
Output:
/*Palindrome*/
/*Package Declaration*/
package main
/*Import Statement - import fmt, bufio, os, strings package*/
import (
"fmt"
"bufio"
"os"
"strings"
)
/*Mandatory main function*/
func main () {
/*Create an input reader variable of type NewReader using stdin*/
inputReader := bufio.NewReader(os.Stdin)
/*Prompt the user to enter something*/
fmt.Printf("\nEnter a string: ")
/*Read string using ReadString function*/
str, _ := inputReader.ReadString('\n')
/*Trim \n and \r characters*/
str = strings.Trim(str, "\n\r")
str_length := len(str) - 1
/*Use rune to fetchs characters in an array*/
str_char := []rune(str)
/*Reverse str*/
for i := 0 ; i < str_length/2 ; i++ {
temp := str_char[i]
str_char[i] = str_char[str_length-i]
str_char[str_length-i] = temp
}
/*Convert back to string using string function*/
rev_str := string(str_char)
fmt.Printf("\nReversed string: %s\n", rev_str)
/*Check if both strings are equal*/
result := strings.Compare(str, rev_str)
if (result == 0) {
fmt.Printf("\n%s is a palindrome.\n", str)
} else {
fmt.Printf("\n%s is not a palindrome.\n", str)
}
}
Output: