Skip to main content

Structs and Interfaces in Go

YashSejani
EditReport

Structs and Interfaces in Go

Hey there! In this guide, we'll explore Structs and Interfaces in Go. Go is not a traditional object-oriented language—it doesn't have classes or inheritance. Instead, it uses structs and interfaces to achieve similar, and often more flexible, designs. Let's dive in!

1. Structs in Go

A struct (short for structure) is a typed collection of fields. They are useful for grouping data together to form records.

Defining a Struct

You define a struct using the type and struct keywords.

type Person struct {
FirstName string
LastName string
Age int
}

Initializing a Struct

You can create an instance of a struct by providing values for its fields.

// Creating a struct with field names (recommended)
p1 := Person{
FirstName: "Alice",
LastName: "Smith",
Age: 30,
}

// Creating a struct without field names (relies on field order)
p2 := Person{"Bob", "Jones", 25}

Accessing Struct Fields

You can access or modify the fields of a struct using the dot . operator.

fmt.Println(p1.FirstName) // Output: Alice
p1.Age = 31 // Update age

2. Methods in Go

Go does not have classes. However, you can define methods on struct types! A method is simply a function with a special receiver argument.

// Method with a receiver of type Person
func (p Person) FullName() string {
return p.FirstName + " " + p.LastName
}

func main() {
p := Person{FirstName: "Alice", LastName: "Smith"}
fmt.Println(p.FullName()) // Output: Alice Smith
}

Pointer Receivers

If you want to modify the struct within the method, you must use a pointer receiver (*Person). If you just use a value receiver (like above), Go passes a copy of the struct.

func (p *Person) HaveBirthday() {
p.Age++ // This actually modifies the original struct!
}

3. Interfaces in Go

Interfaces in Go provide a way to specify the behavior of an object: if something can do this, then it can be used here.

An interface type is defined as a set of method signatures.

Defining an Interface

type Speaker interface {
Speak() string
}

Implementing an Interface

In Go, interfaces are implemented implicitly. You don't use an implements keyword. If a type has all the methods defined by an interface, it automatically implements that interface!

type Dog struct{}

func (d Dog) Speak() string {
return "Woof!"
}

type Cat struct{}

func (c Cat) Speak() string {
return "Meow!"
}

Because both Dog and Cat have a Speak() string method, they both implement the Speaker interface.

Using Interfaces

You can use interfaces to write functions that accept any type that implements the interface.

func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}

func main() {
myDog := Dog{}
myCat := Cat{}

MakeSound(myDog) // Output: Woof!
MakeSound(myCat) // Output: Meow!
}

4. The Empty Interface

The interface type that specifies zero methods is known as the empty interface: interface{} (or any in modern Go). Because every type has at least zero methods, every type implements the empty interface. It is used to handle values of unknown type.

func PrintAnything(v any) {
fmt.Println(v)
}

5. Best Practices

  • Favour small interfaces: In Go, interfaces usually have just one or two methods. (e.g., io.Reader, io.Writer).
  • Accept interfaces, return structs: It is a common Go idiom to have functions take interfaces as arguments (for flexibility) but return concrete struct types.
Finished reading? Mark this topic as complete.