Explore Go’s foundational elements with Basic Constructs & Data Types, mastering the essentials for efficient and robust programming
Basics π
Go files are name filename.go or filename_type.go
Some keywords are reserved in Go

Go has a set of 36 predeclared identifiers
| append | float64 | println |
| bool | imag | real |
| byte | int | recover |
| cap | int8 | int |
| close | int16 | int8 |
| complex64 | int32 | int16 |
| complex128 | int64 | int32 |
| copy | make | int64 |
| delete | new | uint |
| error | nil | uint8 |
| false | panic | uint16 |
| float32 | uint32 | |
| uint64 |
Blank Identifier - Go also has a blank identifier _ used to declare any variable of any type but it is discarded immediately after use.
Anonymous - Some functions can even have no names.
Import Functionality π
import "fmt"
import "os"
// or
import "fmt"; import "os"
//or
import (
"fmt"
"os"
)
// A package can also be given an Alias
import fm "fmt"
Packages π
Every Go file belongs to only one package whereas one package can comprise many different Go files.
Functions π
Simple function -
func functionName()
A few rules:
- The main function starts first
- Func main has no arguments or return values
- After every parameter, there must be a type
func func_Name(param1 type1, param2 type2, ...){
...
}
// Params can also share the same type
func func_Name(param1, param2 type1){
...
}
If it’s returning a type - () type1 { .... } or () ret1 type1 { .... }
If it’s returning multiple types - () (ret1 type 1, ret2 type2) {....}
Small functions can be written in one line like - func Sum(a, b int) int { return a + b }
Data Types π
Go is a statically typed language. Means the compiler can infer the type of the variable whether it’s indicated or not.
| Types | Examples |
|---|---|
| elementary (or primitive) | int, float, bool, string |
| structured (or composite) | struct, array, slice, map, channel |
| interfaces | They describe the behavior of a type. |
A variable is declared as var var_name var_type
A function type is the return type
We can also have user-defined type with aliases
type alias_name int
var a alias_name = 5
If you have more than one type and you’d like to have aliases
type (
IZ int
FZ float32
STR string
)
Go doesn’t automatically convert types unless done manually
To convert a type, do - valueOfTypeB = typeB(valueOfTypeA) || 3 = int(3.2). This is called type casting
Constants π
A value that cannot be changed by the program is called a constant. In Go, a constant can be defined using the keyword const as const identifier [type] = value
By convention, constants are written in uppercase - const INCH = 2.54
Also, a constantβs value should be known at compile time according to design principles.
Multiple assignments (untyped) - const BEEF, TWO, C = "meat", 2, "veg"
Multiple assignments (typed) - const MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY int = 1, 2, 3, 4, 5, 6
Enumerations π
Constant be used to create aliases that hold a value.
const (
UNKNOWN = 0
FEMALE = 1
MALE = 2
)
We can also enumerate with - iota
const (
UNKNOWN = iota
FEMALE = iota
MALE = iota
)
// same as
const (
UNKNOWN = iota
FEMALE
MALE
)
The first use of iota is 0, then 1, then 0 …..
You can also give enumeration a type name
type Gender int
const (
UNKNOWN Gender = iota
FEMALE
MALE
)
Variable π
The naming of variables follows the camelCasing rules. If it has to be exported, it has to start with a capital letter.
Declaration - var number int = 5 or var number = 5
When we omit the type, using the keyword var is extra. We can write the same line of code using the := assignment operator. So, number := 5. The only exception to this is that it can only be used inside functions and not the package.
Scope of Variables π
Global scope A.K.A package scope is available in all source files of a package. They can be changed anywhere in the code.
Local scope is defined inside of a function. They can only be changed inside the code.
Printing π
The fmt package which uses Println also has the Printf function, which uses a format-string as its first argument - func Printf(format string, list of variables to be printed)
fmt.Printf("Original Value of number: %d\n",number)
We used %d because number is an integer. %t prints boolean, %s prints string and so on. \n prints a new line
Elementary Types π
The three main elementary types in Go are:
- Boolean
- Numeric
- Character
Unless you have a good reason to, stick to the following types:
boolstringintuint32byterunefloat64complex128
Read more on types
Operators π
Built-in operators in Go: Arithmetic, Logical, and Bitwise.
Arithmetic Operators π
Binary operators +, -, *, and / that exist for both integers and floats
Logical Operators π
The following are logical operators present in Go: ==, !=, <, > , <=, >=
Boolean Logical Operators
- AND operator (
&&) - OR operator (
||) - NOT operator (
!)
Bitwise operators π
They are used to manipulate individual bits of integer values. Go supports the following bitwise operators:
Bitwise AND (&):
- The bitwise AND operator compares each bit of the first operand to the corresponding bit of the second operand. If both bits are 1, the resulting bit is 1; otherwise, it’s 0.
result := 5 & 3 // Binary: 0101 & 0011 = 0001 fmt.Println(result) // Output: 1Bitwise OR (|):
- The bitwise OR operator compares each bit of the first operand to the corresponding bit of the second operand. If at least one bit is 1, the resulting bit is 1; otherwise, it’s 0.
result := 5 | 3 // Binary: 0101 | 0011 = 0111 fmt.Println(result) // Output: 7Bitwise XOR (^):
- The bitwise XOR (exclusive OR) operator compares each bit of the first operand to the corresponding bit of the second operand. If the bits are different, the resulting bit is 1; if they are the same, the resulting bit is 0.
result := 5 ^ 3 // Binary: 0101 ^ 0011 = 0110 fmt.Println(result) // Output: 6Bitwise NOT (~):
- The bitwise NOT operator inverts each bit of the operand. It turns 1s into 0s and 0s into 1s.
result := ^5 // Binary: ^0101 = 1010 fmt.Println(result) // Output: -6 (in 2's complement form)Left Shift («):
- The left shift operator shifts the bits of the left operand to the left by a specified number of positions. The vacant positions on the right are filled with zeros.
result := 5 << 1 // Binary: 0101 << 1 = 1010 fmt.Println(result) // Output: 10Right Shift (»):
- The right shift operator shifts the bits of the left operand to the right by a specified number of positions. The vacant positions on the left are filled based on the sign bit (for signed integers).
result := 5 >> 1 // Binary: 0101 >> 1 = 0010 fmt.Println(result) // Output: 2
Bitwise operators are often used in low-level programming, such as device drivers or cryptographic algorithms, where fine-grained control over individual bits is required.
Strings π
Two kinds of string literals exist:
- Interpreted strings
- Raw strings
Interpreted Strings
"\n" // represents a newline
"\r" // represents a carriage return
"\t" // represents a tab
"\u" // represents Unicode characters
"\U" // also represents Unicode characters
Raw Strings
`This is a raw string \n`
The length of a string str (the number of bytes) is given by the len() function
len(str)
Concatenation of strings π
Two strings s1 and s2 can be made into one string s with:
s := s1 + s2
HasPrefix - strings.HasPrefix(s, prefix string) bool
HasSuffix - strings.HasSuffix(s, suffix string) bool
package main
import (
"fmt"
"strings"
)
func main() {
var str string = "This is an example of a string"
fmt.Printf("T/F? \nDoes the string \"%s\" have prefix %s? ", str, "Th")
fmt.Printf("\n%t\n\n", strings.HasPrefix(str, "Th")) // Finding prefix
fmt.Printf("Does the string \"%s\" have suffix %s? ", str, "ting")
fmt.Printf("\n%t\n\n", strings.HasSuffix(str, "ting")) // Finding suffix
}
Contains - strings.HasSuffix(s, suffix string) bool
Index - strings.Index(s, str string) int
LastIndex - strings.LastIndex(s, str string) int
IndexRune - strings.IndexRune(s string, ch int) int.
Replace - strings.Replace(str, old, new string, n int)
Count - strings.Count(s, str string) int
Repeat - strings.Repeat(s, count int) string
ToLower - strings.ToLower(s) string
ToUpper - strings.ToUpper(s) string
package main
import (
"fmt"
"strings"
)
func main() {
var orig string = "Hey, how are you George?"
var lower string
var upper string
fmt.Printf("The original string is: %s\n", orig)
lower = strings.ToLower(orig) // changing to lower case
fmt.Printf("The lowercase string is: %s\n", lower)
upper = strings.ToUpper(orig) // changing to upper case
fmt.Printf("The uppercase string is: %s\n", upper)
}
TrimSpace - strings.TrimSpace(s)
To trim a specific string str from a string s, use:
strings.Trim(s, str)
Split String on whitespaces - strings.Fields(s)
Split String on separator - strings.Split(s, sep). The separator can be :,;,,,-
Join over a slice - strings.Join(sl []string, sep string)
Read String - strings.NewReader(str)
Conversion to and from a string π
Package strconv contains a few variables to calculate the size in bits of the int of the platform on which the program runs:
strconv.IntSize
Converting a variable of a certain type to a string will always succeed. For converting from numbers, we have the following functions:
strconv.Itoa(i int) string
It returns the decimal string representation of i. Next, we have:
strconv.FormatFloat(f float64, fmt byte, prec int, bitSize int) string
It converts the 64-bit floating-point number f to a string, according to the format fmt (can be βbβ,βeβ, βfβ or βgβ), precision prec, with bitSize being 32 for float32 or 64 for float64.
For converting to numbers, we have the following functions:
strconv.Atoi(s string) (i int, err error)
It converts to an int. Second, we have:
strconv.ParseFloat(s string, bitSize int) (f float64, err error)
It converts to a 64-bit floating-point number
As can be seen from the return-type these functions will return 2 values: the converted value (if possible) and the possible error. So, when calling such a function, the multiple assignment form will be used:
val, err = strconv.Atoi(s)
Converting a string to another type will not always be possible (as in the case of the functions Atoi and ParseFloat above). Therefore, a runtime error is thrown: parsing "...": invalid argument.
Time and Dates π
t := time.Now()
fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year()) // e.g.: 29.10.2019
func (t Time) Format(s string) string
t := time.Now().UTC()
fmt.Println(t.Format("02 Jan 2006 15:04"))// e.g: 29 Oct 2019 11:00
Pointers π
package main
import "fmt"
func main(){
var i1 = 5
fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1)
}
// An integer: 5, it's location in memory: 0xc82000a270
intP = &i1
So, intP stores the memory address of i1 which means it points to the location of i1. In other words, it references the variable i1.
ππ½ See all notes in this series