Advanced Golang: Generics Explained

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up ladies and gentlemen it's Ryan here and today I want to talk about generics in golang generics is a feature that allows you to write your code in a way where you don't have to repeat the same code over and over again generics has been a part of many other languages for years now C plus plus Java rust and so on but it's rather new for golang and it's probably the biggest update to the go language pretty much ever it just came out recently in the 1.18 release in 2022 so again generics and golang that's what we're going to go over today and let's go ahead and jump into it so let's say you have a function called add and it takes in two parameters one is a which is an INT the other one is B which is also an INT and in the end we're going to return an INT and we're gonna say return a plus b as a sanity checklist just run this print the result and yeah three just as we expected so this is great and all um the only problem is what if we want to pass in something other than an INT what if we change this to 1.1 and 2.2 we want these to be floating Point numbers then what happens okay yes as expected is telling us hey this is a float you're trying to pass it as an into argument that doesn't work and so what we can do here is well we can say you know what let's make this add int and then make this another function called add float and then we can change all these to float 64. and just say Okay add float and sure this works uh as expected got a floating Point error there but the problem is that we have multiple versions of this same logic right it doesn't make sense for all of these or you're doing a plus b so we should be able to reuse this Logic for different types right well now with generics we can do that so let's go back to our previous logic so first of all make sure you're using go 1.18 or later because this will not work on the older versions of golang so having said that what we want to do is add some brackets here say t that's our new type and we're going to say int or float64 and instead of int we're going to say t t and t basically we just turn this into a generic function now it's our IDE is not complaining at least so we're passing in integers Let's test it make sure that works yep and let's turn these into floating Point numbers make sure that works and yep as expected this is cool but the problem is there's a lot of different types of ins right there's INT in 8 16 32 64. so am I really going to go here and do int into 8 and 16 blah blah blah float 32 yada yada yada uh no this is just a little bit too verbose so the first thing I can do is I can move this out create something called num and then we can say type num interface blah blah blah and what we just did is create our own data type called num and that's what T is and so saying the parameters and return type can be any one of these that are part of that interface if we run it yep works as we expected to so still it's a little bit verbose kind of not the way we want to do things right and other languages that use generics you don't even have to do this uh if it were C plus plus for Java you could just say t and so what we can do here instead is let's get rid of num and we're going to say constraint dot ordered you do need to manually import this into your project but it's golang.org X slash exp constraints what this is is basically they took care of all the dirty work that we just did ourselves so all the signed in types all the unsigned int combine those into a union float 32 64 complex and they even added a string at the end of all that so you can concatenate strings so awesome and if we run that yep works as expected so let's go back to the original example where we had int and Float 64. okay what if we have this function we only care about instant flow 64s we really don't care about all that other stuff that's fine it's very common in go for us to create our own type aliases so user ID int so this is the user ID is just an alias for INT and this should work right we should be able to pass in a user ID into this function so let's try that a equals user ID 1 b equals user ID 2 and let's pass in A and B here well my IDE is complaining and saying yeah that doesn't work what does the compiler say yep user ID does not Implement that interface so we add this squiggly thing here I think it's a tilde and that will solve the problem so we run it and yeah it works so basically this tilde allows you to use any type that is an alias for this underlying type so now I'm going to go over a more sophisticated real life example of how you might use generics um in programming there's three common functions that you run into map filter and reduce and I'm going to try to create a mapping function using generics and go so let's check that out so with a mapping function you have an input which is an array of values and then you have an output which is a function that mutates those values so I might say n times 2 and I expect the output to be an array 2 4 and 6. so let's go ahead and try to implement this with generics but first we're just going to create a non-generic function for it so we'll say funk map values will have values which is an array of int for now and then a function we'll call it map Funk which is a funk that takes in an INT and returns an INT and then in the end we're going to return an INT array so we'll say VAR new values irrelevant we'll say four each value in that list of values we passed in we'll say new value equals the mapped version of V and then we'll add that to new values cool and then in the end we're just going to return new values awesome so what we have here is a non-generic just a standard version of the mapping function so let's go ahead and just see if it works the way we expect it to so we'll say result is map values array of int one two three and we'll pass in a function return n times two and let's go ahead and print this so let's go ahead and see if this works how we expect it to so yep two four and six right we're taking one two three n times two let's make it times three now three six nine let's make it let's make it times five five ten fifteen so yeah it works exactly how we expect it to work so once again the problem though is that we can only pass in integers right if I try to make this float 64 let's make these unambiguously floats and I want to make these floats as well just across the board it just doesn't work because it's only accepting integers so again let's turn this into a generic function so I'm going to say t is constraints dot ordered so remember constraints.ordered we have to import this this is not automatically included in your project once you import it you can use this and this contains a union of all the different number types and string as well so we're going to say t that's our type and everywhere it says INT in our function we're just going to replace that with t and boom that quick and easy we turned it into a generic function and let's see if that works yep I'm gonna assume this math is correct but it looks correct so the next thing I want to show you guys is that you're not limited to only using generics with functions you can also use them on structs for example so let's say we have a struct called user and user has an ID and a name and some arbitrary data we don't know what the data is exactly we might be inclined to say interface which technically allows you to use anything you want but generally you want to avoid using interface like that because then you have to cast that into what you actually want it to be and the compiler can't help you and it just sucks so what we can do is after the struct name add our brackets here we can say t is type custom data and we can say type custom data is an interface that can be say constraints dot ordered so it could be any number or string and maybe we even want to allow it to be in a REV byte or an array of roon just about anything but the whole point is we do have explicit typing here right and so here we say data is type T and so let's go ahead and say U equals user let's try to instantiate this so here we have our user and it looks okay here right ID name data but the problem is it needs to know what specifically what type we want to use for data and so we'll have our brackets here and we'll say um I'll let it be an INT then I'll let data be three and then let's go ahead and print this and let's run it and see what happens and yeah print our user the ID blank name but data is three uh let's allow this to be a string Okay cool so the nice thing is that we have the flexibility for data to be practically anything we want so we don't have to resort to using a plain old interface and relying on runtime checking if I make that a string then it doesn't complain and it compiles so this is pretty awesome to give you an extra layer of flexibility in your data types without sacrificing safety all right so the last thing I want to show you guys is that you can use generics on maps as well so we'll say type custom map is a map of let's say string to int that's how we're going to start off well what if we want the key to be more than just a string right well we could say interface but nah we don't want to do that but we'll say t and we need to Define what T is so T is comparable by the way this is a potential job interview if you're looking for a role as a go Lane developer you might run into this right they'll ask you what are the valid data types for the key of a map and the answer is comparable any type which is comparable which means basically any type where you can pair one value to the other so you can say A and N to equals B and int that works right I can say I could do the same thing for string you can actually do the same thing for pointers as well so it's just a blanket sort of Alias for any type which can be directly compared to itself using the equals equals operator so we'll say okay T is comparable so that can be practically anything and we'll say the value can be an INT or string and then we'll say V here so let's go ahead and instantiate this we'll say make or say the key is of type int and the values of type string and that works M of 3 equals blah there you go ladies and gentlemen that's how you can use generics and golang to do more with less code if you liked the video please like And subscribe support a little YouTuber like myself and thank you for watching
Info
Channel: Code With Ryan
Views: 57,504
Rating: undefined out of 5
Keywords:
Id: WpTKqnfp5dY
Channel Id: undefined
Length: 13min 36sec (816 seconds)
Published: Wed Nov 30 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.