Arrays and Slices give
Arrays
Arrays in Go are fixed-size sequences of elements of the same type. Once declared, their size cannot change.
Example 1: Declaring and Initializing an Array
gopackage main
import "fmt"
func main() {
// Declare and initialize an array of integers
var numbers [5]int
numbers = [5]int{1, 2, 3, 4, 5}
// Accessing array elements
fmt.Println("First element:", numbers[0]) // Output: 1
fmt.Println("Last element:", numbers[4]) // Output: 5
}
Example 2: Iterating over an Array
gopackage main
import "fmt"
func main() {
// Declare and initialize an array of strings
var fruits [3]string
fruits = [3]string{"Apple", "Orange", "Banana"}
// Iterating over array elements
for index, fruit := range fruits {
fmt.Printf("Fruit at index %d: %s\n", index, fruit)
}
}
Example 3: Multi-dimensional Array
gopackage main
import "fmt"
func main() {
// Declare and initialize a 2D array
var matrix [3][3]int
matrix = [3][3]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
// Accessing elements in a 2D array
fmt.Println("Element at (1,1):", matrix[1][1]) // Output: 5
}
Example 4: Passing Arrays to Functions
gopackage main
import "fmt"
// Function that takes an array as a parameter
func sum(numbers [5]int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
func main() {
// Declare and initialize an array
numbers := [5]int{1, 2, 3, 4, 5}
// Call function with array argument
result := sum(numbers)
fmt.Println("Sum of array elements:", result) // Output: 15
}
Example 5: Arrays as Values
In Go, arrays are values. Assigning one array to another creates a copy of the array.
gopackage main
import "fmt"
func main() {
// Declare and initialize an array
arr1 := [3]int{1, 2, 3}
// Assign one array to another
arr2 := arr1
// Modify arr2
arr2[0] = 10
// Print both arrays
fmt.Println("Array 1:", arr1) // Output: [1 2 3]
fmt.Println("Array 2:", arr2) // Output: [10 2 3]
}
Slices
Slices are dynamically sized and flexible wrappers around arrays in Go. They provide more functionality compared to arrays.
Example 1: Declaring and Initializing a Slice
gopackage main
import "fmt"
func main() {
// Declare and initialize a slice
var numbers []int
numbers = []int{1, 2, 3, 4, 5}
// Accessing slice elements
fmt.Println("First element:", numbers[0]) // Output: 1
fmt.Println("Last element:", numbers[4]) // Output: 5
}
Example 2: Iterating over a Slice
gopackage main
import "fmt"
func main() {
// Declare and initialize a slice of strings
fruits := []string{"Apple", "Orange", "Banana"}
// Iterating over slice elements
for index, fruit := range fruits {
fmt.Printf("Fruit at index %d: %s\n", index, fruit)
}
}
Example 3: Modifying a Slice
gopackage main
import "fmt"
func main() {
// Declare and initialize a slice
numbers := []int{1, 2, 3, 4, 5}
// Modify elements in the slice
numbers[0] = 10
numbers = append(numbers, 6)
// Print the modified slice
fmt.Println("Modified Slice:", numbers) // Output: [10 2 3 4 5 6]
}
Example 4: Slicing a Slice
gopackage main
import "fmt"
func main() {
// Declare and initialize a slice
numbers := []int{1, 2, 3, 4, 5}
// Slicing a slice
sliced := numbers[1:4]
// Print the sliced slice
fmt.Println("Sliced Slice:", sliced) // Output: [2 3 4]
}
Example 5: Slices and Capacity
Slices have both length and capacity. Capacity represents the maximum number of elements that the slice can hold.
gopackage main
import "fmt"
func main() {
// Declare and initialize a slice
numbers := []int{1, 2, 3, 4, 5}
// Print length and capacity of the slice
fmt.Printf("Length: %d, Capacity: %d\n", len(numbers), cap(numbers))
}
In conclusion, arrays and slices in Go offer different capabilities and flexibility in handling collections of data. Arrays are fixed in size and primarily used for situations where size is known beforehand and doesn’t change, while slices are dynamic, resizable, and provide more functionality for managing data collections.
Maps in Go
Maps in Go are unordered collections of key-value pairs where all keys are unique within the map. They provide an efficient way to look up values based on keys.
Example 1: Declaring and Initializing a Map
gopackage main
import "fmt"
func main() {
// Declare and initialize a map using make function
var person map[string]int
person = make(map[string]int)
// Adding key-value pairs to the map
person["Alice"] = 30
person["Bob"] = 25
person["Eve"] = 35
// Accessing values from the map
fmt.Println("Age of Alice:", person["Alice"]) // Output: 30
}
In this example:
- We declare a map
person
with keys of typestring
and values of typeint
. - We initialize the map using the
make
function to create an empty map. - We add key-value pairs to the map using square brackets and assignment (
=
) operator. - We retrieve and print the value associated with the key
"Alice"
using bracket notation.
Example 2: Initializing a Map with Literal Syntax
gopackage main
import "fmt"
func main() {
// Initialize a map with literal syntax
person := map[string]int{
"Alice": 30,
"Bob": 25,
"Eve": 35,
}
// Accessing values from the map
fmt.Println("Age of Bob:", person["Bob"]) // Output: 25
}
In this example:
- We directly initialize the
person
map using a map literal syntax. - Each key-value pair is separated by a colon (
:
), and pairs are enclosed in curly braces{}
. - We access and print the age of
"Bob"
using bracket notation.
Example 3: Checking if a Key Exists in a Map
gopackage main
import "fmt"
func main() {
// Initialize a map with literal syntax
person := map[string]int{
"Alice": 30,
"Bob": 25,
"Eve": 35,
}
// Check if key exists in the map
if age, ok := person["Charlie"]; ok {
fmt.Println("Age of Charlie:", age)
} else {
fmt.Println("Charlie's age not found")
}
}
In this example:
- We attempt to retrieve the age of
"Charlie"
from theperson
map. - The expression
person["Charlie"]
returns two values: the value associated with the key"Charlie"
and a boolean (ok
) indicating if the key exists. - We use a conditional statement (
if
–else
) to check if the key exists (ok
istrue
). If it exists, we print the age; otherwise, we print a message indicating the key wasn’t found.
Example 4: Deleting an Entry from a Map
gopackage main
import "fmt"
func main() {
// Initialize a map with literal syntax
person := map[string]int{
"Alice": 30,
"Bob": 25,
"Eve": 35,
}
// Delete an entry from the map
delete(person, "Bob")
// Check if key exists after deletion
if age, ok := person["Bob"]; ok {
fmt.Println("Age of Bob:", age)
} else {
fmt.Println("Bob's age not found after deletion")
}
}
In this example:
- We use the
delete
function to remove the entry with the key"Bob"
from theperson
map. - After deletion, we check if the key
"Bob"
exists in the map. Since it doesn’t exist anymore, theok
value will befalse
, and we print a message indicating that"Bob"
‘s age is not found after deletion.
Example 5: Iterating over a Map
gopackage main
import "fmt"
func main() {
// Initialize a map with literal syntax
person := map[string]int{
"Alice": 30,
"Bob": 25,
"Eve": 35,
}
// Iterating over the map
for name, age := range person {
fmt.Printf("%s's age is %d\n", name, age)
}
}
In this example:
- We use a
for
loop withrange
to iterate over each key-value pair in theperson
map. - Inside the loop,
name
holds the key, andage
holds the corresponding value. - We print each person’s name and age using formatted printing (
Printf
).
Conclusion
Maps in Go provide a powerful way to manage collections of data with key-value pairs. They are versatile and essential in various scenarios, such as storing relationships between entities, counting occurrences, and more. Understanding how to declare, initialize, manipulate, and iterate over maps is fundamental for effective Go programming.
Structs in Go
Structs in Go are composite data types used to group together different types of data under a single name. They are analogous to classes in object-oriented programming languages but without inheritance. Structs are useful for organizing data into records or entities.
Example 1: Declaring and Initializing a Struct
gopackage main
import "fmt"
// Define a struct type
type Person struct {
Name string
Age int
City string
Salary float64
}
func main() {
// Initialize a struct using a struct literal
person1 := Person{
Name: "Alice",
Age: 30,
City: "New York",
Salary: 55000.0,
}
// Accessing fields of the struct
fmt.Println("Name:", person1.Name)
fmt.Println("Age:", person1.Age)
fmt.Println("City:", person1.City)
fmt.Println("Salary:", person1.Salary)
}
In this example:
- We define a
Person
struct type with fieldsName
,Age
,City
, andSalary
. - We initialize a
person1
variable of typePerson
using a struct literal with field names and values. - We access and print each field of the
person1
struct using dot (.
) notation.
Example 2: Struct Initialization with Implicit Field Names
gopackage main
import "fmt"
// Define a struct type
type Point struct {
X int
Y int
}
func main() {
// Initialize a struct without field names (implicit order)
point1 := Point{10, 20}
// Accessing fields of the struct
fmt.Println("X coordinate:", point1.X)
fmt.Println("Y coordinate:", point1.Y)
}
In this example:
- We define a
Point
struct type with fieldsX
andY
. - We initialize a
point1
variable of typePoint
without specifying field names, using the order defined in the struct definition. - We access and print the
X
andY
coordinates ofpoint1
using dot (.
) notation.
Example 3: Struct Embedding (Composition)
gopackage main
import "fmt"
// Define a struct type
type Address struct {
City string
Country string
}
// Define a struct with embedded structs
type Person struct {
Name string
Age int
Address // Embedded struct
}
func main() {
// Initialize a struct with embedded structs
person1 := Person{
Name: "Bob",
Age: 28,
Address: Address{
City: "London",
Country: "UK",
},
}
// Accessing fields of the embedded struct
fmt.Println("Name:", person1.Name)
fmt.Println("Age:", person1.Age)
fmt.Println("City:", person1.City) // Accessing embedded struct field
fmt.Println("Country:", person1.Country) // Accessing embedded struct field
}
In this example:
- We define an
Address
struct with fieldsCity
andCountry
. - We define a
Person
struct that embeds theAddress
struct. - We initialize a
person1
variable of typePerson
with values forName
,Age
, andAddress
(using struct literal forAddress
). - We access and print fields of both the
Person
struct (Name
,Age
) and the embeddedAddress
struct (City
,Country
) using dot (.
) notation.
Example 4: Struct Methods
gopackage main
import "fmt"
// Define a struct type
type Rectangle struct {
Length float64
Width float64
}
// Method to calculate area of Rectangle
func (r Rectangle) Area() float64 {
return r.Length * r.Width
}
func main() {
// Initialize a struct
rect1 := Rectangle{Length: 10.5, Width: 5.5}
// Call the method on the struct instance
area := rect1.Area()
// Print the calculated area
fmt.Println("Area of rectangle:", area)
}
In this example:
- We define a
Rectangle
struct type with fieldsLength
andWidth
. - We define a method
Area()
for theRectangle
struct, which calculates and returns the area of the rectangle (Length * Width
). - We initialize a
rect1
variable of typeRectangle
with specific values forLength
andWidth
. - We call the
Area()
method on therect1
instance to calculate the area and store the result in thearea
variable. - We print the calculated area of the rectangle.
Example 5: Working with Pointers to Structs
gopackage main
import "fmt"
// Define a struct type
type Employee struct {
ID int
Name string
Salary float64
}
// Function to increase employee salary using a pointer to the struct
func increaseSalary(emp *Employee, percentage float64) {
emp.Salary *= (1 + percentage/100)
}
func main() {
// Initialize a struct
emp1 := Employee{ID: 101, Name: "Alice", Salary: 60000.0}
// Print initial salary
fmt.Println("Initial salary:", emp1.Salary)
// Call function to increase salary (passing pointer to struct)
increaseSalary(&emp1, 10.0)
// Print updated salary
fmt.Println("Updated salary:", emp1.Salary)
}
In this example:
- We define an
Employee
struct type with fieldsID
,Name
, andSalary
. - We define a function
increaseSalary()
that takes a pointer toEmployee
(*Employee
) and increases theSalary
by a specified percentage. - We initialize an
emp1
variable of typeEmployee
with values forID
,Name
, andSalary
. - We print the initial
Salary
ofemp1
. - We call the
increaseSalary()
function with a pointer toemp1
(&emp1
) to increase the salary by 10%. - We print the updated
Salary
ofemp1
.
Conclusion
Structs in Go are versatile and essential for organizing data into meaningful entities or records. They support composition, methods, and pointers, making them powerful constructs for building complex data structures and systems. Understanding how to declare, initialize, access fields, define methods, and work with pointers to structs is fundamental for effective Go programming.
Interfaces in Go
Interfaces in Go are defined as a set of method signatures. Any type that implements all the methods defined in an interface is said to satisfy that interface. Interfaces enable polymorphism and decouple the definition of objects from their implementation details.
Example 1: Basic Interface Definition
gopackage main
import (
"fmt"
"math"
)
// Define an interface named Shape
type Shape interface {
Area() float64
Perimeter() float64
}
// Define a struct named Circle
type Circle struct {
Radius float64
}
// Define a method Area() for Circle to satisfy Shape interface
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
// Define a method Perimeter() for Circle to satisfy Shape interface
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
// Define a struct named Rectangle
type Rectangle struct {
Width float64
Height float64
}
// Define a method Area() for Rectangle to satisfy Shape interface
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// Define a method Perimeter() for Rectangle to satisfy Shape interface
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
func main() {
// Declare variables of type Circle and Rectangle
circle := Circle{Radius: 5}
rectangle := Rectangle{Width: 10, Height: 5}
// Declare a variable of type Shape (interface)
var shape Shape
// Assign circle to shape (Circle satisfies the Shape interface)
shape = circle
fmt.Printf("Circle - Area: %.2f, Perimeter: %.2f\n", shape.Area(), shape.Perimeter())
// Assign rectangle to shape (Rectangle satisfies the Shape interface)
shape = rectangle
fmt.Printf("Rectangle - Area: %.2f, Perimeter: %.2f\n", shape.Area(), shape.Perimeter())
}
In this example:
- We define an interface
Shape
with two methods:Area()
andPerimeter()
. - We define two structs
Circle
andRectangle
that implement theShape
interface by providing their own implementations ofArea()
andPerimeter()
. - Both
Circle
andRectangle
structs implicitly satisfy theShape
interface because they implement all the methods defined in the interface. - In the
main()
function, we declare variables of typeCircle
andRectangle
. - We declare a variable
shape
of typeShape
(interface). - We assign instances of
Circle
andRectangle
toshape
, demonstrating polymorphism where the same interface (Shape
) can hold different types (Circle
andRectangle
).
Example 2: Interface Embedding
gopackage main
import (
"fmt"
)
// Define an interface named Writer
type Writer interface {
Write(data string) error
}
// Define a struct named FileWriter
type FileWriter struct {
FilePath string
}
// Implement the Write method for FileWriter to satisfy Writer interface
func (fw FileWriter) Write(data string) error {
// Implementation to write data to file
fmt.Printf("Writing data '%s' to file: %s\n", data, fw.FilePath)
return nil
}
// Define a struct named ConsoleWriter
type ConsoleWriter struct{}
// Implement the Write method for ConsoleWriter to satisfy Writer interface
func (cw ConsoleWriter) Write(data string) error {
// Implementation to write data to console
fmt.Printf("Writing data '%s' to console\n", data)
return nil
}
func main() {
// Declare a variable of type Writer (interface)
var writer Writer
// Assign an instance of FileWriter to writer
writer = FileWriter{FilePath: "/path/to/file.txt"}
writer.Write("Hello, Go Interfaces!")
// Assign an instance of ConsoleWriter to writer
writer = ConsoleWriter{}
writer.Write("Hello, Go Interfaces!")
}
In this example:
- We define an interface
Writer
with aWrite
method that accepts a string and returns an error. - We define two structs
FileWriter
andConsoleWriter
that implement theWriter
interface by providing their own implementations of theWrite
method. - Both
FileWriter
andConsoleWriter
structs satisfy theWriter
interface because they implement theWrite
method. - In the
main()
function, we declare a variablewriter
of typeWriter
(interface). - We assign an instance of
FileWriter
towriter
, demonstrating how interfaces can be used to write data to a file. - We then assign an instance of
ConsoleWriter
towriter
, showing how interfaces can be used to write data to the console.
Interfaces in Go provide flexibility and enable code reuse by allowing different types to be used interchangeably wherever the interface is accepted. They promote loosely coupled designs and make Go programs more modular and extensible.
Leave a Reply