
Go (also called Golang) is a statically typed, compiled programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson.
Key Features: - ✅ Simple & Clean - Easy to learn syntax - ✅ Fast Compilation - Compiles to native machine code - ✅ Built-in Concurrency - Goroutines and channels - ✅ Garbage Collection - Automatic memory management - ✅ Strong Standard Library - Rich built-in packages - ✅ Cross-Platform - Compile for Windows, Mac, Linux
Perfect For: - 🌐 Web servers and APIs - ☁️ Cloud-native applications - 🔧 Command-line tools - 🚀 Microservices - 📊 Data pipelines - 🤖 DevOps tools
Companies Using Go: - Google - Uber - Netflix - Docker - Kubernetes - Dropbox
Download Go:
# Visit: https://go.dev/dl/
# Or use package manager:
# macOS
brew install go
# Linux (Ubuntu/Debian)
sudo apt install golang-go
# Windows
# Download installer from go.dev
Verify Installation:
go version
# Output: go version go1.21.0 darwin/amd64
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Run it:
go run main.go
# Output: Hello, World!
Compile it:
go build main.go
./main
myproject/
├── go.mod # Module definition
├── go.sum # Dependency checksums
├── main.go # Entry point
├── internal/ # Private packages
├── pkg/ # Public packages
└── cmd/ # Command-line apps
package main // Executable program
package utils // Library/module
Rules:
- Every Go file starts with package
- main package = executable
- Other packages = libraries
// Single import
import "fmt"
// Multiple imports
import (
"fmt"
"strings"
"time"
)
// Custom packages
import (
"github.com/username/repo/package"
)
// Single-line comment
/*
Multi-line
comment
*/
// Documentation comment (appears in godoc)
// Package math provides mathematical functions.
package math
Go automatically inserts semicolons - you don't write them!
// No semicolons needed
x := 5
y := 10
z := x + y
// Method 1: var keyword
var name string = "Hardik"
var age int = 25
// Method 2: Type inference
var city = "Mumbai" // Type inferred as string
// Method 3: Short declaration (MOST COMMON)
email := "hardik@example.com"
count := 42
Rules:
- := only works inside functions
- Cannot redeclare with :=
- Can only use var at package level
// Boolean
var isActive bool = true
// String
var name string = "Go"
// Integer types
var age int = 25 // Platform-dependent (32 or 64 bit)
var count int8 = 127 // -128 to 127
var id int16 = 32767 // -32768 to 32767
var bigNum int32 = 2147483647
var huge int64 = 9223372036854775807
// Unsigned integers
var positive uint = 42 // Only positive numbers
var small uint8 = 255 // 0 to 255 (also called byte)
// Floating point
var price float32 = 19.99
var precise float64 = 3.14159265359
// Complex numbers
var complex64Num complex64 = 1 + 2i
var complex128Num complex128 = 2 + 3i
// Byte (alias for uint8)
var b byte = 'A' // ASCII value: 65
// Rune (alias for int32) - Unicode code point
var r rune = '😀'
var i int // 0
var f float64 // 0.0
var b bool // false
var s string // "" (empty string)
var p *int // nil
// Single constant
const Pi = 3.14159
// Multiple constants
const (
StatusOK = 200
StatusNotFound = 404
StatusError = 500
)
// Typed constants
const MaxUsers int = 1000
// iota - auto-incrementing
const (
Monday = iota // 0
Tuesday // 1
Wednesday // 2
Thursday // 3
Friday // 4
)
var x int = 42
var y float64 = float64(x) // Explicit conversion required
var a float64 = 10.5
var b int = int(a) // b = 10 (truncates)
// String conversion
import "strconv"
str := strconv.Itoa(42) // "42"
num, _ := strconv.Atoi("42") // 42
// Basic if
if age >= 18 {
fmt.Println("Adult")
}
// If-else
if score >= 90 {
fmt.Println("Grade A")
} else if score >= 80 {
fmt.Println("Grade B")
} else {
fmt.Println("Grade C")
}
// If with short statement
if err := someFunction(); err != nil {
fmt.Println("Error:", err)
}
// Basic switch
day := "Monday"
switch day {
case "Monday":
fmt.Println("Start of week")
case "Friday":
fmt.Println("End of week")
default:
fmt.Println("Middle of week")
}
// Multiple cases
switch day {
case "Saturday", "Sunday":
fmt.Println("Weekend!")
}
// Switch without expression (like if-else)
score := 85
switch {
case score >= 90:
fmt.Println("Excellent")
case score >= 70:
fmt.Println("Good")
default:
fmt.Println("Needs improvement")
}
// Type switch
var i interface{} = "hello"
switch v := i.(type) {
case int:
fmt.Printf("Integer: %d\n", v)
case string:
fmt.Printf("String: %s\n", v)
default:
fmt.Printf("Unknown type: %T\n", v)
}
Go has only one loop keyword: for
// Standard for loop
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// While-style loop
count := 0
for count < 5 {
fmt.Println(count)
count++
}
// Infinite loop
for {
fmt.Println("Forever...")
break // Use break to exit
}
// Range loop (arrays, slices, maps)
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {
fmt.Printf("Index: %d, Value: %d\n", index, value)
}
// Range with only value
for _, value := range numbers {
fmt.Println(value)
}
// Range over string (gets runes)
for i, char := range "Hello" {
fmt.Printf("%d: %c\n", i, char)
}
// Break - exit loop
for i := 0; i < 10; i++ {
if i == 5 {
break // Stops at 5
}
fmt.Println(i)
}
// Continue - skip iteration
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // Skip even numbers
}
fmt.Println(i) // Prints only odd numbers
}
// Labeled break (break outer loop)
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer
}
fmt.Printf("i=%d, j=%d\n", i, j)
}
}
// Simple function
func greet() {
fmt.Println("Hello!")
}
// Function with parameters
func add(a int, b int) int {
return a + b
}
// Shorthand for same type parameters
func multiply(a, b, c int) int {
return a * b * c
}
// Multiple return values
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
}
// Named return values
func calculate(a, b int) (sum int, product int) {
sum = a + b
product = a * b
return // Naked return
}
// Accept any number of arguments
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
// Usage
result := sum(1, 2, 3, 4, 5) // 15
// Assign to variable
add := func(a, b int) int {
return a + b
}
result := add(5, 3)
// Immediately invoked
func() {
fmt.Println("I run immediately!")
}()
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
// Usage
increment := counter()
fmt.Println(increment()) // 1
fmt.Println(increment()) // 2
fmt.Println(increment()) // 3
// Deferred function runs AFTER surrounding function returns
func example() {
defer fmt.Println("World") // Runs last
fmt.Println("Hello") // Runs first
}
// Output: Hello World
// Common use: Clean up resources
func readFile(filename string) {
file, err := os.Open(filename)
if err != nil {
return
}
defer file.Close() // Ensures file closes
// Read file...
}
// Multiple defers (LIFO - Last In First Out)
func stacking() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
}
// Output: 3 2 1
Fixed-size, cannot grow or shrink.
// Declaration
var numbers [5]int // [0 0 0 0 0]
// Initialization
primes := [5]int{2, 3, 5, 7, 11}
// Auto-size
auto := [...]int{1, 2, 3, 4} // Size = 4
// Access elements
first := primes[0] // 2
primes[1] = 100 // Modify
// Length
length := len(primes) // 5
// Iterate
for i, value := range primes {
fmt.Printf("Index: %d, Value: %d\n", i, value)
}
Dynamic-size, can grow and shrink.
// Create slice
var slice []int // nil slice
// From array
arr := [5]int{1, 2, 3, 4, 5}
slice1 := arr[1:4] // [2 3 4] (excludes index 4)
// make() function
slice2 := make([]int, 5) // Length 5, capacity 5
slice3 := make([]int, 3, 10) // Length 3, capacity 10
// Literal
nums := []int{1, 2, 3, 4, 5}
// Append
nums = append(nums, 6) // [1 2 3 4 5 6]
nums = append(nums, 7, 8, 9) // [1 2 3 4 5 6 7 8 9]
// Copy
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
// Slicing operations
nums := []int{0, 1, 2, 3, 4, 5}
nums[1:4] // [1 2 3]
nums[:3] // [0 1 2]
nums[3:] // [3 4 5]
nums[:] // [0 1 2 3 4 5]
// Length and capacity
fmt.Println(len(nums)) // Number of elements
fmt.Println(cap(nums)) // Capacity
Slice Internals:
// Slice = pointer + length + capacity
type slice struct {
ptr *array
len int
cap int
}
Maps are key-value pairs (like dictionaries/hash tables).
// Using make
ages := make(map[string]int)
// Literal
scores := map[string]int{
"Alice": 95,
"Bob": 87,
"Carol": 92,
}
// Empty map
empty := map[string]int{}
// Add/Update
ages["Hardik"] = 25
ages["John"] = 30
// Access
age := ages["Hardik"] // 25
age := ages["Unknown"] // 0 (zero value)
// Check existence
age, exists := ages["Hardik"]
if exists {
fmt.Println("Age:", age)
}
// Delete
delete(ages, "John")
// Length
count := len(ages)
// Iterate
for key, value := range ages {
fmt.Printf("%s: %d\n", key, value)
}
// Keys only
for key := range ages {
fmt.Println(key)
}
⚠️ Important: Maps are unordered - iteration order is random!
Structs are custom data types (like classes without methods).
// Basic struct
type Person struct {
Name string
Age int
Email string
}
// Nested struct
type Address struct {
Street string
City string
Zip string
}
type Employee struct {
ID int
Name string
Address Address // Embedded struct
}
// Method 1: Field names
p1 := Person{
Name: "Hardik",
Age: 25,
Email: "hardik@example.com",
}
// Method 2: Positional (not recommended)
p2 := Person{"John", 30, "john@example.com"}
// Method 3: Partial (unspecified = zero values)
p3 := Person{Name: "Alice"} // Age=0, Email=""
// Method 4: Zero value
var p4 Person // All fields = zero values
// Pointer to struct
p5 := &Person{Name: "Bob"}
person := Person{Name: "Hardik", Age: 25}
// Access
fmt.Println(person.Name) // Hardik
// Modify
person.Age = 26
// Pointer access (automatic dereferencing)
ptr := &person
ptr.Name = "Updated" // Same as (*ptr).Name
// One-time use
user := struct {
Name string
Age int
}{
Name: "Hardik",
Age: 25,
}
type User struct {
Name string `json:"name" xml:"name"`
Email string `json:"email" xml:"email"`
Age int `json:"age,omitempty"`
}
// Used for JSON/XML encoding
import "encoding/json"
user := User{Name: "Hardik", Email: "h@example.com", Age: 25}
jsonData, _ := json.Marshal(user)
// {"name":"Hardik","email":"h@example.com","age":25}
Pointers hold memory addresses of values.