The Go Language: What Makes it Different? - Jay McGavren

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everybody let's talk about GU so as mentioned I am the author of head frisco just published by o'reilly the amazon pre-orders should be shipping in the next week or two i'm also an instructor for tree house in software development and unlike the rust and zinc speakers i am not a language implementer so i am terrible about about talking about abstractions mostly i'm gonna let the code speak for itself during this talk the goals for the talk overall we're gonna get an overview of the language we only have about 45 minutes to a lot of time for questions might go a little over we'll see about that but regardless we're gonna be moving fast so you were not going to learn go by the end of the session where you can learn go there's this awesome website called the go tour it's interactive you can enter go code and run it right there in your web browser it's a fantastic way to learn will will keep the link to that at the end of the talk another humble recommendation is this little book i hear it's really well-written overview of the talk overall we're gonna give a quick sneak peek of some go programs which will help give context for the section that follows what go is exactly and why you might want to use it for your next project then we'll take a look at some of the more interesting aspects of basic go syntax we'll take a look at some object-oriented programming like concepts that go supports and we'll talk and by talking about concurrency using go routines and channels you can no need to take frenzied notes during the talk these slides are posted online you can review them at that URL which will repeat at the end as well ok so a sneak peek of some go programs here's hello world nothing that fancy about it this indicates that the this code is all going to be in the main package you then import the format package which contains the print line function which we call down here to print hello philly out to the terminal here's a tiny web app relies on the net HTTP package here we have a hello handler function which accepts a response writer an HTTP response writer as well as an object requesting our representing the HTTP request and it simply writes out an HTML header out to the response go supports first-class functions so we call the handle func function and specify that any time it receives a request with a path of slash hello it should pass that off to the hello handler we pass the hello handler function to the handle func function here's a quick look at a program that uses go routines and channels so we have here a response size function which accepts a URL it should retrieve as a string and then it also takes a channel that it should send the response size back over here in main we create a new channel which we then pass to the response size function and we call response size three times each with a go routine we set it up as a go routine just by proceeding it with the go keyword so those 3 calls all take place concurrently it doesn't wait for each response to come in before it makes its nest next request then we read the sizes off the channel we passed in and print them out we'll take a more detailed look at each of these programs later alright so why would you want to use go for your project let's take a quick overview of the language ethos if you will so it's got to see like syntax nothing too surprising there it compiles down to native code so you distribute one executable and you're done it's typesafe it's garbage collected which is another speaker said causes unpredictable stop the world latency glitches hasn't been a problem in my experience but you might not want to use it to write hardware drivers and concurrency is built into the language as you saw with go routines and channels ok but what can you do with go exactly well one thing you could write docker so I looked up a presentation by one of the doctor developers and he had some nice things to say about go go build embeds everything you need no more install this in order to run my stuff there's an extensive standard library and dated a lot of the functionality you need is built-in and there's strong duck typing a feature we'll be talking more about later you could write kubernetes for container management here's a these quotes are from a blog post from one of the kubernetes project founders coding though isn't overly complex people don't create factory factory objects everywhere something with the feel of seeing more advanced features like anonymous functions as a great combination and garbage collection we all know how to clean up after ourselves but it's so nice not to have to worry about it personally I like the fact that go value stability here's a quote from the go compatibility promise which is published online it's intended the program is written to the go1 spec will continue to compile and run correctly unchanged over the lifetime of that spec basically you don't have to worry about the language changing out from under you but here's my favorite quote about NGO overheard at this very conference just yesterday it's just a boring really reliable good language I like boring when it comes to my software how popular is go well there's a few different ways to gauge that I looked at the stack overflow 2019 developer survey which had a section saying the percentage of developers who responded that they use go and by that measure go ranks about number nine right behind Ruby right ahead of Swift go was designed by a small team at Google in 2007 it was made open and to open source in 2009 and it hit version 1.0 in 2012 so as languages go it's a baby rationale behind the creation of go the its creators have become frustrated by the undue complexity required to use the languages they were working with they wanted support for concurrency because multi-core processors are everywhere now but a lot of languages don't have built-in support for them they wanted to fix that and they wanted automatic memory management to make resource management tractable in a large concurrent program they needed garbage collection so that one of the language that had it there's things they left out on purpose and the whole thing's simpler object constructor is gone method overloading gone class inheritance mostly gone although there are equivalents and exceptions that's right no exceptions the go team felt that exceptions tend to get abused basically that it exceptions results in convoluted code and that developers tended to label too many ordinary errors as exceptional they provided an alternative instead for plain error handling go supports multi value returns so you can have your main return value and then an error return value is a second return value and you can use that instead of an exception there's no inheritance go has types and methods but there's no type hierarchies and no inheriting of methods again there's alternatives though you can embed types and other types to provide something analogous to subclass in and there's even improvements on the old model methods and go are more general than in c-sharp C++ or Java they can be defined for any sort of data even on built-in types like insert strings concurrency support with go routines one thread sports many go routines basically they multiplex independently executing functions co-routines onto a set of threads so a single operating system thread can run many go routines and that allows you to create hundreds or even thousands of go routines using the same resources you might use for a handful of threads so the effect for your program it's like having multiple function calls running simultaneously if you have a multi-core processor in your computer which you probably do go routines will help you make use of it other needs stuff there's first-class functions as we saw you can pass one function to another or store it in a variable there's built-in Unicode support and a room type to ensure that you are working with an entire character not half of the bytes of a character interfaces are fully decoupled from types that compile time duck typing we were talking about earlier and it includes lots of useful tools go yet for example will download other people's packages for you and install them so your code can use them go format will format your code for you and go test will run all your unit tests for you all that's included standard with every go install go formats pretty cool it automatically fixes your code style and here's the cool part it acts as the community style guide so there's no more arguing about tabs versus spaces its tabs by the way go format will change everything for you here's some code that's pretty badly in need of reformatting you can see the indentations all off the spacing is inconsistent so all I have to do is that my command line run go format and then the name of the file I want to reformat or I can have a hook and my editor automatically do this for me and there's the reformatted version much cleaner the go playground is neat you don't even have to install go to try it just go to play golang.org and you can edit and run go code in your browser will have that link at the end of the talk as well okay let's look at some ghost syntax so I cut a lot of stuff out of this portion of the talk we're keeping only the more interesting aspects in the interest of time all right so layout of every go file every go file starts with a package Clause which indicates what package you're currently in so this code here will all be in the main package then we have an import clause where we import any other packages we're going to use functions from so this one imports the format package and uses its print line function to print hello go out to the terminal if you need additional packages you just include them in the import statement here's a multi-part here's the multi import format here in parentheses so we import the format math and strings packages and you can see that we use the floor function from the math package to round a variable down our to around a floating-point number down we use the title function from the strings package to capitalize a string and we use print line again to print everything out to the terminal if you include an import and don't use it that's a compile error imports are expensive they slow down compilation and that was one of the priorities for the go project was fast compilation so go helps you by making sure that every import you declare actually gets used in your program if you don't that's a compile error it warns you and you can take the import back out if managing all that manually sounds a little tedious there's the go imports command it's a wrapper for go format so you can so it'll automatically reformat your code while it adds your imports for you you can install it with the command you see here or just do a web search for go imports that I'll have info when is uninstalling it and using a hook to integrate it with your editor so here is that previous example but with its import section removed all I have to do is hit save in my editor and the import section is automatically added for me and by the way another big goal of the go project was to make automated tooling easy go imports is just one example of the static code analysis that go enables variables boring topic right but you work with them a lot so it's worth discussing briefly every variable has a type associated with the go as a type safe language so here we declare a my integer variable with type in here we declare my float with type float 64 we assign values to them and we print the values and their types but of course declaring types everywhere gets a little boring so go has short variable declarations it can infer the type of what a variable should be from the initial value you assign to it here you're assigning an integer so the type of my integer must be int here you're assigning a float so the type must be float64 go doesn't allow you to add an import without using it and it doesn't allow you to declare a variable without using it either here we declare subtotal and taxpayer Able's but then print only the subtotal well we probably made a mistake there somewhere right why'd we declare tax if we're not going to perform a calculation with it so that's a compile error tax declared I'm not used that's your cue that hey you need to either remove that variable or do something with it for loops aren't too surprising you got an initialization you got a condition and you've got a post statement here but a little more interesting is the full range set up which will loop over a structure such as slice here and you can think of a slice like an array so here we've got a slice of strings this will loop over that slice and print the index and a value for each one of those you'll notice we provide two variables one to hold the index and one to hold the value what if we skip using the index though well again we're required to use every variable we declare right so that's a compile error I declared and not used in that case we can use the blank identifier that discards the value for you and it provides a clear visual indicator that a value is being ignored so you just put an underscore in place of the variable and that'll that'll indicate that you're discarding it both to go itself and to anyone who's reading your code multiple return values here we have a parse bool function from the string conversion package so it takes a string that contains a boolean and converts it to an actual boolean value but what if you were to pass a string that doesn't convert very well to a boolean such as the string fubar well that means to raise an error right well when we call parse pool and we only provide one variable to assign return valuable values who we get a compile error because parse Bowl is actually defined to return to values that second value is an error value it indicates that there was some kind of problem in converting the string to a boolean so up here this called the par school we now provide two variables to hole our return values true converts to boolean successfully so flag is going to contain true and error error here is going to be nil so no problems up here fubar flag is it's going to contain a boolean but it's not a value you can use because fubar doesn't convert to a boolean successfully so error is not going to be Mill in this case we just do very simple handling and we log the error value we get out to the terminal and then terminate the program you can do fancier error handling if your program requires it of course in go error handling is important the languages design and conventions encourage you to explicitly check for errors where they occur this is as opposed to other languages where you throw exceptions and sometimes catch them this quote from one of the go maintain errs in the go blog go supports first-class functions sometimes called higher-order functions so here we have a thrice function that takes another function as a parameter and invokes it three times here we have a refrain function which simply prints this string out and here down in main we call thrice and pass the referring function to it which gives us the output give it away give it away give it away now we could just as well us get declaring the refrain function explicitly though because you go supports anonymous functions we can just pass a function literal to thrice if we want here's a more practical use of first-class functions it's a simple web app we've got a Hello handler which takes a an HTTP writer and an HTTP request and as we saw before prints a header out to out to that response writer the hello handler displays hello web and the Bonjour handler displays Bonjour web then down in Maine we call the HTTP packages handle funk and pass it a string path of /hello which we specify any requests coming in that has that path should go to Hello handler this specifies any path cut or any request coming in with a path of Bonchurch and go to bones your handler go supports various loci like concepts it's not exactly goal P they're not exactly objects but you can do similar things with them so with objects an object contains data and behavior right so first we're going to need data with any variable and go you can declare that it's type is a struct struct as you're probably used to from other languages is just a an agglomeration of different fields each with its own type so here this bucket variable is going to hold the struct with number word and toggle fields numbers of float64 a word is a string and a toggle is a boolean and then we can assign values to each of those fields but of course repeating that struct type declaration everywhere you want to use it that's not too practical right so you can declare a type with that struct as an underlying type so you use the keyword type and you give it a name my type and here's that underlying type same syntax as you would use to assign the type directly to a variable and it's got a number word and toggle feels just like the previous truck did then all you have to do if you want a variable with that type with that type is you say var a bucket my type and it'll have those number word and toggle fields available for you you're not limited to struct types though as custom type can have an underlying basic type if you want like an end to float a boolean a string whatever you need so here we declare type leaders with an underlying value with an underlying type of float 64 and then its second type gallons with the same underlying type defining a type also defines a conversion from the underlying type to the new type so here we take the float 10.0 and we convert it to gallons here we take the float 240 point O and convert it to leaders you can define methods on any type even if the underlying type is just a basic type like an enter a float or a string as you see here you can define methods on it so here we take the type MyType i and we declare a new method on it called say hi we do that by specifying simply by specifying a receiver parameter so right before the function name we put the receiver parameter name followed by its type here in parentheses whatever type your receiver parameter has that's the type that the method is going to get declared on so my type now has a say hi function anytime we create a my type value it'll have a say say hi method we can call on it and the cool part about receiver parameters is they act just like another parameter you can access their value within the method just like you would this or self in other languages so we've got my type here here's a revised say hi method which takes the value in my type remember that's got an underlying type of string and it just prints it so if we declare a if we create a my type value with an underlying string of a my type value and call say hi on that will get hi from a my type value declare my type with an underlying string of another value and call say hi on that whoops and you'll get hi from another value but an underlying type is not a superclass the underlying type specifies how it types data will be stored but it will not inherit methods from that underlying type so here we have my type its underlying type is string as before and here we have my type 2 with an underlying type of my type we can do this this is legal we can create a my type 2 value with an underlying string but what we can't do even though the my type has a say high method find on it we cannot create a mind type to value and then attempt to call say hi on it because methods are not inherited from the underlying type you'll get a compile error saying my type 2 has no field or methods say hi although NGO has types and methods and allows an object-oriented style of programming there's no type hierarchy there is method and there's no method inheritance but there is another way to get the same benefits so the first thing you might want from inheritance is the ability to inherit data storage and you can do that by embedding struts so here we have a coordinates type it's based on a struct it has latitude and longitude fields and here we have a landmark type which has a name field and then it also has an anonymous field coordinates it has no name of its own just a type which refers to the type that we defined up here what we can do if we set it up that way is we can create a landmark value and we can assign a value to its name field no real surprise there but then it also apparently has latitude and longitude fields those are promoted from the embedded coordinates struct up to landmark and just like fields get promoted methods can get promote promoted as well so if we were to define a location method on coordinates here which you'll recall is embedded within location or within landmark all the location method does here is it takes the latitude and longitude fields and formats them as a string which it returns so we can create a new landmark value set its name latitude and longitude fields and then we can call the embed are the promoted location method on the landmark even though landmark doesn't have a location method defined on it directly that's promoted from the embedded type and you can bet additional types within a struct type to gain additional methods you've heard the saying favorite composition over inheritance before go implements that principle at the language level interfaces this part here is my favorite alright simple example we've got a type here with play and stop methods it's called tape player and we've got another type with play and stop methods this one's called tape recorder there's played there's stop and there's an extraneous record method which we're not too concerned about we've got a function that accepts the tape player value so it takes a slice of strings and loops over them and passes each of those strings to play on the tape player device it received then when it's all done playing the songs that call stop here in our main function we create that slice of strings and we create a tape player value and pass it to playlist and it will play each of those songs and then call stop when it's done but don't try to pass a tape recorder to playlist because playlist only accepts tape players you'll get a compiler if we try to do that can't use a can't use type tape recorder as type tape player when you're passing it to playlist but we'd like playlist to accept either a tape player or a tape recorder right they both have play and stop methods what you can do is you can define a player interface with the method you want so you use the same syntax for declaring other types type string the name you want your type to have and then the underlying type is an interface here in the curly braces you define a list of the methods you want it to have so we want it to have a play method that accepts a string parameter and we want it to have a stop method with no parameters notice that we didn't have to met modify either the tape player or tape recorder types we just declared the interface here too independently of it we can do that outside of the package where tape player and tape recorder defined we can do it anywhere we want and any type that has play play in stop methods automatically satisfies this interface now all we have to do is modify the plate function to accept a value of the player type we know that any player is going to have play in stop methods because the interface requires them so we can safely call them within playlists and now you can pass in a tape player or a tape recorder or any other type that happens to have play and stop methods and work the same structural typing is like compile-time duck typing it makes gold feel like a dynamic language such as Ruby or Python this from a blog post on the topic so pretty cool feature let's end with a look at concurrency using goroutines and channels so here's a non concurrent program it's and we took a sneak peek at this earlier it takes a URL as a string and it sends an HTTP request to retrieve that URL and then returns excuse me prints the length of the response body here in our main function we note the time that we started processing and we make three calls to response size and then at the end here we just print how long the whole operation took how long the whole program took to complete and here's the output we get example.com it's response sizes 1270 bytes golang.org is eight thousand bytes golang.org slash tacket slash doc is 1200 bytes or twelve thousand bytes scuse me whole thing takes 1.5 seconds to finish and that's because we're calling response size seria serially right we call response size we wait for the response to come back then we call the next make the next call to response size and that's fine if all you have is three URLs but imagine if you had hundreds or thousands of them that would take a while right so instead let's call response sizes go routine we're not going to make any changes to the response size function itself right now we'll just add the go keyword right before each call to it and that will one each of these function calls in a separate go routine concurrently unfortunately this doesn't work quite like we want the output consists of this scientific notation number the run times so brief that the program run duration is a fraction of a second and none of the responses go routines gets even a request their URL problem is the main go routine every main function runs and then its own go routine automatically even if you don't explicitly set one up that main go routine exits ending the program without waiting for the response sighs go routines to do their thing what we can do to fix this is modify the response size function to accept a channel as a parameter a channel type is written as Cham followed by the type of data you want that channel to carry so we say that response size is going to have a channel parameter of type Chan int we make no changes to most of the code within response size but then here at the end we calculate the length of the response body and we send that via the channel then here within main we record the start time for the program as we did before here we make a new channel by calling the built-in make function and we create a channel that's going to carry in we say that in the sizes variable here and then in for each of our response size go routines we're going to pass the sizes Channel is an argument to it will then read the size that response size sends back over that channel and print it out would be that three times and here's our result we get each of the pages we print each of the sizes and it finishes in half the time of the original less than a second so the channel accomplishes two things simultaneously the channel reads cause the main go routine to block until the response size go routine send so the program doesn't end until response size has a chance to do its thing and also the channel carries data you don't have to set up a shared with a mutex surrounding it or anything like that just read from the channel to get the data you need back so two birds one stone alright to wrap up stuff we didn't have time forward to further panic and recover all interesting topics defers interesting because it lets you make a function call and then defer it to run until the enclosing function ends so if you encounter an error you can be sure that your deferred function call is going to happen anyway we've got the panic and recover keywords also interesting we didn't have a chance to look at packages or modules really those are worth looking up we didn't get to talk about the testing package which comes standard with every go distribution definitely worth reading up on that didn't you get to talk about buffered channels which let you buffer a whole series of values sent over them before processing them and we didn't really get to talk about runes or utf-8 support definitely interesting features in the language so worth looking up let's see how are we doing on time because they were portions I cut out we're actually in fairly good shape so I am going to launch a little bonus presentation here so we are going to get to talk about panic and recover after all let's see assuming of course it's going to cooperate with me alright defer panic and recover I deferred it to the end so it's usually polite to end the conversation with goodbye right you start with hello you say nice weather eh you make your small talk for a while and then you say goodbye if you were to make an ordinary function call and right defer before it it'll be deferred until the enclosing function ends so we call format print line goodbye at first but because it has the defer keyword here it waits until the socialize function exits before it gets called so the output goes in the correct order anyway hello nice weather eh goodbye deferred calls deferred calls get made no matter what so even if socialized exits early say due to an error so we make our deferred called a goodbye we say hello and then we decided to talk today so we exit and this code won't get one but because we deferred the call to print goodbye we get our goodbye gets called anyway so it says hello it says goodbye and then it also prints our error that we returned I don't want to talk so the social order is maintained here's a somewhat more realistic example we've got a print lines function which takes a file name as a string we open it up if there were no errors or if there was an error opening it we return that and then of course it's always important to close the file after you open it right even if there's an error reading from it so we defer a call to file dog close then we create a new scanner which scans through the contents of the file and just prints each line a bit and again if there's an error we immediately return that well because we deferred a call oh sorry and then here in main we make a call to print lines with the file name that we want to process and we log any error that we encounter because we deferred a call to or because we deferred that call to file that close even if there's an error in scanning it we can be assured that file will be closed when we're done panic usually signals an unanticipated error this example is here just to show its mechanics so we've got a socialize function and we start our conversation hello but then we panic I need to get out of here and the code below that won't be run because the program exits immediately hello I need to get out of here however if we use defer to defer our goodbyes then even in the event of a panic will still perform all our niceties in the conversation hello goodbye we panics I need to get out of here and there's our stack trace below recover allows you to the recovery keyword allows you to recover from a panic excuse me it's actually a function call so here we define a calm down function so we call recover here recover returns whatever the panic value was so that we can process it and then we can print the value passed who that was passed a panic just by printing the value of that variable so in our socialized function we defer a call to goodbye we also defer a call to calm down so we start the conversation hello as before we panic as before and that gives us the results hello I need to get out of here goodbye the deferred calmed down prints the panic value and then because we called recover it halts the program panic the program doesn't then it doesn't print a stack trace now this may seem like an exception and the mechanics are kind of similar but panic is not intended to be used like an exception I know of exactly one place in the standard library that panic is used in normal program flow there's a recursive parsing function that panics unwind the call stack after a parsing error that function recovers and handles the error normally the general rule with panic is you can panic within your own package within your own library but don't allow a panic to cross package bounds that's bad form so panic acts like an exception but it's syntax is --all there's a little since hat syntactic vinegar surrounding it it's not intended for normal program use generally speaking you're only going to want to use panic to indicate impossible situations so here we've got a switch we randomly generate a number between 1 and 3 and depending which door number we get we print out what prize someone gets there shouldn't ever be a different number generated and this would be an appropriate case to use a panic if that ever did happen so if you know an error could happen generally speaking you should use normal control flow statements to handle it along with extra return values just google the phrase golang errors or values if you want some tips on making normal error handling more pleasant all right I think that's it for the segue so we did have time for defer panic and recover but I definitely recommend looking up this other stuff I need to give credit for the Go gopher logo which is by Renee French and here are those links that I promised here's a link up here we have a link to these slides if you want to review them if you want to play around with go in your web browser there's the go tour and go playground and there's a link to my book there at the bottom alright so let's go ahead and take some questions there at the bottom is the link where you can go ask them and I'm gonna switch to my browser and hope that I can figure out how this works when using go routines how does go maintain type safety in the event of a data race I actually am Not sure in that events yeah so I'm gonna have to punt on that one I'll attempt to ping me on Twitter and all attempt to look that up for you later let's see what kind of support does go have for calling lower-level functions say see for example there is C go the C go package so you can just call out I don't know the specific details but basically if there's a C function you can include the code and make a call to it direct light how fast is go compared to C C++ rust or zig there again the measurements are imprecise but there is a site out there called the programming language benchmarks game which has several standard algorithms that they ask people to implement in different languages generally speaking you're gonna find that C C++ and rust are going to be faster I prop I would presume Zig as well because of in part because of goes garbage collection so there's a little bit of a trade-off for having that nice feature anyway to timeout a channel wait I am not familiar with such a way No will a partially implemented interface work what if you have two interfaces in a scope that define the same function I am Not sure there could be a collision actually well I would think that only a type that implements the entire interface would be acceptable for where a particular interface is required so you could avoid collisions that way but no any any type that is missing methods required by the interface does not satisfy that interface and can't be used in those places what are practical reasons for creating a custom type that's inherited from another custom type to be honest I don't normally recommend doing that I included that in my samples to demonstrate that methods aren't inherited generally speaking you are going to want to embed your custom type within another type if you want to inherit any of its methods or fields who closes a channel how does Maine know how many values to accept expect from the channel I think you get to cover that here but channels can be closed I believe they are generally speaking closed by the go routine although it may be possible to close them from the main go routine as well and closing can be used to indicate when there are no more values to receive can you have multiple defer statements in one function yes you can the code samples we put up actually demonstrated that defers cause function calls to occur in the reverse order that they were deferred so the behavior is well defined and yes you can do multiple defers y have error but not include exceptions basically the reason the reason they were very specific about their reasons for excluding exceptions that they didn't like what exceptions did the control flow caused spooky action at a distance and all that good stuff so that's why they were excluded error was included as her error values were included as an alternative a reasonable alternative to exceptions can you cancel a defer if for instance you no longer need that return protection in your function no I believed once you defer that call is going to happen once the enclosing function exits no matter what so if you need that processing not to occur then your deferred function is going to have to detect the state somehow that it's processing is no longer required you'll have to include that in the function definition all right I think that's all I got thanks everybody you you
Info
Channel: ChariotSolutions
Views: 45,263
Rating: undefined out of 5
Keywords: go, programming languages, goroutines, philly ete, ete 2019
Id: FEFXjRoac_U
Channel Id: undefined
Length: 44min 46sec (2686 seconds)
Published: Fri May 10 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.