Want to learn how to build better Go applications faster and easier? You can.
Check out my course on the Go Standard Library. You can check it out now for free.
Introduction:
In Go, a struct is a way to create your own custom data types. It’s like building a blueprint for a new type of object.
Think about it this way: you have a collection of information (data) that belongs together. Instead of having separate variables for each piece of information, a struct lets you combine them into a single structure. This is helpful because it keeps your code organized and easy to understand.
Introduction to Structs:
Let’s say you want to store information about a person. You could use separate variables for their name, age, address, etc., but that can get messy. A struct lets you create a new type named “Person” to hold all that data in a structured way:
Step by step explanation:
type
keyword. This structure would typically include fields for things like name, age, and address. For example:package main
import "fmt"
// Define a struct to represent a person.
type Person struct {
FirstName string
LastName string
Age int
Address string
}
func main() {
// Create a new instance of the "Person" struct.
person1 := Person{
FirstName: "John",
LastName: "Doe",
Age: 30,
Address: "123 Main Street",
}
fmt.Println("First Name:", person1.FirstName)
fmt.Println("Last Name:", person1.LastName)
fmt.Println("Person's age:", person1.Age)
}
This code defines a struct named “Person” with three fields: FirstName
, LastName
, and Address
.
Why it matters:
Structs are powerful for organizing data. Instead of thinking about a person as separate pieces of information (like individual variables for firstName
, lastName
, and age
), we can create a single type that defines all the essential characteristics.
Creating Meaningful Data Structures:
In this example, “Person” is a custom data structure. We can think of it like a blueprint for building a person object in Go.
type Person struct {
FirstName string
LastName string
Age int
// ... other fields
// Example:
Name string
Age int
Height float64
Weight float64
}
func (p *Person) speak() {
fmt.Println("Hello, my name is", p.FirstName, p.LastName)
}
Creating a “Person” Type:
Let’s say you want to use the Person
struct to store information about a person and their address.
You can think of it like this:
// Define a struct for a person
type Person struct {
FirstName string
LastName string
Age int
Height float64
speak func()
}
func (p *Person) setHeight(height float64) {
// ... code to change the height of the person
fmt.Println("Setting a height for this Person!")
// ... code to access and modify the 'height' field
}
Speaking about the “Person” type:
The speak
function is a great example of how Go allows you to define functions that belong to a specific data structure.
In this case, the ‘Person’ struct would have a function defined on it:
// ... (previous code for 'FirstName', 'Age' and 'Height' fields)
// Define a function to speak.
func (p *Person) sayHello() {
fmt.Println("Hello,", p.LastName, "!", p.FirstName)
}
This is a good example of what we call a method. A method is simply a function that’s defined on a specific data type.
By defining the speak
function directly on the ‘Person’ struct, we can give each person instance its own way of saying “Hello” through the p.speak
.
Defining methods:
A method in Go is a function that has a special receiver parameter. This allows us to define functions specific to an object.
In our Person
example, the sayHello
function would be defined as:
func (p *Person) sayHello() {
// ... (code for the 'speak' method)
}
type Person struct {
FirstName string
LastName string
Age int
Height float64
}
// This code defines a new instance of the 'Person' struct.
// We are defining a function `sayHello` that is specific to the 'Person' type:
func (p *Person) sayHello() {
fmt.Println("Hello,", p.LastName, "!", p.firstName)
}
func main() {
// ...
person := Person{} // We don't need a height in this example!
person.sayHello() // Call the 'sayHello' function directly on the struct instance
}
Why use Structs and Methods?
Organization: Imagine trying to keep track of all the information about a person using separate variables. You’d have a lot of data floating around: firstName
, lastName
, age
, height
, weight
, address
, etc. A struct lets you combine these into a single, organized unit.
Readability: Keeping all the information for a person together in a struct makes your code easier to understand and maintain. You can easily see that ‘person1’ has both ‘firstName’, ‘lastName’, age
, and ‘height’ as attributes.
Reusability: By defining methods on the Person
struct, you can reuse the same code for handling a person’s name (or in this case, their height) across different parts of your program.**
Reusability:
Using a method
to define the ‘hello’ function is just one way to show how they are useful. Imagine needing to calculate the BMI of a person.
// ... (previous code for "Person" type)
// Function to represent height in the 'Person' struct
func (p *Person) sayHello() {
fmt.Println("This is a function to print a greeting!")
}
type Person struct {
FirstName string
LastName string
Height float64
// ... other fields
// Define a `sayHello` method on the 'Person' type
func (p *Person) speak() {
println("Hello,", p.lastName, "!")
}
type Person struct {
FirstName string
LastName string
Age int
Age float64 // We can use 'float64' for height and age
// ... (rest of the code)
// Calculate BMI
func (p *Person) speak() {
fmt.Println("Hello, I'm a", p.FirstName, "and I'm", personAge, "years old.")
}
BMI Calculation:
In this example, we can use the calculateBMI
function for calculating the BMI of any object that has a height
and weight
value:
// ... (previous code)
person := Person{FirstName: "John", LastName: "Doe", Height: 1.75, Weight: 75.0} // Example of 'Person' struct with fields