Lesson Description

The "Structs" Lesson is part of the full, Complete Go for Professional Developers course featured in this preview video. Here's what you'd learn in this lesson:

Melkey begins covering custom data structures starting with structs. They are data types that can hold data and be passed around the application. The syntax for a struct resembles a class or type declaration from object-oriented programming languages. This lesson also demonstrates nested structs.

Preview
Close

Transcript from the "Structs" Lesson

>> Melkey: But I want to finish up more advanced data structures with Go. And here, I wanna start introducing us to custom data structures, which will be structs and pointers. And talk about a lot of more intricate things that maybe are native to Go, as opposed to these control structures, which are pretty common to other programming languages. So what I'm going to do is, I'm gonna remove the functions here, okay? And now we have func main, we have our import. I wanna talk about structs, so structs, I've briefly mentioned them a few times. Structs stand for structure, okay? And the textbook definition of a struct is a data type that can hold data in your app and pass it around along your application, okay? It holds data and you can use it across your app. That's kind of a very bare bone definition of a struct, but it has a lot more versatility power behind it than just that definition. So for example, structs were created for a bunch of different reasons in Go, it's kind of like the author's original answer to object oriented programming, because that's not in Go. Go has this concept of interfaces and structs that remove the necessity for object oriented programming. But you can see, if you come from an object-oriented programming language, you can see where structs kind of play a role in solving that issue. So here, I'm gonna create a structure called a person. So to define a struct, we'll do type then the name of the struct. So our struct can be person, and then the keyword struct followed by curly braces. Now if you notice, if we ignore this compiler, the elements for the unused format our compiler does not yell that we have person defined and not used. Because what is literally happening is, we are defining a new type. Person is a struct, but it is also a type. We now have the ability to use person types across our application, which means, we can define functions that take persons as arguments. We can write functions that return persons as arguments. We can use persons as an argument that we have made. It is our custom data type, okay? So, obviously, with a person, let's go ahead and create a person, right? So let's go ahead and just do, person to create and use our struct, and use the struct name, so person, followed by the curly braces, and then the explicit field. So we can put, oops, kind of ahead of myself here, but the person struck, we can put a name, so the name of the field, then the type, so a string, okay? And then we put age and int. So our person struck now has two fields, name and age. And it could have multiple fields, it could have many, many fields, right, of all different types. It could have a struct as a type as well. So you have name and age, and if you wanna use this, we can do our person and then, name, we can say something like, John, okay? And then age will say 25, okay? So now we have this person, it's not declared, but we can do format, Printf. This is our person, and we can use our format specifier, but here you have two options. So you can use the modulo v, all right, don't forget to break the line per person. If we save this, I'm gonna clear my terminal here. If we save that and run this, you can see this is our person, John 25, great. But if you wanna be a little more explicit and showcase the values of your struct, you can prepend a plus symbol in front of the v. So now, when you run it, you can see that our person struct now also demonstrates the field names associated to it. So it's a level of how explicit you want to be in the variable declaration. There's also something called anonymous struct. So here, we have a not anonymous struct. It's a defined struct, it's person. We know now it's a type, it's a struct. We can use it however many times we want. We can also have anonymous structs. We can have something like employee, and in here, we can define the struct in place. Struct wants our brackets a second set of brackets, curly brackets to be specific. The first set here determines the fields of the struct. Okay, so here, we'll put name string and something like id int. And then the second set of brackets fill those fields in. We actually provide values for those fields, we can do name, Alice, and we can do id 123, and this is what's called an anonymous struck. These have very, very powerful use cases, especially when we get into testing, okay? We'll see when we get into our testing module, how we make use of anonymous structs for handling our test cases in our application. And we can use this as well, right, format, just print law and you can say this is employee, right? I'm being a little lazy with the print line, but you can go ahead and use format specifiers, that's totally fine. So you can see here, if you run it, we now have our person struct and our anonymous employee struck as well.
>> Speaker 2: Are structs reference or value semantics, do they get copied when you're passing them around?
>> Melkey: Yeah, great question, everything in go, you always ask one question I had, like I love it. In Go, everything's parsed by value. It explicitly say something is reference, right? So gonna spoil the next part of the thing, but when we passed even a struct, we were passing a copy of it into our function. And in that copied value of our struct only exists in the scope of the function. And so, once that function executes, the memories released from the allocated struct. But you can pass structs by reference, and then modifications will persist, which I'll show you. We are going to continue on with structs. So we showcased anonymous structs, we've showcased a defined struct, our person struct above. And here, we're going to define two more structs, just so I can demonstrate nested structs. You will probably see this in a code, basically, right? But here, let's say we have type address. It's going to be a struct. I'm gonna make sure I type that correctly, all right, let's continue so we have this type address struct. Let's just say this has a street string, I'm gonna keep it simple. Let's just say city also a string, and let's say we have another struct, which we'll define as contact. So type contact is gonna be a struct like so, we'll save the name of this new contact, we'll say it's a string, and we can put address as our address struck like so, and then phone string, all right? So here, we have a second struct defined with a nested struct type, and again, it's not initiated. We don't have a contact just yet, but we do contact and create the contact struct type, we can put our name, let's say Mark, okay? And then for address, we put address here with the address struct just like this. So we kinda put it inside the definition of the parent struct that we have. We can say street, we can say is 123 Main street. And in City, we can put something like Anytown, okay? And one thing I forgot to mention, but we can actually omit fields in our struct. So here, if you wanna create this new contact without actually passing in the phone, that's completely fine. And again, this is due to zero values and the default values, so there's always a fallback to a type that is not explicitly defined, question?
>> Speaker 2: Are types scoped to the function block they're declared in? And can you redeclare types from other blocks?
>> Melkey: No, you cannot redeclare a type in functions. Once you have a type defined, that's the type. You cannot redefine them within the function block or without. So this didn't show the function has to adhere to function signature. Even if you have a variable declared in the function you cannot read declared a variable at a different type.
>> Speaker 2: There's a question about, when would you wanna avoid nested structs?
>> Melkey: When you want to avoid nested structs, so essentially, there isn't one reason to avoid them or not. However, like I was saying earlier, Go passes things by value, so we make copies of everything. So if you know in your code base, if you have a giant struct that has many nested fields, many nested structs. And you continuously passing that whole thing by copy, you're probably not exerting the best memory practices there. So you may wanna avoid that, you might wanna restructure and consider if you wanna use a nested struct at all. That's one of the main things I can think of when to not nest a struct is passing it down and making copies of it.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now