 This is going to be a really quick video where I show you some examples of go code translated into JavaScript using the go for JS compiler. If you want to convert your go code into JavaScript, it's helpful to understand how that conversion works. So first off in this example, we have the simplest possible go program, just a main function that prints out some variables. And if I come down here and I build the program, so if we go to the output, which is a single file here, go for test.js, there's a whole lot of code in here. It's like 70,000 bytes about most of this is of course not a result of my code. It's the runtime code. It's an equivalent of the go runtimes code for managing go routines and a few other things. Obviously, if we're compiling to JavaScript, this runtime code doesn't have to add a garbage collector. JavaScript has its own garbage collector, but there's various go runtime equivalent stuff in here. And then our actual code is way down at the bottom. If we look for main, this is our actual code, just a single function main. And you can see that our int string and Boolean variables in the go code are translated into their direct JavaScript equivalents. Though of course in JavaScript, we lose all typing information. There's no declaration of what type of variables that these are. Booleans become Booleans, strings become strings, and our int becomes just a JavaScript number. We have a number type in JavaScript, which is basically a float 64. So when any number type in go gets translated into a number in JavaScript, the underlying type is always going to be just JavaScript number. And also note that when we use the print line built in function in the go code that gets translated into console.log. If you import the fump package in your go code, and then invoke fump.print or print line, it doesn't get translated to console.log. That is translated into code, which in a node environment will print out to actual console, will print the standard output. Whereas in the browser, we want to print out to console.log. So that's why we're using print line and not fump.print line. Though also, you have to be careful about importing fump because the fump package uses reflection and the reflection package when compiled into JavaScript requires a huge amount of special code that is like almost a megabyte in size. So in general, when using Go for Jazz, we avoid fump than any other package which uses reflection because it blots the output code enormously. In our next example, now we're introducing a struct type foo with three fields a, b, and c and string and booleans. And we create a single variable x of type foo and assign values to its three fields and then print out x. If we come down here and compile, and we go look at the code, now you see this is the equivalent in the JavaScript code of the struct declaration. There's quite a bit going on here with this call to new type, though that's really internal business of the Go for Jazz compiler. I'm not entirely clear exactly what it does, but it basically creates a data structure in the JavaScript side, which is a representation of the foo struct in our go code. And then down in main, our x variable of type foo, of course, does not have the foo type on it because we don't have static typing in JavaScript. And when a value of type foo is created, it's done so with this code, which returns an object. And then the fields of our struct value are just properties of that object, a, b, and c. So real quick to see this in the browser. I've created this test.html and I've loaded it up already in the browser. If hit refresh, we see on the console, this object, which has an a, b, and c. And then under the prototype, we can see that Go for Jazz has given this instance of foo. These get in set methods. I'm not sure what those are about. Also, there's the property val, which is a recursive reference to the same object. I don't know why that's in here, but we can just recursively descend forever. That must be there for some reason, I suppose. Anyway, notice that the struct values are basically represented as JavaScript objects where the structs of the field correspond to properties of the same name. In this next example, it's the same code, but now we're creating variables y and z, assigning to y the value of x itself, which in Go would mean copying the struct value. When you assign structs, the assignment is a copy, really. And so what we're going to see in the JavaScript code for this assignment is it's going to have to actually copy the foo struct and then assign the result of that copy to y. Whereas here, if z is a pointer to foo and we're getting a pointer to x, it just copies x to z. In JavaScript code, it's just going to be a plain assignment of x to z. So looking at the actual JavaScript code, here's that assignment of x to y and the x object is copied in this call to clone. Whereas when x is assigned to z, it's just a plain assignment. Here we've introduced a function bar, which takes in a value of type foo, our struct type. And we have again our variable x of type foo, which we pass to this call to bar. If we compile the code and go look at the JavaScript code, when bar is called, because structs when assigned and passed the functions are effectively copies, x has to be cloned and then passed the bar. And notice that in our function bar, we don't have any type on the F parameter. Of course, you can't have static types in JavaScript code, but that's not really a problem because when our go code is compiled by Goverges, it's doing static type checking. So we're still getting the benefits of it checking for our type correctness. So in the call to bar and our go code, it would complain if x were not of the right type, if we're not of type foo. Now let's look at a couple pointers. Here we have variables A and B of type int, but also C and D of type pointer int. And we initialize A to the value three, B to the value of A. And C and D will both assign the address of A. And go look at the JavaScript code. You can see that our declared int variables are initialized with the value zero, no surprise there. That's the default value for an int. Our pointers C and D are initialized with this nil value. But then the reference operator expressions have all this funny business. And what's going on is that a pointer type is being created. And in this pointer type, it's provided two closure functions. The first returns the value of the variable pointed to, and the second sets it. And the reason for this funny business with the A dollar sign 24 pointer, this variable that is introduced by the compiler is because when we get the pointer to variable A more than once in this function, we don't want it to be different pointers. We want it to be the same singular pointer object both times. And so what this code is effectively doing is caching the pointer type in this variable and next time around, if it's non null, that is then what's going to be assigned to D. So it doesn't create a second pointer type object. Off the top of my head, I can't imagine a scenario where two separate objects representing a pointer to the single variable A would actually create incorrect code. So I wonder if this is just done as an optimization to avoid proliferation of redundant pointer objects. In any case, you can see how they simulate pointers to local variables using closure functions. In this next example, we're creating some arrays. First an array of size three of type foo, assigning that to A. And then an array of size three of type int with these three starting values, and that's assigned to X. An array of two strings with these starting values, and that's assigned to Y. And then we're assigning X to Z. And we'll see two interesting things in the JavaScript output. Arrays of most types in Go will be translated to the generic array type in JavaScript. But for ints, it's going to use the special in 32 arrays, because that's going to be a little more compact and so a little more efficient for the special case of ints. And then when the assignment is performed, again, arrays like structs are assigned and passed by copy. So in the JavaScript here, we'll see that X is cloned for this assignment. I'm going to compile the code. We go look at the JavaScript. And yeah, there's that assignment with the clone. Notice that for every array type we're using in the function, it creates these local variables representing the different array types. And these two native array calls are what return actual array objects. And the compiler passes in something specifying the type of the array. And if we go over to the browser and reload the page, it spits out on console the arrays we created. The first one here was our foo array. It's basically a normal JavaScript array. And each element is an object representing a foo value. The X array is just an ordinary int32 array. This is all just standard stuff to JavaScript. And a string array, same deal, it's just an array of strings. If we change the arrays into slices, then the first notable difference is that this assignment of X to Z is just going to be assigned by reference. Because, and this is a subtle point, in Go, slice values themselves are actually immutable. There's no operation that will directly modify a slice value itself, where the slice value is a pointer to an array, a number representing a length and a number representing the capacity. The arrays pointed to by slices, of course, are mutable, but the slice value itself is not. And so this assignment of X to Z here does not require any cloning. Now I'll compile the code and we'll go look at the output. Basically like what we saw before, there's no clone here for this assignment. And instead of creating arrays, the compiler generates these slice type functions which create values of slice types. If we run this code, what it prints out to console are objects representing the slice values that we created. And the slice object has an array property pointed to some underlying array, a capacity value, a length property, just like in Go. Except the new thing here is there's an offset value. Because in Go, you can have a pointer to a location within the middle of an array. But you can't do that in JavaScript. If you have a pointer to array, you have a pointer to the start of the array. And so this offset value is used to logically index into some middle part of the array rather than the start. There's also, again, this val property, which is a recursive reference to the slice object itself. I don't know what business it serves, but it's there again. I'd be kind of interested to hear an explanation of why the val property is there, what purpose it serves. But I think we can pretty safely ignore it. Next, we have an example with a couple maps. The first to map those strings to ints assigned to a. The second to map of foo values to int, where foo again is our struct type. And we create a third map variable z, which we assign the value of a. And lastly, we'll print out abz and the value of a subscript yo. And we'll look up in a the value for the key yo. So let's compile the code, go look at the output. And note first that the assignment of a to z, because maps are always passed and assigned by reference. There's no clone here. Z and a are pointing to the very same map object. And the maps are actually created with this make map function. There's some funny business that'll make a little more sense when we look at the output in the console. And down in the console, we print out the values of a, b, and z. But notice that when we look at the key yo in the a map, it's this complex expression. Because in the underlying object in the JavaScript side, when we look up for key matching the string yo, if it's not there, we don't want to get back undefined. We want this expression and go is supposed to return the default value for the value type of the map. And so this is a map of strings to ints and the default value for int is zero. So in the event there is no string key yo, we want to get back zero, which is what you see here in this conditional expression. So looking at this in the browser, I'll refresh the page and it spits out our objects. What do they look like? Well, it's a regular JavaScript object where the properties notice our strings, but they've tacked a dollar sign onto the front. And then the value of the property is itself another object with k and v for key and value. So every key value pair is stored as its own object within the object representing the map. The second object here, which I recall is a map of foos to ints. It only had the one entry. And strangely, because our foo type was just a single int value. Strangely, the single property has key four. And the value for key four has two properties k and v. And k itself, its value is an object representing the foo value. I think what's going on here, and I should test this and demonstrate it with another example, but I'm not going to bother. I think what's happening is that for our foos struct keys, it is getting a string representation, which in this case is just the value four. And that's how it determines the keys for this map object. So it looks a little strange just to see number four here. I presume if our foos struct had multiple fields and somehow all those field values would be combined to one string. And those would be the keys in this map. Now let's look at an example of GoRoutines, which is surely the trickiest thing that the Go for JS compiler implements. Because JavaScript, of course, runs in a single threaded event driven context. And so somehow in that context, Go for JS has to simulate a multi-threaded context for GoRoutines. But what we'll see in this simple example is we just have two functions, which go through loops and print out a bunch of values. In Elastic and Main, we print out Main. Now normally in Go, when you return from Main, any remaining GoRoutines are killed. Once the main GoRoutine ends, that's the end of the program. So if you want them to keep on going without terminating the program, you have to put your main GoRoutine into a loop or have a block or something. You have to somehow stop it from terminating. But the way this is going to execute in JavaScript is these Go statements are going to register these functions to execute later in events. But those queued up events are not going to be executed until our Main has totally finished running. So when we compile and run the program, what we see is Main followed by first, first, first, first, first, first, second, second, second, second, second. And notice that the loops of printing out these values from the first GoRoutine and the second, none of it is interleaved. If you go look at the compiled code, you have this function here, which is the first GoRoutine and this function here, which is the second GoRoutine. They're both registered with the compiler's Go function. But note that nothing in this JavaScript code is going to interrupt it. When a JavaScript function runs, no other thread's going to come along and interrupt it. That's just not how JavaScript works. So in this example, our code is not in any way concurrent. Not only is all our code running in just a single thread, there's no real interleaving. It's just our Main function and then some set of events on a queue that are just executed in some order. If though now, we bring in a channel, here a channel of ints with a buffer size of zero, we'll print out the channel value just to get a sense in the console of what that object actually looks like in JavaScript terms. And we have a single function which just sits in a loop and reads from the channel, printing out the result. And from the Main GoRoutine, we're sending a bunch of values to that channel. So let's compile the code and go look at what we get. And we get a lot of weird, funny business. Because what the Go for JS compiler has to do is anytime you introduce a blocking operation, like sending or receiving from a channel or in Node.js, there are certain other kinds of IO operations you might do that also might block. All those things must be specially implemented in the compiler such that it logically splits the function into two. At any point you have a blocking operation that has to actually be split at that point into a function representing everything before it and then a second function representing everything that comes after. And as you can see, this looks really ugly in the compiled code. It's not even formatted properly. And it uses a bunch of variables with single letter names and ugly business like that. But that is what's ultimately going on here. This receive operation on the channel effectively has to logically split the Go function, which was just one function into two. So everything before it's one function, everything after it's a second. And down here you can see the send operation back in our main function, same business, the main function, everything before that point is one function, everything after is a separate function. So that's pretty frightening, but that's what the Goverges compiler has to do given the limitations of the environment. So let's actually go see this run, control R. And it's printing out all the numbers, which are being sent from the main Go routine and then received in the other Go routine. The first thing here, it's printing out our channel object, which probably resembles a slice object. It has that buffer and capacity fields. But then also closed flag and then receive queue and send queue. OK, last thing, what about interoperation with the JavaScript environment? In our Go code, we want to be able to access, say, the DOM API of the browser. Well, to do this, we import a special package, Goverges's JS library, which has not much stuff in it. I suggest you go browse the documentation. It's not all that long, but the most essential things for this package are first, there is a object type. Which is what we use in our Go code to represent values of the native JavaScript object type. Or more accurately, we use a pointer to JS object, not JS object itself. And most essential methods on a pointer to JS object are get, set, and call. For getting set, you specify a property name as a string. And get, of course, retrieves the value of that property and sets a value for that property. JS.global is a global in the JS package, which references the global object of your JavaScript environment. So for browsers, that would be the window object. And so this here effectively is equivalent of window.document, which we're signing to doc. And then the call method on a JS object, you specify as a string the name of the method you want to call on this object. And then afterwards, you provide any necessary arguments. So here, if I have this single argument, this is like calling document.getElementById with an argument of id foo. So in this case, it's like I'm calling getElementById to look up the element with id foo. And that's going to be assigned to this foo variable. And note that the compile time type returned by call is always pointer to object. Regardless of what the JavaScript method actually returns, if it returns a number or a string or whatever, in our go code, the compile time type, regardless, will always be pointer to object. And so if the underlying value of a pointer to object is actually a string or a Boolean or a number, pointer to object has a string method, which returns the value as a string, and an int method returns the value as an int, et cetera. So now let's see how this compiles. And what you should note here is that the JS package, when compiled, is treated specially by the compiler. The call method, for example, when compiled, just translates into a direct call to that method. So you don't see any dot call here or anything like that. Also notice that the arguments to call are processed through this externalized method. This will translate values of certain types, like slices and arrays and maps, so that they appear more like ordinary JavaScript arrays and objects that don't have those funny properties. Now, if you're writing go code to run on the browser, it can get quite clumsy and verbose when you use the JS package, and you're also effectively losing the benefit of static typing because you're calling dynamic language functions where it has no idea if you're passing in the right kinds of arguments. And in fact, when you use the call method, you're specifying a method name using a string and the compiler has no idea if you're referring to a method name that actually exists or not. So it's really easy for stupid typos to give you runtime errors. What you might prefer to do then is to use a wrapper for the DOM API, a wrapper that creates a go equivalent for all of the DOM types and their methods. So if you use these wrapper types and methods, in the wrapper code, they're just translated verbatim into the JS package equivalent, but you'll get the benefit of less verbosity and static type checking. So there is already a open source DOM wrapper. This is the import path. And here in the code say, we're getting the window, it returns a window object, not just a JS object. It has a document method, which returns a document object, not just a JS object. And from that, we can call get element by ID. That looks like a proper go method call. Notice that it begins with capital G and this returns an element object, which has this class method, which returns what they call token lists, which is a list of all the classes on that element and then the setString method effectively adds another class to the element, et cetera. So you can see the wrapper doesn't correspond precisely to the DOM API, but that makes sense because the wrapper has to introduce some compile time types that just, of course, don't exist in the JavaScript code. So you might prefer to use such a wrapper. I find that when I'm using go for JS for browser code, I'm doing so because my logic is gonna get quite complex and most of my logic isn't directly touching the DOM. The DOM is generally a relatively small part of my code. And so if accessing the DOM is a little verbose and not properly statically typed, it's generally not a huge deal. So in such cases like that, there's probably not much advantage to using this wrapper, but if you're gonna be touching the DOM extensively, then it can be a benefit.