1 00:00:00,300 --> 00:00:04,800 You will no doubt have used to go build, go run type tools because you've been 2 00:00:04,800 --> 00:00:08,900 writing go code but it's worth doing a little review of the layout of 3 00:00:08,900 --> 00:00:12,900 the go workspace because sometimes it can be a little bit confusing. And 4 00:00:12,900 --> 00:00:16,500 also, there are times when you really don't need to use the entire go 5 00:00:16,500 --> 00:00:17,900 workspace layout 6 00:00:18,900 --> 00:00:22,900 If we take another little program I've written here. It is very simple. 7 00:00:22,900 --> 00:00:26,700 It prints out, hello world and a couple of different ways and imports, a 8 00:00:26,700 --> 00:00:30,700 couple of modules. I've created a couple of packages one called EE Cummings, after the 9 00:00:30,700 --> 00:00:34,600 poet, who wrote everything in lower case and one called shouter which does everything in 10 00:00:34,700 --> 00:00:38,800 uppercase. And if we take a look at the shelter module, 11 00:00:38,800 --> 00:00:39,300 which is 12 00:00:40,800 --> 00:00:44,600 Here, it's very simple. It just takes a string and upper 13 00:00:44,600 --> 00:00:48,500 cases it. And if we look at the ear, Cummings module, what it 14 00:00:48,500 --> 00:00:52,900 does, is it lower case is something and then removes all the punctuation from 15 00:00:52,900 --> 00:00:56,500 it. So, very simple layout. Now, if we take a look here in 16 00:00:56,800 --> 00:00:59,200 the source code for this, 17 00:01:00,500 --> 00:01:04,700 we will find that there is a source directory and within the source 18 00:01:04,700 --> 00:01:08,800 directory I've got three directories, you Cummings program 19 00:01:08,800 --> 00:01:12,800 name and shelter and of course program name you could use whatever you want as a name for your 20 00:01:12,800 --> 00:01:16,900 program I just made it clear by saying program name and it's in that program named 21 00:01:16,900 --> 00:01:20,400 directory that there is a file which 22 00:01:20,900 --> 00:01:24,700 contains package means. So that's the that name program. They will 23 00:01:24,700 --> 00:01:28,900 be the one used for the executable for your program and the 24 00:01:28,900 --> 00:01:30,100 other files in there. 25 00:01:30,300 --> 00:01:34,900 Packages. So for example, within your Cummings there's small dog, go. And if we take a 26 00:01:34,900 --> 00:01:38,600 look at small dog go, it says e comings of the top. So that's that's 27 00:01:38,600 --> 00:01:42,400 all the things that are part of. That package are in the directory. With the same name, 28 00:01:42,400 --> 00:01:46,700 the source of all this is this 29 00:01:46,700 --> 00:01:47,900 current directory. I'm in here. 30 00:01:49,100 --> 00:01:53,900 And if we look at gopath, I've set it to be that directory 31 00:01:53,900 --> 00:01:57,800 and the go path is essentially the root of your workspace where you're 32 00:01:57,800 --> 00:02:01,700 going to be writing, go code. And it's the one thing you probably need to 33 00:02:01,700 --> 00:02:05,800 set because you need to it is used by all the go build tools to then find 34 00:02:05,800 --> 00:02:09,800 other bits of code and underneath gopath it expects to 35 00:02:09,800 --> 00:02:13,700 find a source directory and within the source directory expects to find other 36 00:02:13,700 --> 00:02:17,900 directories which are either programs you're going to build or packages. In this case we've got 37 00:02:17,900 --> 00:02:18,600 one program 38 00:02:19,000 --> 00:02:23,600 And those packages, if you think about, I'd go path, followed 39 00:02:23,600 --> 00:02:27,400 by sauce, followed by something, the 40 00:02:27,400 --> 00:02:31,800 something. Let's suppose we lists a shelter. That last part will be 41 00:02:31,800 --> 00:02:35,100 what you use when you import that particular 42 00:02:35,800 --> 00:02:39,600 package. So you I just say shouter and it knows to look in gopath Source, 43 00:02:39,600 --> 00:02:43,700 shelter. And if you have a more complex structure, obviously, you can have many slashes in 44 00:02:43,700 --> 00:02:46,700 there, multiple directories. And so we can just 45 00:02:47,500 --> 00:02:51,900 We can build this program by saying, I want you to build program name that 46 00:02:51,900 --> 00:02:55,400 it will look in Source program name. And hopefully there's a main dog go 47 00:02:55,900 --> 00:02:59,900 and it would create its created a simple program there, which I can build, so which 48 00:02:59,900 --> 00:03:03,700 runs like that. So, one of the things you're expected to do, when you write go 49 00:03:03,700 --> 00:03:07,800 code, is to write tests for your packages and I hadn't actually written 50 00:03:07,800 --> 00:03:11,900 any tests for this shelter thing. Although, it's rather simple, but it'll be good to write a 51 00:03:11,900 --> 00:03:15,900 unit test. Then we can run it. And obviously, the way in which unit test working 52 00:03:15,900 --> 00:03:17,100 go, is you have if 53 00:03:17,300 --> 00:03:21,900 I'll typically with the same name with underscore test, appended to it and that way the 54 00:03:22,100 --> 00:03:26,900 go test is able to find the tests and execute them. So, what I've done 55 00:03:26,900 --> 00:03:30,900 is, I've actually put together a little test package here, it is called shout underscore test. 56 00:03:30,900 --> 00:03:34,500 It's going to test this function. This shelter package, 57 00:03:34,500 --> 00:03:38,600 it's within the same package. And what I've done is I've written myself a little 58 00:03:38,600 --> 00:03:42,600 function which can test that shout function of 59 00:03:42,600 --> 00:03:46,900 imported the testing package and then all I'm doing is I have a test string and I'm 60 00:03:47,200 --> 00:03:51,900 Using a regular expression to look for any lowercase characters or to make sure there's nothing lower case 61 00:03:51,900 --> 00:03:55,800 left. And and I'm shouting a string and the shout is within 62 00:03:55,800 --> 00:03:59,700 the shelter package, so I don't know, chefs a sheltered or shout because I'm inside the package. 63 00:03:59,900 --> 00:04:03,800 So this should be all uppercase. And then I just use matched ring 64 00:04:03,800 --> 00:04:07,700 and if we just check that, there's a lot of different functions of the 65 00:04:07,700 --> 00:04:11,900 Radix package, some of them work on bite, slices on the work on strings. This particular 66 00:04:11,900 --> 00:04:15,800 one works on a string, so this is quite a simple one. It returns 67 00:04:15,800 --> 00:04:17,100 a Boolean if it matches. 68 00:04:17,300 --> 00:04:21,900 So in the case that we find some lower case we should say, oops, I should say 69 00:04:21,900 --> 00:04:25,800 found no case we found some lowercase and then to run that we can just 70 00:04:25,800 --> 00:04:29,800 go go test and then the name of the package and it runs it and 71 00:04:29,800 --> 00:04:33,300 luckily it all works correctly. The 72 00:04:33,300 --> 00:04:37,900 test tool will look for the test files 73 00:04:37,900 --> 00:04:41,600 within the packages that are in Go part. So you can specify 74 00:04:41,600 --> 00:04:45,800 them on the go test command line and it will then run through all of them. So, typically you'd 75 00:04:45,800 --> 00:04:47,100 have a whole load of packages here, 76 00:04:47,200 --> 00:04:51,900 Which you would run through. So that works great for simple unit test. But one of the classic 77 00:04:51,900 --> 00:04:55,800 questions is how I tested everything and the go test tool that actually 78 00:04:55,800 --> 00:04:59,700 has a - cover option, which gives you coverage information about your 79 00:04:59,700 --> 00:05:03,700 unit test. So excuse the unit test and then can tell you, whether it actually touched all of 80 00:05:03,700 --> 00:05:07,700 the functions on all the lines in your code. And just to demonstrate 81 00:05:07,700 --> 00:05:11,800 that, I'm going to leave my unit tests as it is. But I've added an extra function called shout 82 00:05:11,800 --> 00:05:15,500 really loud. And what it does. Is it shouts? And put an exclamation mark on the end to make it 83 00:05:15,900 --> 00:05:17,100 more impressive and I'm really 84 00:05:17,200 --> 00:05:21,300 As for it. Now if I then go in and I run go test - 85 00:05:21,300 --> 00:05:25,700 cover on the shelter, what is going to do is run all the unit tests and give me a report. 86 00:05:26,300 --> 00:05:30,800 So I do that. You can see only 50% of the statements have been covered. So it's showing me that 87 00:05:30,800 --> 00:05:34,700 I, you know, I've missed out some information here about this function here 88 00:05:34,700 --> 00:05:38,800 has not been tested and I should, I should write some test for it. So that coverage 89 00:05:38,800 --> 00:05:42,900 output on test is nice from a reporting perspective, but if you want, you want to dig in 90 00:05:42,900 --> 00:05:46,900 and see what has not been tested, and there are some extra ways to do that. So, 91 00:05:47,200 --> 00:05:51,900 If you look at this go test, I got here. I've got go test and I've now instead of saying just - cover, I've said 92 00:05:51,900 --> 00:05:55,600 - cover profile and given a file name. Well, that's going to do is it's going to 93 00:05:55,600 --> 00:05:59,700 write out a file containing information about the coverage. So I'm going to run 94 00:05:59,700 --> 00:06:03,900 that it's going to do the same thing in the same reporting output but I've now got a file called coverage 95 00:06:03,900 --> 00:06:07,700 dot out and I can do a couple of things with that. There's a go tool 96 00:06:08,900 --> 00:06:10,200 called cover. 97 00:06:12,100 --> 00:06:16,900 And that will if I just run it like that with - Funk passing in the name of that file, it's 98 00:06:16,900 --> 00:06:20,900 going to tell me which functions I have not got coverage for. You can see obviously that 99 00:06:20,900 --> 00:06:24,800 shout really loud as God 0% and if I wasn't obvious, I could 100 00:06:24,800 --> 00:06:28,700 dig in a lot more deeply. Now, the way to dig in deeply is to 101 00:06:28,700 --> 00:06:31,800 use - HTML. So if I change this to HTML, 102 00:06:32,800 --> 00:06:36,700 it's going to fire up my browser and it's going to color the 103 00:06:36,700 --> 00:06:40,800 Lines within that actual code, whether they were covered or not. So I can 104 00:06:40,800 --> 00:06:41,700 immediately see that 105 00:06:42,200 --> 00:06:46,400 This thing has not been executed. And for anything, where you have complex if source, 106 00:06:46,400 --> 00:06:50,900 which are the functionalities can be, extremely useful for figuring out, exactly, which part 107 00:06:50,900 --> 00:06:54,800 of the package or writing has not been covered by the tests, 108 00:06:55,200 --> 00:06:59,600 despite the fact that concurrency is incredibly easy and go and you don't really use 109 00:06:59,600 --> 00:07:03,700 mutexes or semaphores or some of the things. It's still possible to create 110 00:07:03,700 --> 00:07:07,400 data races and luckily go itself has a race 111 00:07:07,400 --> 00:07:11,500 detection mechanism which can be run if you're running into weird problems, 112 00:07:12,000 --> 00:07:16,900 Got a very simple program here which is actually the example from the golang blog that illustrates 113 00:07:16,900 --> 00:07:20,800 how this operates. So the program is is fairly simple. What it does? Is 114 00:07:20,800 --> 00:07:24,600 it it starts a timer using after Funk. So it'll call a 115 00:07:24,600 --> 00:07:28,700 function after some amount of time. Here's the function and what the 116 00:07:28,700 --> 00:07:32,400 function does is it resets the timer for sometime in the future 117 00:07:32,800 --> 00:07:36,900 after printing out, the time it is now in fact the Delta 118 00:07:36,900 --> 00:07:40,300 from when this program started and the actual time is some 119 00:07:40,300 --> 00:07:41,700 randomly generated times. 120 00:07:41,900 --> 00:07:45,600 So it just going to for about five seconds. It's going to step through random 121 00:07:45,600 --> 00:07:49,300 printing of the time, and we can run that I've been run it using 122 00:07:49,800 --> 00:07:53,800 go run like this. This is an alternative way of doing bills, right? I don't have to 123 00:07:53,800 --> 00:07:57,900 build this within the structure. This is just in the current directory. Go run will build 124 00:07:57,900 --> 00:08:01,900 it and execute in one. Go very useful for small programs and if I do 125 00:08:01,900 --> 00:08:05,700 that it's going to start printing out times up to about five 126 00:08:05,700 --> 00:08:09,900 seconds. Now occasionally this program will crash within 127 00:08:09,900 --> 00:08:11,800 with a nil pointer and it 128 00:08:11,900 --> 00:08:15,700 Be very occasionally, so it's not obvious. What's wrong with this 129 00:08:15,700 --> 00:08:19,900 particular program? It looks actually like pretty reasonable code. So, to find out what 130 00:08:19,900 --> 00:08:23,800 we can do is, we can do go, run. Now we can say - Race. You can 131 00:08:23,800 --> 00:08:27,800 also put - Race on go test. So that during the test Suite, you can look for data races 132 00:08:28,200 --> 00:08:32,900 and this will run the same program. And immediately it says, by the way, there's a data 133 00:08:32,900 --> 00:08:36,900 race going on in here. So let's just stop this and it's telling 134 00:08:36,900 --> 00:08:40,500 us that there's a go routine, go routine, number 135 00:08:40,500 --> 00:08:41,800 six, which is 136 00:08:41,900 --> 00:08:45,600 Rated this line. So just go to line 18, this line here. 137 00:08:47,000 --> 00:08:51,300 Is having a problem with a go routine at 138 00:08:51,600 --> 00:08:55,900 line 19. So what's happening is this after Funk actually starts to go 139 00:08:55,900 --> 00:08:59,900 routine and it's actually resetting this value T 140 00:09:00,500 --> 00:09:04,900 in the middle of T being used. And so the fact there's, there's a race here between these 141 00:09:04,900 --> 00:09:08,900 two different things because of the, the random amounts of time. And so this is this is a 142 00:09:08,900 --> 00:09:12,800 big problem and this would show up occasionally and it's actually 143 00:09:12,800 --> 00:09:16,400 quite difficult to diagnose there because you may not be obvious that that 144 00:09:16,600 --> 00:09:20,600 Timer is being accessed from one, go routine or another. And so the 145 00:09:20,600 --> 00:09:24,900 data race tests can detect this type of thing and other sorts of 146 00:09:24,900 --> 00:09:28,500 synchronization problems with the program. And it gives a fairly clear, output of where to look 147 00:09:28,500 --> 00:09:32,000 in your, in your program. For the error, you've generated. 148 00:09:32,000 --> 00:09:36,700 If you've written any reasonably sized program in go, then you probably have had to 149 00:09:36,700 --> 00:09:40,900 include some sort of version string and some kind of way of finding out what the version of 150 00:09:40,900 --> 00:09:44,500 the program is at that moment. And this creates a bit of a conundrum because 151 00:09:44,500 --> 00:09:46,400 often the version string might have 152 00:09:46,500 --> 00:09:50,900 Been generated from something in Gate or something external that decides on it, yet, you needed to 153 00:09:50,900 --> 00:09:54,500 be in the program and there are various ways of dealing with this problem. You 154 00:09:54,500 --> 00:09:58,600 could dynamically generate a go program, that gets compiled and that GoPro and could have the 155 00:09:58,600 --> 00:10:02,900 version number in it or you could do some hideous things in a make file was said to adjust 156 00:10:02,900 --> 00:10:06,800 things but there's actually another rather neat way, which is to actually pass 157 00:10:06,800 --> 00:10:10,500 information to the go Linker and you can actually step into a 158 00:10:10,500 --> 00:10:14,800 variable inside the go Linker directly. So I'm gonna show you how to do that. I'm going to go back to my 159 00:10:14,900 --> 00:10:16,400 little program that shouts and 160 00:10:16,500 --> 00:10:20,000 Riley says hello world and I'm going to add 161 00:10:21,300 --> 00:10:25,600 a flag to this. I'm going to say, do they want to know the version? 162 00:10:28,600 --> 00:10:30,700 so, if they ask for the version in, 163 00:10:31,700 --> 00:10:33,300 By default it won't get it. 164 00:10:35,500 --> 00:10:39,900 And then pause the flags and then if there's 165 00:10:39,900 --> 00:10:42,600 also the version, then what we'll do is we'll do this. 166 00:10:44,200 --> 00:10:47,600 This is version and let's just say it's like that 167 00:10:49,200 --> 00:10:50,700 and version is some 168 00:10:53,200 --> 00:10:55,300 Variable. And then we will exit. 169 00:10:56,900 --> 00:10:57,900 so, that should 170 00:11:02,900 --> 00:11:06,800 Build that right? 171 00:11:06,800 --> 00:11:10,900 Okay, set the version. So we'll just set this as a string here version 172 00:11:10,900 --> 00:11:12,100 equals 1.0.0. 173 00:11:14,500 --> 00:11:18,900 And build it and run it. There it is. If I say yes version. There you go. I got 174 00:11:18,900 --> 00:11:22,800 the version number. So, how do I set one 2020 from the outside the program? 175 00:11:23,200 --> 00:11:27,800 Well, there's a couple of ways to do this and obviously, I could do some said things and adjust it, 176 00:11:27,800 --> 00:11:31,400 but actually an easier way is when I'm building it is to set. 177 00:11:33,000 --> 00:11:34,100 LD Flags. 178 00:11:38,300 --> 00:11:42,500 I can go into here like this and I can say I'm going to set this 179 00:11:42,500 --> 00:11:46,500 variable sorry main dot version which is I mean package means of this is the 180 00:11:46,500 --> 00:11:49,700 version and I'm going to set it to 2.00. 181 00:11:51,200 --> 00:11:55,900 And so there's my program and now I'm to do 0 to 0 so that's actually 182 00:11:55,900 --> 00:11:59,800 very easy to build into the workflow and I was able to do that with go run and other things 183 00:11:59,800 --> 00:12:03,700 but it's very simple to build in a version number here and it could be 184 00:12:03,700 --> 00:12:07,900 something that came from get log that gives you the latest hash you're on or a version 185 00:12:07,900 --> 00:12:11,000 generated by some external tool and it requires no 186 00:12:11,700 --> 00:12:15,900 tricks and no changing to the tool is just done with LD flax and so LD 187 00:12:15,900 --> 00:12:19,600 flag actually gets passed to the go Linker and this works nicely whether you're 188 00:12:19,600 --> 00:12:20,800 using C girl. 189 00:12:21,000 --> 00:12:25,800 Or not. So there's no there's no worries about that and you can easily pass in a version number like this. You can 190 00:12:25,800 --> 00:12:29,700 change anything the format here. You notice main that's the package 191 00:12:29,700 --> 00:12:33,600 name if it were, if there was a package path, if it was food / main, you could do 192 00:12:33,600 --> 00:12:37,700 that. And then just the name of the variable. You want to change. If it's a 193 00:12:37,700 --> 00:12:39,200 string you can set it just like that.