Home
Sign in Buy now

Golang Language Fundamentals

Structs and interfaces

Completed

Summary

In this episode, we explore Go's approach to composition over inheritance, where structs are combined to build complex data structures like a bank system with users, accounts, and transactions. We learn how to add methods to structs, such as a withdraw function, and discover how Go's duck typing enables powerful interface-based programming. The key takeaway is that interfaces should be discovered organically as patterns emerge across different structs, rather than being created preemptively.

Transcript

If you have ever programmed in other languages like Python, Ruby, PHP, you’ll be familiar with the concept of inheritance and object-oriented programming. Go is not an object-oriented language, as the creators have chosen to favor what is known as composition instead. A classical way of explaining object-oriented languages and inheritance is to think of a blueprint for, say, a car. You have a base model that all other cars will inherit from. But doing it this way can and often will lead to some cars having attributes and methods that does not really belong on that specific car. What Go does instead is to define structs that will represent elements of a car and when combined together becomes a car or represents a car. We don’t really need to discuss, the finer details of object-oriented versus composition. Both of them have their place. Just remember that in Go, you need to visualize structures. But how do we create a structure? Well, let’s begin by creating a user struct here. So we have the type keyword, then we have the name of the struct, and then we have the struct keyword. And let’s say we are creating a bank and we need to represent a user in the bank. This way, so we’ll have an ID, that’s an int64. Then we have a name, that’s a string. And then finally, we’ll have the address of the user. And the way we can create a user from this struct is we go into our function here. It’s a user and it’s a user struct. So the ID is just going to be one. Let’s say the name is going to be Alice. And then finally, the address. It’s going to be 123 Main Street. Our users would also have an account in this bank, right? So to illustrate that, we could create another struct here. Let’s just call it account. That has an ID. And let’s just say a balance. And then we could go ahead and add this struct to our user struct. So now our users also have… an account associated with them. An account will also typically hold transactions, right? So we can create another struct here. Let’s say type transactions. And the transaction will again have an ID of int64. And let’s just say we have a field here called created at. That’s a time dot time. And then finally, let’s just say amount. Again, an int64. And then we could update our account struct to have all the transactions made on that account. So let’s say transactions, which is a slice of transaction. There we go. So this is composition in play, right? We create structures and then we combine them together to create larger structures. But we can also add methods to these structs. Say we wanted to withdraw money from our account. We will go down here and we will say func and then a pointer to the struct. And then we will say, let’s just call this withdraw amount int64. And then let’s just return an error. And then we could see if a balance minus amount is less than zero. We would say return errors new insufficient funds. And if not, then we would just say a balance. And then we subtract the amount and then finally we just return. Now, we would also need to record the transaction and we could do so by adding another method to the transaction struct and then update. So we can see that those transactions associated with the account. Now, the method we just added, withdraw, can be used to describe a struct. And what I mean by this is that in Go we have what is known as duck typing. And that’s this little quote that says, if it walks like a duck and quacks like a duck, then it must be a duck. So we could define this in an interface. So say we have an interface. Here we have a duck. Here we have a duck. here called “Withdrawer Interface” and follows a similar pattern to structs. We have the type keyword and the name and then the interface keyword. And in here we would say “Withdraw Amount 64” and then “Error”. Now, anything that implements that interface can be thought of as a “Withdrawer”. And this becomes very powerful when we have, say, different accounts that can send, let’s say, money. So if we were to go down here, we could have a function that’s called “SendMoney”. That would have an amount argument and then, let’s say, receiving and then a receiving account. And then finally, we would have a sending account that implements with “Withdrawer”. There we go. And then let’s just return an “Error”. Return nil. So I’m not going to fill out the logic here, but this simply means that this function accepts anything that implements this “Withdrawer Interface” right here. This is very powerful. And when you’re just learning about interfaces, it can be very tempting to use them all the time. But as a rule of thumb, these interfaces should be discovered, not created. So once you start seeing the same type of behavior being used across different structs, it can be beneficial to abstract those into an interface. Go comes with a comprehensive standard library, which we will also touch upon soon. But if you want a good example of how we can utilize interfaces to accept more generic behavior, you could look up the I/O Writer interface, which does a really good job at describing a simple interface that is then reused throughout the standard library to do the same operation, but in different ways.

Episode Notes

Get the Full Course

Unlock all episodes and get lifetime access to course updates.

What others say

"With this course, I'm learning Golang + datastar while building my personal blog hitting several birds with one stone. It's a fantastic course."

Testimonial from ignacio
Ignacio Barceló
Bought Early Access

Video Completed!

Great job finishing this episode

Up Next

Golang Language Fundamentals
Packages, modules and privacy