WEBVTT

1
00:00:00.080 --> 00:00:03.520
<v Speaker 1>Welcome to the deep dive. Today. We're really getting into

2
00:00:03.560 --> 00:00:06.440
<v Speaker 1>the fundamentals of the Go programming language. We're using Go

3
00:00:06.519 --> 00:00:10.359
<v Speaker 1>fundamentals Go for guides as our source here, and our

4
00:00:10.439 --> 00:00:13.960
<v Speaker 1>mission really is to pull out the core ideas how

5
00:00:14.039 --> 00:00:18.000
<v Speaker 1>GOT structures projects, it's basic elements, how it handles dependencies,

6
00:00:18.519 --> 00:00:21.839
<v Speaker 1>basically giving you a solid understanding without feeling like you're

7
00:00:21.879 --> 00:00:23.239
<v Speaker 1>reading a textbook exactly.

8
00:00:23.440 --> 00:00:29.280
<v Speaker 2>We'll be looking at modules, packages, dependencies obviously, but also

9
00:00:29.519 --> 00:00:32.520
<v Speaker 2>the language basics, numbers, strings.

10
00:00:32.560 --> 00:00:34.840
<v Speaker 1>Booleans, variables, constants.

11
00:00:34.520 --> 00:00:37.679
<v Speaker 2>Variables, constants, how to format things, and then collections like

12
00:00:37.759 --> 00:00:43.679
<v Speaker 2>arrays and slices, maps, control structures, functions, interfaces.

13
00:00:43.240 --> 00:00:45.960
<v Speaker 1>Error handling too, right, yeah, and concurrency it's a big one.

14
00:00:45.960 --> 00:00:50.640
<v Speaker 2>And go oh yeah, definitely, guroteines, channels, context synchronization, primitives,

15
00:00:50.759 --> 00:00:53.399
<v Speaker 2>even touching on the filesystem stuff. It's quite a bit,

16
00:00:53.399 --> 00:00:54.159
<v Speaker 2>but we'll break it down.

17
00:00:54.200 --> 00:00:57.119
<v Speaker 1>That's good. So for you listening, maybe you're prepping for

18
00:00:57.159 --> 00:00:59.640
<v Speaker 1>a tech chat, or just want to brush up on Go,

19
00:00:59.840 --> 00:01:02.479
<v Speaker 1>or you're just curious, this deep dive should give you

20
00:01:02.560 --> 00:01:05.680
<v Speaker 1>a structured, insightful look. Hopefully some moha moments along the way,

21
00:01:05.959 --> 00:01:08.680
<v Speaker 1>let's hope. So okay, let's start unpacking it at the

22
00:01:08.799 --> 00:01:11.920
<v Speaker 1>very foundation. How does Go organized code.

23
00:01:11.599 --> 00:01:15.079
<v Speaker 2>Right, It really starts with modules. Think of the Go

24
00:01:15.159 --> 00:01:19.599
<v Speaker 2>dot mod file. It's goes way of promising reproducible builds.

25
00:01:19.599 --> 00:01:21.280
<v Speaker 1>Reproducible builds meaning naing.

26
00:01:21.120 --> 00:01:23.159
<v Speaker 2>Everyone on the team or you know, your build server

27
00:01:23.480 --> 00:01:26.680
<v Speaker 2>uses the exact same versions of all the libraries. The

28
00:01:26.719 --> 00:01:29.079
<v Speaker 2>Go dot mod file names your project, says what Go

29
00:01:29.239 --> 00:01:31.560
<v Speaker 2>version it needs. Like the examples we looked at use

30
00:01:31.760 --> 00:01:32.719
<v Speaker 2>Go one point nineteen.

31
00:01:32.760 --> 00:01:35.599
<v Speaker 1>Okay, so godat mod is the project manifest and inside

32
00:01:35.599 --> 00:01:37.280
<v Speaker 1>modules we have packages exactly.

33
00:01:37.400 --> 00:01:41.519
<v Speaker 2>Packages are the fundamental unit of importable code. The key

34
00:01:41.560 --> 00:01:45.400
<v Speaker 2>thing with naming them. Keep it short, simple, easy to recognize.

35
00:01:44.840 --> 00:01:47.400
<v Speaker 1>Like squile L or HDPP precisely.

36
00:01:47.040 --> 00:01:50.439
<v Speaker 2>Much better than say structured query language. Imagine typing that

37
00:01:50.480 --> 00:01:51.599
<v Speaker 2>out every time you use it.

38
00:01:51.680 --> 00:01:54.040
<v Speaker 1>Yeah, that would get old fast. Yeah. What if you

39
00:01:54.079 --> 00:01:57.120
<v Speaker 1>have two packages with the same name, like from different places.

40
00:01:57.159 --> 00:02:00.599
<v Speaker 2>Ah, good question. That's where import aliasing comes in. If

41
00:02:00.640 --> 00:02:03.719
<v Speaker 2>you import say demo fubar and maybe another place bar,

42
00:02:03.799 --> 00:02:06.680
<v Speaker 2>you can give one an alias like import pub demo fubar.

43
00:02:06.879 --> 00:02:08.879
<v Speaker 1>Oh I see, so you'd use pub dot function name

44
00:02:08.960 --> 00:02:11.520
<v Speaker 1>for one and maybe just bar another function for the

45
00:02:11.560 --> 00:02:12.319
<v Speaker 1>other exactly.

46
00:02:12.360 --> 00:02:14.800
<v Speaker 2>It avoids those name clashes and keeps things clear.

47
00:02:14.919 --> 00:02:18.840
<v Speaker 1>Okay, so go dot mod tracks external stuff packages organize

48
00:02:18.840 --> 00:02:21.879
<v Speaker 1>your internal code. How do you actually get those external libraries?

49
00:02:21.919 --> 00:02:24.039
<v Speaker 2>That's the go get command. So if you need let's

50
00:02:24.080 --> 00:02:27.159
<v Speaker 2>say that fleck library for working with words, Yeah, you

51
00:02:27.319 --> 00:02:31.319
<v Speaker 2>just run Go get GitHub dot Com forward Slash, go Buffalo, flecked,

52
00:02:31.840 --> 00:02:36.240
<v Speaker 2>Go fetches. It updates your Go dot mod with the dependency.

53
00:02:35.599 --> 00:02:37.800
<v Speaker 1>In the version, and it also creates that go dot

54
00:02:37.800 --> 00:02:39.919
<v Speaker 1>sum file. Right. What's that for again?

55
00:02:40.120 --> 00:02:43.120
<v Speaker 2>Right, the go dot sum It's basically a lockfile with

56
00:02:43.199 --> 00:02:46.840
<v Speaker 2>cryptographic hashes like digital fingerprints for your dependencies. It ensures

57
00:02:46.919 --> 00:02:49.319
<v Speaker 2>the code you downloaded is exactly what it's supposed to be,

58
00:02:49.479 --> 00:02:53.240
<v Speaker 2>hasn't been tampered with. Consistency and security, got.

59
00:02:53.039 --> 00:02:56.560
<v Speaker 1>It like a security checkpoint and versions. How does go

60
00:02:56.719 --> 00:02:57.800
<v Speaker 1>handle updates?

61
00:02:57.960 --> 00:03:01.240
<v Speaker 2>It uses semantic versioning, you know, the major dot minor

62
00:03:01.319 --> 00:03:02.599
<v Speaker 2>dot patch system.

63
00:03:02.360 --> 00:03:05.719
<v Speaker 1>Where major means breaking changes, minor means new features, Patch

64
00:03:05.759 --> 00:03:07.319
<v Speaker 1>means fixes pretty much.

65
00:03:07.400 --> 00:03:10.319
<v Speaker 2>Yeah, Go get usually updates you to the latest minor

66
00:03:10.439 --> 00:03:13.719
<v Speaker 2>or patch versions safely. One thing I'll watch out for, though,

67
00:03:13.800 --> 00:03:15.599
<v Speaker 2>is sychnical imports.

68
00:03:15.240 --> 00:03:17.680
<v Speaker 1>Where package A needs b and B needs.

69
00:03:17.479 --> 00:03:20.800
<v Speaker 2>A Yeah, that can get messy fast, generally best to

70
00:03:20.840 --> 00:03:21.199
<v Speaker 2>avoid that.

71
00:03:21.240 --> 00:03:25.360
<v Speaker 1>Structure makes sense, Okay, modules, packages, dependencies clear. Now let's

72
00:03:25.360 --> 00:03:27.520
<v Speaker 1>dive into the language itself, the basics.

73
00:03:27.639 --> 00:03:31.759
<v Speaker 2>Okay, So GO is statically typed.

74
00:03:31.639 --> 00:03:34.479
<v Speaker 1>Meaning it checks types before you run the code.

75
00:03:34.280 --> 00:03:37.000
<v Speaker 2>Exactly, catches lots of errors early, like trying to add

76
00:03:37.039 --> 00:03:40.159
<v Speaker 2>text to a number. It's also compiled straight to machine code,

77
00:03:40.240 --> 00:03:42.759
<v Speaker 2>so it's fast, and it has garbage collection.

78
00:03:42.919 --> 00:03:44.599
<v Speaker 1>The automatic memory cleanup.

79
00:03:44.280 --> 00:03:47.039
<v Speaker 2>Crew that's the one takes a lot of manual memory

80
00:03:47.080 --> 00:03:48.719
<v Speaker 2>management burden off the developer.

81
00:03:49.159 --> 00:03:52.159
<v Speaker 1>Big plus definitely sounds helpful. Yeah, okay, let's talk numbers.

82
00:03:52.159 --> 00:03:52.879
<v Speaker 1>What are the options?

83
00:03:53.039 --> 00:03:55.879
<v Speaker 2>GO gives you a fair range. You've got integers signed

84
00:03:56.000 --> 00:03:58.479
<v Speaker 2>in tate through in sixty four and unsigned and dad

85
00:03:58.680 --> 00:04:01.080
<v Speaker 2>on sixty four plus t us the general int and

86
00:04:01.400 --> 00:04:04.479
<v Speaker 2>that depend on your system architecture, and for decimals float

87
00:04:04.479 --> 00:04:07.479
<v Speaker 2>thirty two and float sixty four. Usually float sixty four

88
00:04:07.520 --> 00:04:09.919
<v Speaker 2>is the default choice unless you have specific needs.

89
00:04:10.159 --> 00:04:12.479
<v Speaker 1>That's a lot of integer types. How do you choose?

90
00:04:12.680 --> 00:04:16.000
<v Speaker 2>Often you can just start with int for whole numbers

91
00:04:16.160 --> 00:04:19.279
<v Speaker 2>and float sixty four for decimals. The specific sizes like

92
00:04:19.319 --> 00:04:22.079
<v Speaker 2>in eight become important when you're really optimizing for memory

93
00:04:22.240 --> 00:04:25.160
<v Speaker 2>or you know, dealing with specific hardware interfaces.

94
00:04:25.319 --> 00:04:27.800
<v Speaker 1>Okay, what about putting two big a number into a

95
00:04:27.839 --> 00:04:30.759
<v Speaker 1>small type overflow right overflow?

96
00:04:31.000 --> 00:04:33.759
<v Speaker 2>The compiler might catch it if you try to assign

97
00:04:33.800 --> 00:04:37.079
<v Speaker 2>a value that's obviously too big, like varx once equals

98
00:04:37.079 --> 00:04:38.879
<v Speaker 2>three hundred, that won't compile.

99
00:04:39.000 --> 00:04:40.519
<v Speaker 1>But what about during calculations.

100
00:04:40.600 --> 00:04:43.240
<v Speaker 2>Ah, that's different. If you add say one to a

101
00:04:43.279 --> 00:04:45.879
<v Speaker 2>one eight that's already two fifty five, it doesn't crash.

102
00:04:45.959 --> 00:04:48.240
<v Speaker 1>It wraps around, wraps around two zero yep.

103
00:04:48.040 --> 00:04:51.720
<v Speaker 2>Wraps around to zero. Go doesn't automatically saturate or stop

104
00:04:51.759 --> 00:04:53.160
<v Speaker 2>the calculation by default.

105
00:04:53.519 --> 00:04:56.600
<v Speaker 1>Something to be aware of, good to know, subtle. Okay,

106
00:04:56.639 --> 00:04:58.519
<v Speaker 1>what about text strings In GO?

107
00:04:59.000 --> 00:05:01.399
<v Speaker 2>Strings are pretty straight forward. You've got your standard double

108
00:05:01.480 --> 00:05:04.879
<v Speaker 2>quoted strings. They interpret escape sequences like in for new.

109
00:05:04.759 --> 00:05:07.040
<v Speaker 1>Line t for tabs, standard stuff.

110
00:05:06.720 --> 00:05:09.879
<v Speaker 2>And then you have raw string literals using backticks inside

111
00:05:09.879 --> 00:05:12.759
<v Speaker 2>these backslashes or just backslashes, no special meaning.

112
00:05:13.120 --> 00:05:13.959
<v Speaker 1>That sounds useful.

113
00:05:14.120 --> 00:05:17.480
<v Speaker 2>It's great for multiline strings, like embedding JSON or writing

114
00:05:17.560 --> 00:05:21.839
<v Speaker 2>regular expressions where you'd otherwise be escaping constantly. And GO

115
00:05:22.040 --> 00:05:25.040
<v Speaker 2>handles UTF eight out of the box, so complex characters

116
00:05:25.079 --> 00:05:26.120
<v Speaker 2>different languages.

117
00:05:25.839 --> 00:05:27.600
<v Speaker 1>Usually just works and what's a roun?

118
00:05:28.120 --> 00:05:30.600
<v Speaker 2>A roune is basically an alias for N thirty two.

119
00:05:30.879 --> 00:05:33.600
<v Speaker 2>It represents a single Unicode code point, which might be

120
00:05:33.639 --> 00:05:35.079
<v Speaker 2>one or more bites in UTF E.

121
00:05:35.240 --> 00:05:38.720
<v Speaker 1>Okay, so strings cover text? Well? Yeah, what about simple

122
00:05:38.800 --> 00:05:39.560
<v Speaker 1>true or false?

123
00:05:39.959 --> 00:05:43.360
<v Speaker 2>That's the bool type values are just true or false

124
00:05:43.680 --> 00:05:45.720
<v Speaker 2>essential for conditions obviously.

125
00:05:45.399 --> 00:05:48.480
<v Speaker 1>Right, numbers, text booleans. Yeah, how do we actually hold

126
00:05:48.480 --> 00:05:49.600
<v Speaker 1>onto these values? Variable?

127
00:05:49.720 --> 00:05:52.879
<v Speaker 2>Yep, Variables You declare them with var than the name

128
00:05:52.959 --> 00:05:54.920
<v Speaker 2>than the type like var count int.

129
00:05:54.800 --> 00:05:57.040
<v Speaker 1>You assign with what If you declare but don't a sign,

130
00:05:57.120 --> 00:05:57.399
<v Speaker 1>then it.

131
00:05:57.360 --> 00:05:59.879
<v Speaker 2>Gets the zero value for its type zero for numbers,

132
00:06:00.000 --> 00:06:04.720
<v Speaker 2>empty strength for strings, false for bulls, and nil for pointers, slices, maps, interfaces,

133
00:06:04.720 --> 00:06:05.160
<v Speaker 2>et cetera.

134
00:06:05.439 --> 00:06:08.240
<v Speaker 1>Mil Okay, is there a shorter way to declare? Yes?

135
00:06:08.639 --> 00:06:13.079
<v Speaker 2>The short variable declaration name value. This declares and initializes

136
00:06:13.120 --> 00:06:15.800
<v Speaker 2>in one go and go infers the type from the value.

137
00:06:16.040 --> 00:06:18.600
<v Speaker 1>Very common, ah, the amperator got it?

138
00:06:18.839 --> 00:06:22.560
<v Speaker 2>And naming rules start with a letter or underscore can

139
00:06:22.560 --> 00:06:27.360
<v Speaker 2>contain letters, numbers, underscores, case sensitive, can't be a keyword

140
00:06:27.439 --> 00:06:30.800
<v Speaker 2>like funk or if and go style prefers short names

141
00:06:31.240 --> 00:06:34.360
<v Speaker 2>often yes, especially for variables with a very limited scope

142
00:06:34.399 --> 00:06:38.399
<v Speaker 2>like loop counters Terseness is common, but clarity still matters,

143
00:06:38.439 --> 00:06:39.360
<v Speaker 2>of course makes sense.

144
00:06:39.519 --> 00:06:41.000
<v Speaker 1>And constants, how are they different?

145
00:06:41.120 --> 00:06:44.439
<v Speaker 2>Declared with const The key thing is their value cannot

146
00:06:44.439 --> 00:06:47.920
<v Speaker 2>be changed after declaration. They're fixed. They can be typed

147
00:06:48.040 --> 00:06:50.879
<v Speaker 2>or untyped. Untyped constants are a bit more flexible.

148
00:06:50.959 --> 00:06:54.480
<v Speaker 1>Okay, var for changeable const for fixed. Now, how do

149
00:06:54.519 --> 00:06:57.040
<v Speaker 1>we display these values? Formatting?

150
00:06:57.120 --> 00:06:59.680
<v Speaker 2>That's where the FMT package comes in. It's your standard

151
00:06:59.759 --> 00:07:00.959
<v Speaker 2>in output.

152
00:07:00.600 --> 00:07:03.920
<v Speaker 1>Toolkit FMT dot pron FMT dot print of those ones.

153
00:07:03.759 --> 00:07:06.920
<v Speaker 2>Exactly, printlin prints things with spaces in between, and adds

154
00:07:06.920 --> 00:07:09.680
<v Speaker 2>a newline. Print for formatted output using.

155
00:07:09.519 --> 00:07:12.120
<v Speaker 1>Verbs verbs like percent or percent right.

156
00:07:12.000 --> 00:07:14.560
<v Speaker 2>Percent is the default value. Format prients two shows the

157
00:07:14.560 --> 00:07:18.120
<v Speaker 2>type percent for decimal integers, percents for strings, percent reported strings,

158
00:07:18.120 --> 00:07:21.480
<v Speaker 2>percent for floats, lots of options sprintoff works like print,

159
00:07:21.519 --> 00:07:23.839
<v Speaker 2>but returns the formatted string instead of printing.

160
00:07:23.639 --> 00:07:26.399
<v Speaker 1>It useful and you can control padding and stuff.

161
00:07:26.240 --> 00:07:31.120
<v Speaker 2>Yep padding integers, printing signs showing base prefixes for binary pers,

162
00:07:31.240 --> 00:07:35.240
<v Speaker 2>octal perso x, percentx escape sequences like N and T

163
00:07:35.560 --> 00:07:39.680
<v Speaker 2>work in strings too. FMT is pretty powerful for basic formatting.

164
00:07:40.079 --> 00:07:43.199
<v Speaker 1>Cool. Okay, basic types and printing cover. Let's move on

165
00:07:43.199 --> 00:07:45.519
<v Speaker 1>to collections, arrays, and slices.

166
00:07:45.680 --> 00:07:48.560
<v Speaker 2>Right, So, rais and GO have a fixed size. You

167
00:07:48.560 --> 00:07:51.360
<v Speaker 2>declare an array, say varnums five int, and it always

168
00:07:51.360 --> 00:07:53.720
<v Speaker 2>has five integers. Can't change that size later.

169
00:07:54.040 --> 00:07:55.959
<v Speaker 1>And all elements must be the same time correct.

170
00:07:55.959 --> 00:07:58.839
<v Speaker 2>If you don't initialize it, elements get the zero value.

171
00:07:59.000 --> 00:08:01.720
<v Speaker 2>The compiler also helps prevent you from accessing an index

172
00:08:01.720 --> 00:08:06.120
<v Speaker 2>that's out of bounds. Importantly, arrays are value types value.

173
00:08:05.759 --> 00:08:07.839
<v Speaker 1>Types, meaning if you assign one array to another, it

174
00:08:07.879 --> 00:08:09.160
<v Speaker 1>copies everything exactly.

175
00:08:09.160 --> 00:08:10.639
<v Speaker 2>You get a full independent copy.

176
00:08:10.759 --> 00:08:14.240
<v Speaker 1>Okay, so fixed size value types. That sounds limiting sometimes,

177
00:08:14.240 --> 00:08:15.079
<v Speaker 1>what about slices.

178
00:08:15.160 --> 00:08:18.319
<v Speaker 2>That's where slices come in. They are dynamically sized flexible

179
00:08:18.399 --> 00:08:21.399
<v Speaker 2>views into an underlying array, much more common in GO

180
00:08:21.560 --> 00:08:24.759
<v Speaker 2>code than raw arrays. The view into an array, yeah,

181
00:08:25.199 --> 00:08:28.319
<v Speaker 2>a slice has a pointer to the underlying array, a

182
00:08:28.439 --> 00:08:32.000
<v Speaker 2>length how many elements it currently holds, and a capacity

183
00:08:32.440 --> 00:08:35.559
<v Speaker 2>how large the underlying array segment is. You can create

184
00:08:35.600 --> 00:08:38.440
<v Speaker 2>them with it literal like in one, two, three, or

185
00:08:38.559 --> 00:08:42.480
<v Speaker 2>using the make function. Make yent five creates a slice

186
00:08:42.480 --> 00:08:47.120
<v Speaker 2>of five integers initialized to zero. Make zero ten creates

187
00:08:47.159 --> 00:08:49.960
<v Speaker 2>an empty slice, but with an underlying array capacity of

188
00:08:50.000 --> 00:08:50.960
<v Speaker 2>ten ready to.

189
00:08:50.919 --> 00:08:54.279
<v Speaker 1>Grow, and slices are reference types unlike arrays.

190
00:08:54.320 --> 00:08:58.519
<v Speaker 2>Correct assigning a slice just copies the slice header pointer, length, capacity,

191
00:08:58.879 --> 00:09:01.159
<v Speaker 2>not the underlying beta. Both slices will point to the

192
00:09:01.200 --> 00:09:01.720
<v Speaker 2>same data.

193
00:09:01.759 --> 00:09:04.759
<v Speaker 1>Ah, so changes through one slice are visible through the other.

194
00:09:04.639 --> 00:09:06.320
<v Speaker 2>If they point to the same underlying elements.

195
00:09:06.399 --> 00:09:08.519
<v Speaker 1>Yes, how do you add elements to a slice? It's

196
00:09:08.519 --> 00:09:09.279
<v Speaker 1>it's their dynamic.

197
00:09:09.399 --> 00:09:11.919
<v Speaker 2>You use the built in a pen function. My slice,

198
00:09:11.919 --> 00:09:14.679
<v Speaker 2>a pend, my slice new value. If there's enough capacity

199
00:09:14.679 --> 00:09:16.799
<v Speaker 2>in the underlying array, it just adds the element and

200
00:09:16.799 --> 00:09:17.639
<v Speaker 2>increases the length.

201
00:09:17.679 --> 00:09:19.679
<v Speaker 1>And if there isn't enough capacity.

202
00:09:19.440 --> 00:09:23.320
<v Speaker 2>Then a pen allocates a new, larger underlying array, copies

203
00:09:23.360 --> 00:09:26.480
<v Speaker 2>the old data over adds the new element, and returns

204
00:09:26.480 --> 00:09:28.879
<v Speaker 2>a slice pointing to this new array. That's why you

205
00:09:28.879 --> 00:09:30.720
<v Speaker 2>always assign the result of a pend back to your

206
00:09:30.759 --> 00:09:31.440
<v Speaker 2>slice variable.

207
00:09:31.480 --> 00:09:33.840
<v Speaker 1>Got it? You can depend a whole other slice too, right, yep?

208
00:09:33.960 --> 00:09:37.120
<v Speaker 2>Using the operator a pend slice one, slice two. And

209
00:09:37.159 --> 00:09:40.759
<v Speaker 2>there's a copy function to explicitly copy elements between slices.

210
00:09:40.799 --> 00:09:44.120
<v Speaker 1>Okay, fixed arrays flexible slices, how do we loop through them?

211
00:09:44.159 --> 00:09:46.840
<v Speaker 2>The four loop is goes only looping construct you can

212
00:09:46.919 --> 00:09:50.039
<v Speaker 2>use the classic C style for with an index for

213
00:09:50.159 --> 00:09:53.399
<v Speaker 2>i or o omeaning my slice i plus plus slice

214
00:09:53.559 --> 00:09:57.279
<v Speaker 2>familiar but more idiomatic, and go is using with a

215
00:09:57.399 --> 00:10:01.000
<v Speaker 2>range keyword for index value range my flesh. It iterates

216
00:10:01.039 --> 00:10:03.440
<v Speaker 2>over the collection, giving you the index and the value

217
00:10:03.440 --> 00:10:04.080
<v Speaker 2>at each step.

218
00:10:04.279 --> 00:10:06.639
<v Speaker 1>Range works on a rais and slices what else.

219
00:10:06.480 --> 00:10:10.200
<v Speaker 2>Maps strings gives indexed and run and channels only built

220
00:10:10.240 --> 00:10:14.159
<v Speaker 2>in collection types. Mostly inside loops, you can use continue

221
00:10:14.200 --> 00:10:16.759
<v Speaker 2>to skip to the next iteration or break to exit

222
00:10:16.799 --> 00:10:17.919
<v Speaker 2>the loop entirely.

223
00:10:17.759 --> 00:10:21.480
<v Speaker 1>Standard loop control. Okay, foreign range. Let's talk about maps

224
00:10:21.559 --> 00:10:22.759
<v Speaker 1>key value pairs.

225
00:10:22.720 --> 00:10:26.080
<v Speaker 2>Exactly like dictionaries or hash maps and other languages rate

226
00:10:26.120 --> 00:10:29.159
<v Speaker 2>for lookups, you declare them using make map key type,

227
00:10:29.240 --> 00:10:32.399
<v Speaker 2>value type, or a map literal like map string at one, one,

228
00:10:32.440 --> 00:10:32.840
<v Speaker 2>two to two.

229
00:10:33.159 --> 00:10:34.919
<v Speaker 1>How do you add or get values.

230
00:10:34.960 --> 00:10:38.159
<v Speaker 2>Using square brackets with the key my map key value

231
00:10:38.200 --> 00:10:40.240
<v Speaker 2>to set and vowel my map key to.

232
00:10:40.200 --> 00:10:41.799
<v Speaker 1>Get What if the key isn't there when you try

233
00:10:41.840 --> 00:10:42.240
<v Speaker 1>to get it.

234
00:10:42.200 --> 00:10:44.440
<v Speaker 2>You get the zero value for the value type e g.

235
00:10:44.679 --> 00:10:47.600
<v Speaker 2>Zero for end for string. But there's a better way

236
00:10:47.600 --> 00:10:52.240
<v Speaker 2>to check if it exists. The calm op idiom value okay,

237
00:10:52.279 --> 00:10:55.840
<v Speaker 2>my map key here okay will be boolean true if

238
00:10:55.840 --> 00:10:59.279
<v Speaker 2>the key existed false. Otherwise value holds the actual value

239
00:10:59.320 --> 00:11:02.000
<v Speaker 2>if okay is true, or the zero value if false.

240
00:11:02.360 --> 00:11:05.399
<v Speaker 2>Prevents confusion between a stored zero value and a missing key.

241
00:11:05.559 --> 00:11:07.840
<v Speaker 1>Ah, that's neat. Do maps have a fixed size?

242
00:11:08.080 --> 00:11:10.919
<v Speaker 2>No, they grow dynamically as you add more entries. Practically

243
00:11:11.039 --> 00:11:13.519
<v Speaker 2>unlimited really just limited by memory. Like slices.

244
00:11:13.559 --> 00:11:15.600
<v Speaker 1>There are reference types, and the order you get things

245
00:11:15.600 --> 00:11:17.639
<v Speaker 1>back when iterating isn't guaranteed correct.

246
00:11:17.720 --> 00:11:20.799
<v Speaker 2>Iteration order over a map is intentionally randomized and go.

247
00:11:21.080 --> 00:11:22.639
<v Speaker 2>Don't rely on it got.

248
00:11:22.399 --> 00:11:26.200
<v Speaker 1>It maps for lookups, no guaranteed order. How about making

249
00:11:26.240 --> 00:11:27.840
<v Speaker 1>decisions if statements.

250
00:11:27.799 --> 00:11:31.320
<v Speaker 2>Yip standard to if lcfls. One neat GO feature is

251
00:11:31.320 --> 00:11:33.759
<v Speaker 2>that you can declare a variable scope just to the

252
00:11:33.840 --> 00:11:38.240
<v Speaker 2>if statement itself. If value okay, my map key okay,

253
00:11:38.519 --> 00:11:41.039
<v Speaker 2>value and okay only exist inside the if in any

254
00:11:41.039 --> 00:11:41.639
<v Speaker 2>else blocks.

255
00:11:41.720 --> 00:11:44.519
<v Speaker 1>Oh that's tidy, keeps the scope tight. Yeah. What about switch?

256
00:11:44.799 --> 00:11:46.879
<v Speaker 2>Switch is powerful and go. You can switch on a

257
00:11:46.960 --> 00:11:49.799
<v Speaker 2>value and then have different case blocks. Unlike see your Java,

258
00:11:49.840 --> 00:11:52.799
<v Speaker 2>there's no automatic fall through. A matched case executes and

259
00:11:52.840 --> 00:11:53.720
<v Speaker 2>then the switch is done.

260
00:11:53.759 --> 00:11:55.639
<v Speaker 1>No need for break everywhere exactly.

261
00:11:56.039 --> 00:11:57.840
<v Speaker 2>If you want fall through, you have to use the

262
00:11:57.840 --> 00:12:01.159
<v Speaker 2>fall through keyword explicitly. You can lists multiple values in

263
00:12:01.159 --> 00:12:03.600
<v Speaker 2>a single case, and there's a default case. You can

264
00:12:03.600 --> 00:12:06.159
<v Speaker 2>even use switch without an expression, making each case just

265
00:12:06.240 --> 00:12:09.279
<v Speaker 2>a boolean condition switch case by zero, case by.

266
00:12:09.279 --> 00:12:13.120
<v Speaker 1>Zero like a cleaner if lsif chain nice. Let's package

267
00:12:13.159 --> 00:12:15.440
<v Speaker 1>up reusable code functions.

268
00:12:15.120 --> 00:12:18.679
<v Speaker 2>Right define with the funk keyword. Function function name r

269
00:12:18.840 --> 00:12:21.799
<v Speaker 2>one type one rchqwo type two return type. The main

270
00:12:21.799 --> 00:12:23.960
<v Speaker 2>function in the main package is the entry point for

271
00:12:24.000 --> 00:12:25.120
<v Speaker 2>executable programs.

272
00:12:25.320 --> 00:12:27.440
<v Speaker 1>You have to declare the type for every argument.

273
00:12:27.600 --> 00:12:32.720
<v Speaker 2>Yes always funk ad a in b nt in return

274
00:12:32.799 --> 00:12:36.559
<v Speaker 2>a plus b. You can group types if consecutive ARBs

275
00:12:36.559 --> 00:12:39.960
<v Speaker 2>have the same type funk ad a b n t in,

276
00:12:40.000 --> 00:12:43.440
<v Speaker 2>and return values can return zero or more values. Just

277
00:12:43.480 --> 00:12:46.679
<v Speaker 2>list the return types after the arguments. Funk divide ab

278
00:12:46.879 --> 00:12:50.080
<v Speaker 2>float sixty four, float sixty four error. Returning an error

279
00:12:50.120 --> 00:12:52.720
<v Speaker 2>as the last value is the standard go away to

280
00:12:52.840 --> 00:12:53.679
<v Speaker 2>signal failure.

281
00:12:53.840 --> 00:12:55.559
<v Speaker 1>Multiple return values are common, then.

282
00:12:55.639 --> 00:12:58.480
<v Speaker 2>Very common, especially for the value and error pattern. You

283
00:12:58.480 --> 00:13:01.679
<v Speaker 2>can also name the return values funk split some int

284
00:13:02.039 --> 00:13:04.720
<v Speaker 2>x ynt. They act like variables declared at the start

285
00:13:04.759 --> 00:13:07.840
<v Speaker 2>of the function. If a function returns values, the caller

286
00:13:07.879 --> 00:13:10.679
<v Speaker 2>has to handle or explicitly ignore them using funk.

287
00:13:10.840 --> 00:13:14.200
<v Speaker 1>Okay, what if a function needs to accept, say any

288
00:13:14.279 --> 00:13:15.159
<v Speaker 1>number of arguments.

289
00:13:15.200 --> 00:13:18.039
<v Speaker 2>That's very atic. Arguments use before the type of the

290
00:13:18.120 --> 00:13:22.120
<v Speaker 2>last parameter funks, numbs, dot nt intinct. Inside the function,

291
00:13:22.279 --> 00:13:24.559
<v Speaker 2>numbs is treated as a slice event, so you could.

292
00:13:24.360 --> 00:13:26.919
<v Speaker 1>Call some one to two or some one two.

293
00:13:26.799 --> 00:13:30.320
<v Speaker 2>Three four exactly. Very flexible for things like logging functions

294
00:13:30.440 --> 00:13:31.879
<v Speaker 2>or database query builders.

295
00:13:32.000 --> 00:13:34.320
<v Speaker 1>Cool. Now, what about defer That seems unique to.

296
00:13:34.279 --> 00:13:39.720
<v Speaker 2>Go It is pretty distinctive. Differ schedules a function call

297
00:13:39.759 --> 00:13:43.399
<v Speaker 2>to be executed just before the surrounding function.

298
00:13:43.200 --> 00:13:44.679
<v Speaker 1>Returns, before it returns like at.

299
00:13:44.559 --> 00:13:48.240
<v Speaker 2>The very end yep whether the function returns normally or panics.

300
00:13:48.480 --> 00:13:52.399
<v Speaker 2>The deferred calls run. If you have multiple defers, they

301
00:13:52.440 --> 00:13:56.480
<v Speaker 2>execute in last in first out laf order.

302
00:13:56.639 --> 00:13:59.279
<v Speaker 1>I have a FILT, so the last one deferred runs first.

303
00:13:59.440 --> 00:14:02.559
<v Speaker 2>Correct. The most common use is resource cleanup, like open

304
00:14:02.600 --> 00:14:06.840
<v Speaker 2>a file, then immediately defer file close. Guarantees it gets closed.

305
00:14:06.559 --> 00:14:08.039
<v Speaker 1>Even if there's an error later in the function.

306
00:14:08.279 --> 00:14:13.000
<v Speaker 2>Exactly. It simplifies cleanup logic immensely. One key point the

307
00:14:13.200 --> 00:14:16.080
<v Speaker 2>arguments to the deferred function are evaluated when the defer

308
00:14:16.200 --> 00:14:19.399
<v Speaker 2>statement is executed, not when the call actually happens.

309
00:14:19.480 --> 00:14:22.279
<v Speaker 1>Ah. Okay, So if you defer function using a variable,

310
00:14:22.399 --> 00:14:24.799
<v Speaker 1>it uses the variable's value at that moment.

311
00:14:24.679 --> 00:14:26.840
<v Speaker 2>Right, Something to keep in mind, especially with loops and

312
00:14:26.919 --> 00:14:27.960
<v Speaker 2>anonymous functions.

313
00:14:28.000 --> 00:14:30.840
<v Speaker 1>Got it defer for guaranteed cleanup? What about the innit function?

314
00:14:31.120 --> 00:14:34.360
<v Speaker 2>A knit is special. It runs automatically when its package

315
00:14:34.399 --> 00:14:37.080
<v Speaker 2>is initialized before main runs. You don't call it yourself?

316
00:14:37.120 --> 00:14:37.960
<v Speaker 1>When would you use it?

317
00:14:38.159 --> 00:14:41.080
<v Speaker 2>Usually for package levels setup you can have multiple init

318
00:14:41.120 --> 00:14:44.120
<v Speaker 2>functions in a file or package. Within a file, they

319
00:14:44.200 --> 00:14:47.240
<v Speaker 2>run in order of appearance across files in a package.

320
00:14:47.279 --> 00:14:50.480
<v Speaker 1>The order isn't guaranteed, so maybe setting up database connections

321
00:14:50.559 --> 00:14:51.799
<v Speaker 1>or registering.

322
00:14:51.320 --> 00:14:54.879
<v Speaker 2>Things sometimes use for that. Yeah, like registering image formats

323
00:14:54.879 --> 00:14:57.600
<v Speaker 2>by importing the image package for its in it side effect.

324
00:14:57.840 --> 00:15:00.200
<v Speaker 2>But relying on import side effects is often seen as

325
00:15:00.240 --> 00:15:02.879
<v Speaker 2>an anti pattern. Now, better to be explicit.

326
00:15:03.000 --> 00:15:06.320
<v Speaker 1>Okay, in it for setup, but use with caution. Let's

327
00:15:06.320 --> 00:15:09.639
<v Speaker 1>move to structuring more complex data structs and methods.

328
00:15:09.720 --> 00:15:12.360
<v Speaker 2>Structs let you group different pieces of data together into

329
00:15:12.399 --> 00:15:17.720
<v Speaker 2>a single custom type type, person, struct, name, string, age.

330
00:15:17.440 --> 00:15:20.120
<v Speaker 1>And p. Simple enough, how do you access the fields?

331
00:15:20.279 --> 00:15:24.480
<v Speaker 2>Dot notation dot p person name, Alice age thirty f

332
00:15:24.559 --> 00:15:25.679
<v Speaker 2>mt printline P name.

333
00:15:25.759 --> 00:15:27.200
<v Speaker 1>What about embedding.

334
00:15:27.080 --> 00:15:31.519
<v Speaker 2>AH, Embedding is like anonymous fields type employee struct salary

335
00:15:31.519 --> 00:15:35.039
<v Speaker 2>float sixty four. Now an employee value E has field

336
00:15:35.159 --> 00:15:38.639
<v Speaker 2>Z salary, but also E name and ehe promoted from

337
00:15:38.679 --> 00:15:39.720
<v Speaker 2>the embedded person struct.

338
00:15:39.720 --> 00:15:43.200
<v Speaker 1>Do you access the embedded fields directly? Cool and methods

339
00:15:43.440 --> 00:15:44.960
<v Speaker 1>functions attached to types.

340
00:15:44.919 --> 00:15:48.799
<v Speaker 2>Exactly, You define a method with a receiver funker pee

341
00:15:48.840 --> 00:15:52.080
<v Speaker 2>person Hell, my name is peak person p person grant

342
00:15:52.200 --> 00:15:53.639
<v Speaker 2>here pee person is the receiver.

343
00:15:53.840 --> 00:15:56.240
<v Speaker 1>You can have pointer receivers too, right, yeah, funk person

344
00:15:56.360 --> 00:15:57.600
<v Speaker 1>setage new agent. Right.

345
00:15:57.679 --> 00:16:02.200
<v Speaker 2>The big difference pointer receivers person can modify the original struct.

346
00:16:02.279 --> 00:16:07.039
<v Speaker 2>Value value receivers person operate on a copy of the struct,

347
00:16:07.120 --> 00:16:10.600
<v Speaker 2>so modifications inside the method don't affect the original.

348
00:16:11.360 --> 00:16:14.000
<v Speaker 1>So use pointers if you need to change the struct.

349
00:16:13.840 --> 00:16:16.679
<v Speaker 2>Generally yes, or if the struct is very large and

350
00:16:16.679 --> 00:16:19.720
<v Speaker 2>you want to avoid copying it for performance reasons. Value

351
00:16:19.720 --> 00:16:21.759
<v Speaker 2>receivers are simpler if you don't need mutation.

352
00:16:22.159 --> 00:16:25.039
<v Speaker 1>Can you add methods to any type like built.

353
00:16:24.799 --> 00:16:27.679
<v Speaker 2>In types, not directly to built ins like INNT, but

354
00:16:27.799 --> 00:16:30.399
<v Speaker 2>you can define a new type based on it. Type

355
00:16:30.440 --> 00:16:33.120
<v Speaker 2>my int int and add methods to my ind However,

356
00:16:33.159 --> 00:16:36.080
<v Speaker 2>the new type doesn't inherit methods from the underlying type.

357
00:16:36.320 --> 00:16:38.840
<v Speaker 2>You can also define methods for types from other packages,

358
00:16:38.879 --> 00:16:41.360
<v Speaker 2>but only within the package where you define the method.

359
00:16:41.519 --> 00:16:43.559
<v Speaker 1>What about calling methods on nil pointers?

360
00:16:43.960 --> 00:16:47.039
<v Speaker 2>That can cause a panic if you're not careful. Methods

361
00:16:47.080 --> 00:16:50.480
<v Speaker 2>with pointer receivers should ideally check if the receiver is nil.

362
00:16:51.080 --> 00:16:52.879
<v Speaker 2>If p equals nil.

363
00:16:53.519 --> 00:16:57.879
<v Speaker 1>Good practice, Okay, structs and methods. What about pointers themselves?

364
00:16:58.279 --> 00:17:01.440
<v Speaker 2>Pointers hold the memory address of a value. GO is

365
00:17:01.559 --> 00:17:05.799
<v Speaker 2>pass by value, meaning function arguments are copies. Pointers let

366
00:17:05.880 --> 00:17:09.160
<v Speaker 2>you effectively pass by a reference, allowing functions to modify

367
00:17:09.200 --> 00:17:10.160
<v Speaker 2>the original value.

368
00:17:10.359 --> 00:17:11.160
<v Speaker 1>How do you work with them?

369
00:17:11.839 --> 00:17:15.119
<v Speaker 2>Type declares a pointer type for example int, and the

370
00:17:15.200 --> 00:17:18.759
<v Speaker 2>variable gets the memory address. Creates a pointer pointer variable

371
00:17:18.799 --> 00:17:21.079
<v Speaker 2>to references the pointer to get the value it points to.

372
00:17:21.359 --> 00:17:23.839
<v Speaker 1>So she takes the address follows the address pretty much.

373
00:17:24.000 --> 00:17:26.960
<v Speaker 2>Using pointers avoids copying large data structures, which can be

374
00:17:26.960 --> 00:17:28.839
<v Speaker 2>good for performance, but it also means you need to

375
00:17:28.839 --> 00:17:31.480
<v Speaker 2>think about shared access and potential garbage collector impact.

376
00:17:31.640 --> 00:17:35.000
<v Speaker 1>Got it pointers for indirect access and modification? Now testing

377
00:17:35.319 --> 00:17:37.559
<v Speaker 1>crucial part of development. How does go do it?

378
00:17:37.640 --> 00:17:40.319
<v Speaker 2>Go has great built in testing test files, end and

379
00:17:40.440 --> 00:17:43.279
<v Speaker 2>test dot go test functions start with test and take

380
00:17:43.319 --> 00:17:46.799
<v Speaker 2>a testing dot T argument test my function testing dot T.

381
00:17:46.960 --> 00:17:48.880
<v Speaker 1>And it is used for reporting.

382
00:17:48.480 --> 00:17:53.039
<v Speaker 2>Failures right TFA TALF expected percingop percy and expected actual

383
00:17:53.079 --> 00:17:56.079
<v Speaker 2>logs and error, but continues t fetalf logs and stops

384
00:17:56.119 --> 00:17:58.839
<v Speaker 2>the current test immediately. Good error messages are key.

385
00:17:58.960 --> 00:18:00.599
<v Speaker 1>How do you run test Go tests in.

386
00:18:00.599 --> 00:18:04.680
<v Speaker 2>The directory go test dash v gives verbose output showing

387
00:18:04.720 --> 00:18:05.519
<v Speaker 2>each test run.

388
00:18:05.559 --> 00:18:08.119
<v Speaker 1>What about code coverage? Seeing what percentage of your code

389
00:18:08.160 --> 00:18:09.039
<v Speaker 1>the tests hit.

390
00:18:09.039 --> 00:18:13.000
<v Speaker 2>Easy, Go test dash Tierra profile coverage dot out generates

391
00:18:13.000 --> 00:18:17.079
<v Speaker 2>a profile. Then Go tool cover dash HTML coverage dot

392
00:18:17.119 --> 00:18:20.920
<v Speaker 2>out opens a nice HTML report showing covered and uncovered lines.

393
00:18:21.119 --> 00:18:21.680
<v Speaker 2>Very useful.

394
00:18:21.759 --> 00:18:25.920
<v Speaker 1>That sounds great for finding gaps. Any techniques for organizing tests, Table.

395
00:18:25.759 --> 00:18:28.480
<v Speaker 2>Driven tests are very popular and effective. You define a

396
00:18:28.519 --> 00:18:31.599
<v Speaker 2>slice of test cases often strucks, each containing inputs and

397
00:18:31.599 --> 00:18:34.920
<v Speaker 2>expected outputs. Then one loop runs all the cases.

398
00:18:34.680 --> 00:18:37.720
<v Speaker 1>Keeps things dry, don't repeat yourself exactly and clear.

399
00:18:38.119 --> 00:18:41.279
<v Speaker 2>Go also supports subtests using t run subtest name funct

400
00:18:41.279 --> 00:18:44.319
<v Speaker 2>testing dot T you. This gives better output organization and

401
00:18:44.400 --> 00:18:47.000
<v Speaker 2>lets you run specific subtests. You can even run subtests

402
00:18:47.000 --> 00:18:47.799
<v Speaker 2>in parallel with t.

403
00:18:48.079 --> 00:18:52.960
<v Speaker 1>Parallel tests nice any other useful GO test flags lots.

404
00:18:52.799 --> 00:18:55.880
<v Speaker 2>Short skips, long running tests if you mark them. Booker

405
00:18:56.000 --> 00:18:58.079
<v Speaker 2>na sets the number of tests to run in parallel.

406
00:18:58.119 --> 00:19:01.240
<v Speaker 2>You can run specific tests by name using NUSH run rejects,

407
00:19:01.559 --> 00:19:04.559
<v Speaker 2>nushtime out duration, NESHO, foul fast, NUSH account one to

408
00:19:04.640 --> 00:19:06.599
<v Speaker 2>disable caching, plenty.

409
00:19:06.279 --> 00:19:08.880
<v Speaker 1>Of control, and test helper functions.

410
00:19:08.519 --> 00:19:12.079
<v Speaker 2>Yeah common practice to extract reusable logic into helper functions

411
00:19:12.119 --> 00:19:15.559
<v Speaker 2>within the test file. Conventionally, they take testing dot t

412
00:19:15.680 --> 00:19:18.200
<v Speaker 2>B as the first argument, which works for both tests

413
00:19:18.400 --> 00:19:20.640
<v Speaker 2>testing dot t and benchmarks testing B.

414
00:19:20.960 --> 00:19:24.839
<v Speaker 1>Cool solid testing framework. Let's switch gears to interfaces, a

415
00:19:24.880 --> 00:19:25.839
<v Speaker 1>core concepting GO.

416
00:19:26.279 --> 00:19:30.079
<v Speaker 2>Interfaces define a set of method signatures. They specify behavior.

417
00:19:30.279 --> 00:19:32.759
<v Speaker 2>What makes Go different is implicit implementation.

418
00:19:33.119 --> 00:19:36.240
<v Speaker 1>Implicit meaning you don't have to say my type implements

419
00:19:36.279 --> 00:19:37.519
<v Speaker 1>my interface exactly.

420
00:19:37.599 --> 00:19:39.880
<v Speaker 2>If your type has all the methods declared in the

421
00:19:39.920 --> 00:19:43.279
<v Speaker 2>interface with the right signatures, it automatically implements that interface,

422
00:19:43.640 --> 00:19:45.240
<v Speaker 2>no explicit declaration needed.

423
00:19:45.400 --> 00:19:47.240
<v Speaker 1>Interesting like the io writer example.

424
00:19:47.359 --> 00:19:53.680
<v Speaker 2>Perfect example, io writer requires a right byte int error method.

425
00:19:54.119 --> 00:19:57.599
<v Speaker 2>Both o's file and bytes buffer have that method, so

426
00:19:57.680 --> 00:20:01.599
<v Speaker 2>they both satisfy io writer even though they're very different types. Internally,

427
00:20:02.079 --> 00:20:04.880
<v Speaker 2>you can create your own types that implement interfaces to

428
00:20:05.400 --> 00:20:06.039
<v Speaker 2>So it's.

429
00:20:05.920 --> 00:20:07.599
<v Speaker 1>If it walks like a duck and quacts like.

430
00:20:07.559 --> 00:20:09.880
<v Speaker 2>A duck, it implements the duck interface.

431
00:20:09.920 --> 00:20:11.240
<v Speaker 1>Basically, Yeah, what are the benefits?

432
00:20:11.440 --> 00:20:15.440
<v Speaker 2>Huge flexibility, abstraction. You can write functions that accept an

433
00:20:15.480 --> 00:20:18.319
<v Speaker 2>interface type and they'll work with any concrete type that

434
00:20:18.359 --> 00:20:21.880
<v Speaker 2>provides the required behavior. Great for decoupling parts of your

435
00:20:21.880 --> 00:20:25.599
<v Speaker 2>system and for testing. You can easily pass in mock implementations.

436
00:20:25.799 --> 00:20:27.920
<v Speaker 1>And the advice is to keep interfaces small.

437
00:20:28.160 --> 00:20:32.880
<v Speaker 2>Yes, very much so. The GO philosophy favors small, focused interfaces,

438
00:20:33.039 --> 00:20:36.920
<v Speaker 2>often with just one or two methods. Interfaces define only methods,

439
00:20:37.000 --> 00:20:37.640
<v Speaker 2>not fields.

440
00:20:37.799 --> 00:20:40.359
<v Speaker 1>Can you use interfaces to make functions more specific about

441
00:20:40.400 --> 00:20:40.880
<v Speaker 1>what they need?

442
00:20:41.240 --> 00:20:46.000
<v Speaker 2>Definitely? Instead of insert in data any, maybe insert in model.

443
00:20:46.240 --> 00:20:49.359
<v Speaker 2>Where a model is an interface requiring an id int method.

444
00:20:49.680 --> 00:20:51.160
<v Speaker 2>It clarifies the expectation.

445
00:20:51.319 --> 00:20:52.559
<v Speaker 1>What about the empty interface?

446
00:20:52.559 --> 00:20:56.599
<v Speaker 2>Any any or interface is the interface with zero methods.

447
00:20:56.640 --> 00:20:59.960
<v Speaker 2>Since every type has zero or more methods, every type

448
00:21:00.119 --> 00:21:01.319
<v Speaker 2>implements any so.

449
00:21:01.279 --> 00:21:02.839
<v Speaker 1>It can hold literally anything.

450
00:21:03.119 --> 00:21:06.319
<v Speaker 2>Yes, but you lose static type safety. To get the

451
00:21:06.400 --> 00:21:09.200
<v Speaker 2>underlying concrete value back, you need a type assertion.

452
00:21:09.480 --> 00:21:14.920
<v Speaker 1>The comic coaduck again vow okay, buy any dot string exactly.

453
00:21:14.960 --> 00:21:17.720
<v Speaker 2>That's the safe way. If the assertion fails, okay as

454
00:21:17.759 --> 00:21:20.839
<v Speaker 2>falls no panic. You can also use a type switch

455
00:21:21.039 --> 00:21:25.400
<v Speaker 2>switch v ANI types to handle multiple possible types safely okay.

456
00:21:25.160 --> 00:21:29.559
<v Speaker 1>Any for ultimate flexibility, but use assertions carefully. Now, errors

457
00:21:29.559 --> 00:21:32.839
<v Speaker 1>and panics. How does go handle things going wrong?

458
00:21:33.319 --> 00:21:36.279
<v Speaker 2>The standard way is using the built in air interface.

459
00:21:36.519 --> 00:21:38.880
<v Speaker 2>It just requires an error string method. Functions that can

460
00:21:38.920 --> 00:21:41.240
<v Speaker 2>fail return an error as their last return value. If

461
00:21:41.240 --> 00:21:43.079
<v Speaker 2>everything's okay, they return nil.

462
00:21:42.920 --> 00:21:45.319
<v Speaker 1>For the error, So check if air nil.

463
00:21:45.480 --> 00:21:47.759
<v Speaker 2>That's the standard pattern. Yes, you can create your own

464
00:21:47.759 --> 00:21:49.839
<v Speaker 2>custom err types too, just by defining a type with

465
00:21:49.880 --> 00:21:50.599
<v Speaker 2>an error method.

466
00:21:50.640 --> 00:21:52.119
<v Speaker 1>What about panics? When do they happen?

467
00:21:52.400 --> 00:21:56.279
<v Speaker 2>Panics are for truly unexpected, unrecoverable situations at run time,

468
00:21:56.920 --> 00:21:59.440
<v Speaker 2>things like index out of bounds, nil point, or to

469
00:21:59.480 --> 00:22:03.119
<v Speaker 2>reference stuff that likely indicates a programming bug. You can

470
00:22:03.160 --> 00:22:06.839
<v Speaker 2>trigger one explicitly with panic something went very wrong. Panics

471
00:22:06.920 --> 00:22:08.160
<v Speaker 2>unwind the call stack.

472
00:22:08.440 --> 00:22:11.079
<v Speaker 1>Can you stop a panic from crashing the whole program?

473
00:22:11.279 --> 00:22:15.119
<v Speaker 2>Yes, using recover, but it only works if called directly

474
00:22:15.160 --> 00:22:16.279
<v Speaker 2>inside a deferred function.

475
00:22:16.599 --> 00:22:18.000
<v Speaker 1>Only inside a defer yep.

476
00:22:18.279 --> 00:22:21.920
<v Speaker 2>If a panic occurs, deferred functions run. If one calls recover,

477
00:22:22.279 --> 00:22:25.839
<v Speaker 2>the panic stops and recover returns the value past panic.

478
00:22:26.559 --> 00:22:29.640
<v Speaker 2>Useful for preventing a single guarantine failure from taking down

479
00:22:29.640 --> 00:22:30.000
<v Speaker 2>the server.

480
00:22:30.079 --> 00:22:32.400
<v Speaker 1>For example, what are common causes of panics?

481
00:22:32.519 --> 00:22:34.839
<v Speaker 2>Nil pointer to references are a big one. Trying to

482
00:22:34.880 --> 00:22:38.039
<v Speaker 2>access a field on an uninitialized struct pointer or calling

483
00:22:38.119 --> 00:22:41.359
<v Speaker 2>a method on a nil interface value. Also calling a

484
00:22:41.359 --> 00:22:42.839
<v Speaker 2>function variable that's nil.

485
00:22:43.000 --> 00:22:46.039
<v Speaker 1>Right, got to initialize things? What about adding more context

486
00:22:46.039 --> 00:22:47.160
<v Speaker 1>to errors wrapping?

487
00:22:47.559 --> 00:22:50.440
<v Speaker 2>Error wrapping is great for that. Using fmt dot air

488
00:22:50.599 --> 00:22:52.400
<v Speaker 2>with the percent of a verb lets you wrap an

489
00:22:52.400 --> 00:22:56.000
<v Speaker 2>existing air inside a new one, adding context fmt dot

490
00:22:56.039 --> 00:22:59.240
<v Speaker 2>air opening configure dot percent of view air so.

491
00:22:59.160 --> 00:23:01.400
<v Speaker 1>You can see the chain of error exactly.

492
00:23:01.799 --> 00:23:05.400
<v Speaker 2>Errors dot unrapper gets you the underlying error. You can

493
00:23:05.440 --> 00:23:09.400
<v Speaker 2>implement unwrap methods on custom error types too. This helps

494
00:23:09.440 --> 00:23:10.359
<v Speaker 2>track the root.

495
00:23:10.200 --> 00:23:13.079
<v Speaker 1>Cause and errors is an errors.

496
00:23:12.880 --> 00:23:16.000
<v Speaker 2>Errors is Their target checks if any error in the

497
00:23:16.079 --> 00:23:19.640
<v Speaker 2>chain matches the target error, either a specific sentinel value

498
00:23:19.759 --> 00:23:23.799
<v Speaker 2>or type errors as are and targetvar tries to find

499
00:23:23.839 --> 00:23:26.039
<v Speaker 2>an error of a specific type in the chain and

500
00:23:26.119 --> 00:23:29.920
<v Speaker 2>assigns it to targetbar. Very useful for handling specific error

501
00:23:29.920 --> 00:23:31.000
<v Speaker 2>types programmatically.

502
00:23:31.079 --> 00:23:34.160
<v Speaker 1>Okay, air handling patterns are clear. What about stack traces?

503
00:23:34.720 --> 00:23:36.359
<v Speaker 1>Seeing the call sequence.

504
00:23:36.079 --> 00:23:40.000
<v Speaker 2>The runtime BBUG package helps there, debug stack returns the

505
00:23:40.000 --> 00:23:44.000
<v Speaker 2>current stack trace, debug dot print stack prints. It invaluable

506
00:23:44.039 --> 00:23:46.119
<v Speaker 2>when debugging tricky errors or panics.

507
00:23:46.200 --> 00:23:49.160
<v Speaker 1>Definitely okay. Let's move on to a newer feature, generics.

508
00:23:49.279 --> 00:23:50.400
<v Speaker 1>What problem do they solve?

509
00:23:50.559 --> 00:23:54.000
<v Speaker 2>Before generics, writing functions or types that worked with multiple

510
00:23:54.119 --> 00:23:57.519
<v Speaker 2>unrelated types often involved using interface any and lots of

511
00:23:57.559 --> 00:24:00.759
<v Speaker 2>type assertions, which was cumbersome and less type safe.

512
00:24:00.880 --> 00:24:03.039
<v Speaker 1>Like writing a keys function for a map that could

513
00:24:03.079 --> 00:24:05.480
<v Speaker 1>work for maps with string keys or in keys.

514
00:24:05.599 --> 00:24:09.559
<v Speaker 2>Exactly generics, let you write that function once using type parameters.

515
00:24:09.559 --> 00:24:13.799
<v Speaker 2>You declare them in square brackets funk KEYSK comparable v

516
00:24:14.079 --> 00:24:17.720
<v Speaker 2>any any m map kV k k.

517
00:24:17.680 --> 00:24:20.240
<v Speaker 1>Comparable v any. Those are type parameters.

518
00:24:19.720 --> 00:24:22.359
<v Speaker 2>With constraints right, K and V are the type parameters.

519
00:24:22.640 --> 00:24:25.079
<v Speaker 2>Comparable is a constraint, meaning K must be a type

520
00:24:25.119 --> 00:24:27.160
<v Speaker 2>that can be compared, like map keys need to be

521
00:24:27.640 --> 00:24:30.799
<v Speaker 2>any means V can be any. Type. Constraints limit what

522
00:24:30.839 --> 00:24:31.759
<v Speaker 2>types can be used.

523
00:24:31.799 --> 00:24:33.720
<v Speaker 1>How does the compiler know what K and V are

524
00:24:33.759 --> 00:24:35.400
<v Speaker 1>when you call the function.

525
00:24:35.480 --> 00:24:38.440
<v Speaker 2>Often through type inference based on the arguments. If you

526
00:24:38.480 --> 00:24:40.599
<v Speaker 2>pass a map string in, it figures out P is

527
00:24:40.640 --> 00:24:43.359
<v Speaker 2>string and V isnt. Sometimes you might need to specify

528
00:24:43.400 --> 00:24:45.519
<v Speaker 2>them explicitly key string in my map.

529
00:24:45.759 --> 00:24:48.200
<v Speaker 1>Can you have multiple parameters and complex constraints?

530
00:24:48.319 --> 00:24:53.720
<v Speaker 2>Yep, multiple type parameters, constraints defined using interfaces, specifying required methods,

531
00:24:53.799 --> 00:24:58.160
<v Speaker 2>combining constraints with n using to allow underlying types type

532
00:24:58.240 --> 00:25:01.519
<v Speaker 2>my end int could satisfy INT. The constraints package offers

533
00:25:01.519 --> 00:25:04.400
<v Speaker 2>predefined ones like ordered integer, float, and.

534
00:25:04.359 --> 00:25:07.279
<v Speaker 1>You can define generic types too, like strucks, dot type,

535
00:25:07.359 --> 00:25:09.000
<v Speaker 1>no t any structure Absolutely.

536
00:25:09.039 --> 00:25:12.440
<v Speaker 2>Generic types are very useful even with generics. Sometimes you

537
00:25:12.519 --> 00:25:15.720
<v Speaker 2>might still need type assertions inside the generic function if

538
00:25:15.720 --> 00:25:18.960
<v Speaker 2>you need to access type specific behavior not covered by

539
00:25:18.960 --> 00:25:19.640
<v Speaker 2>the constraints.

540
00:25:19.799 --> 00:25:25.559
<v Speaker 1>Generics sound powerful for reusable, type safe code. Now concurrency

541
00:25:26.079 --> 00:25:27.000
<v Speaker 1>Goh's famous for this.

542
00:25:27.279 --> 00:25:31.480
<v Speaker 2>It is important distinction. First. Concurrency is about managing multiple tasks,

543
00:25:31.559 --> 00:25:36.559
<v Speaker 2>maybe interleaving them. Parallelism is about executing multiple tasks simultaneously.

544
00:25:37.000 --> 00:25:41.079
<v Speaker 2>Go makes concurrency easy. Their routines right guroutines are lightweight

545
00:25:41.119 --> 00:25:44.039
<v Speaker 2>concurrent functions. You launch one just by putting go before

546
00:25:44.119 --> 00:25:47.200
<v Speaker 2>function call to go. My funk very cheap to create

547
00:25:47.279 --> 00:25:48.279
<v Speaker 2>thousands of them.

548
00:25:48.079 --> 00:25:50.720
<v Speaker 1>And the go run times schedules them onto OS threads.

549
00:25:50.920 --> 00:25:54.480
<v Speaker 2>Yeah, the ghost scheduler manages multiplexing groutines onto a smaller

550
00:25:54.519 --> 00:25:57.240
<v Speaker 2>pool of OS threads, handling things like work sharing and

551
00:25:57.279 --> 00:26:00.559
<v Speaker 2>stealing to keep cores busy. Developers have some control via

552
00:26:00.640 --> 00:26:03.640
<v Speaker 2>runtime dot gegomax prosess, but mostly it just.

553
00:26:03.640 --> 00:26:06.400
<v Speaker 1>Works okay, easy to start concurrent tasks. How do they

554
00:26:06.400 --> 00:26:07.000
<v Speaker 1>talk to each other?

555
00:26:07.160 --> 00:26:10.839
<v Speaker 2>Channels? Channels are the idiomatic way for guroteins to communicate safely.

556
00:26:11.119 --> 00:26:15.960
<v Speaker 2>They're typed conduits each each make caint you send with

557
00:26:16.279 --> 00:26:18.920
<v Speaker 2>change value and receive with value.

558
00:26:18.799 --> 00:26:22.279
<v Speaker 1>And they're syncretous by default, meaning send blocks until receive

559
00:26:22.599 --> 00:26:24.000
<v Speaker 1>and vice versa exactly.

560
00:26:24.039 --> 00:26:27.640
<v Speaker 2>For unbuffered channels, make chant ind it forces synchronization. They

561
00:26:27.759 --> 00:26:32.000
<v Speaker 2>operate fifo. You can also create buffered channels move fee,

562
00:26:32.319 --> 00:26:33.880
<v Speaker 2>make chan string ten.

563
00:26:33.839 --> 00:26:37.640
<v Speaker 1>Buffer channels let the sender proceed without a receiver immediately.

564
00:26:37.200 --> 00:26:40.839
<v Speaker 2>Available up to the buffer capacity. Yes, sends block only

565
00:26:40.839 --> 00:26:43.599
<v Speaker 2>if the butter is full, receives block only if it's empty.

566
00:26:43.960 --> 00:26:45.920
<v Speaker 1>How do you receive multiple values?

567
00:26:46.319 --> 00:26:49.359
<v Speaker 2>For range YEP for value rained loops until the channel

568
00:26:49.440 --> 00:26:51.880
<v Speaker 2>is closed to listen on multiple channels at once you

569
00:26:52.000 --> 00:26:53.279
<v Speaker 2>use select.

570
00:26:52.960 --> 00:26:54.680
<v Speaker 1>Select weights for the first channel.

571
00:26:54.440 --> 00:26:58.119
<v Speaker 2>That's ready right, select case vowel netwuble one cases, envel, default,

572
00:26:58.119 --> 00:27:01.880
<v Speaker 2>default if multiple are ready, uses one randomly. The default

573
00:27:01.920 --> 00:27:05.279
<v Speaker 2>case makes the select non blocking channels ensure only one

574
00:27:05.359 --> 00:27:08.359
<v Speaker 2>guaranteine receives each value sent. They're not message ques in

575
00:27:08.359 --> 00:27:08.839
<v Speaker 2>that sense.

576
00:27:08.960 --> 00:27:11.799
<v Speaker 1>Can you restrict channels to only sending or only receiving?

577
00:27:12.119 --> 00:27:15.880
<v Speaker 2>Yes, UNI directional channels, chantunt is send only, chance string

578
00:27:16.039 --> 00:27:19.119
<v Speaker 2>is receive only. Good for API clarity and type safety?

579
00:27:19.240 --> 00:27:21.079
<v Speaker 1>How do you signal you're done sending on a channel?

580
00:27:21.440 --> 00:27:24.200
<v Speaker 2>Receivers can detect a closed channel using the comma act

581
00:27:24.240 --> 00:27:27.839
<v Speaker 2>idiom value ok on. If ok is false, the channel

582
00:27:27.920 --> 00:27:30.920
<v Speaker 2>is closed and value is the zero value for the type.

583
00:27:31.119 --> 00:27:33.640
<v Speaker 1>What happens if you close an already closed channel or

584
00:27:33.680 --> 00:27:35.039
<v Speaker 1>send on a closed channel.

585
00:27:34.759 --> 00:27:38.839
<v Speaker 2>Panic Gotta be careful. Often you sink once or a

586
00:27:38.880 --> 00:27:42.519
<v Speaker 2>dedicated don channel pattern to ensure safe single closure.

587
00:27:42.359 --> 00:27:46.759
<v Speaker 1>Okay guarantines and channels for concurrency. What about managing the

588
00:27:46.759 --> 00:27:50.839
<v Speaker 1>life cycle of these operations, especially across APIs context exactly?

589
00:27:50.839 --> 00:27:54.000
<v Speaker 2>The context package is key for managing request life cycles, passing,

590
00:27:54.039 --> 00:27:58.039
<v Speaker 2>cancelation signals, deadlines, and request scoped values across API boundaries

591
00:27:58.039 --> 00:27:59.000
<v Speaker 2>and between guarantines.

592
00:27:59.039 --> 00:27:59.880
<v Speaker 1>What are the core parts?

593
00:28:00.039 --> 00:28:03.680
<v Speaker 2>Context dot background is the root empty context context dot

594
00:28:03.680 --> 00:28:07.559
<v Speaker 2>todo is a placeholder. Then you derive context using with cancel,

595
00:28:07.759 --> 00:28:10.279
<v Speaker 2>with deadline, with timeout, and with value.

596
00:28:09.960 --> 00:28:11.799
<v Speaker 1>And the context interface itself.

597
00:28:12.039 --> 00:28:14.079
<v Speaker 2>It is done a channel closed when the context is

598
00:28:14.119 --> 00:28:17.160
<v Speaker 2>canceled or times out. Aircast returns the reason for cancelation,

599
00:28:17.720 --> 00:28:21.319
<v Speaker 2>Context canceled or context deadline exceeded. Deadline tells you the

600
00:28:21.319 --> 00:28:27.440
<v Speaker 2>time it will be canceled, and value key retrieves associated values.

601
00:28:27.480 --> 00:28:29.119
<v Speaker 1>How do you attach values.

602
00:28:28.720 --> 00:28:32.960
<v Speaker 2>Context with value parent ctx key value. The key should

603
00:28:32.960 --> 00:28:36.160
<v Speaker 2>be comparable, often a custom unexported type to avoid collisions

604
00:28:36.200 --> 00:28:39.599
<v Speaker 2>between packages. Using the same string key value searches up

605
00:28:39.599 --> 00:28:40.640
<v Speaker 2>the context tree.

606
00:28:40.400 --> 00:28:41.799
<v Speaker 1>For the key and cancelation.

607
00:28:41.880 --> 00:28:44.400
<v Speaker 2>How does that work with cancel Parent Ctx returns a

608
00:28:44.440 --> 00:28:47.960
<v Speaker 2>new context and a cancel function. Calling cancel closes the

609
00:28:48.119 --> 00:28:51.240
<v Speaker 2>done channel that context and all contexts derived from it.

610
00:28:51.359 --> 00:28:53.680
<v Speaker 1>So gortein should listen on ctx.

611
00:28:53.200 --> 00:28:56.839
<v Speaker 2>Done yes, usually in a select statement select case natchy

612
00:28:56.920 --> 00:29:01.200
<v Speaker 2>ctx done, return ctx dot dr. It's crucial to defer

613
00:29:01.279 --> 00:29:04.599
<v Speaker 2>cancel right after getting the cancel function to ensure resources

614
00:29:04.599 --> 00:29:07.559
<v Speaker 2>are cleaned up. Timeouts and deadlines are just automatic ways

615
00:29:07.599 --> 00:29:08.039
<v Speaker 2>to call.

616
00:29:07.960 --> 00:29:12.160
<v Speaker 1>Cancel context seems essential for robust concurrent systems. How about

617
00:29:12.200 --> 00:29:15.079
<v Speaker 1>coordinating guarantines more directly synchronization.

618
00:29:15.359 --> 00:29:18.920
<v Speaker 2>The sink package has tools for that. Sinc weightgroup is

619
00:29:18.960 --> 00:29:21.440
<v Speaker 2>common for waiting for a group of gorgutines to finish.

620
00:29:21.640 --> 00:29:22.319
<v Speaker 1>How does it work?

621
00:29:22.519 --> 00:29:27.279
<v Speaker 2>You call WG dot ad DN for ngorutines. Each guarantine

622
00:29:27.359 --> 00:29:31.519
<v Speaker 2>calls WG done when finished, The main guarantine calls WG weight,

623
00:29:31.640 --> 00:29:34.920
<v Speaker 2>which blocks until the counter reaches zero. Need to be

624
00:29:34.960 --> 00:29:37.920
<v Speaker 2>careful not to misuse ad or done can cause deadlocks

625
00:29:37.960 --> 00:29:38.559
<v Speaker 2>or panics.

626
00:29:38.920 --> 00:29:41.319
<v Speaker 1>Is there something simpler for handling groups and errors?

627
00:29:41.680 --> 00:29:45.319
<v Speaker 2>Yes, go lang dot organ sensor group. It manages a group,

628
00:29:45.480 --> 00:29:48.960
<v Speaker 2>propagates context cancelation, and returns the first error encountered by

629
00:29:48.960 --> 00:29:52.119
<v Speaker 2>any groatine in the group. Often simpler than managing weight,

630
00:29:52.160 --> 00:29:53.720
<v Speaker 2>group and error channels manually.

631
00:29:54.000 --> 00:29:56.359
<v Speaker 1>What about protecting shared data from raise conditions?

632
00:29:56.559 --> 00:30:00.359
<v Speaker 2>That's sync mutex a mutual exclusion lock mutext dot lock

633
00:30:00.519 --> 00:30:04.359
<v Speaker 2>before accessing shared data. Mutex dot unlock afterwards insures only

634
00:30:04.400 --> 00:30:06.680
<v Speaker 2>one gorotine can be in the critical section at a time.

635
00:30:06.839 --> 00:30:10.119
<v Speaker 2>Don't copy utext's after first use. Trilock provides a non.

636
00:30:10.000 --> 00:30:12.359
<v Speaker 1>Blocking attempt and sync once.

637
00:30:12.519 --> 00:30:15.680
<v Speaker 2>Guarantees of function runs exactly once, even with concurrent calls

638
00:30:15.720 --> 00:30:19.400
<v Speaker 2>to its disdue method. Perfect for thread safe lazy initialization

639
00:30:19.599 --> 00:30:21.480
<v Speaker 2>like we mentioned for safely closing channels.

640
00:30:21.759 --> 00:30:25.039
<v Speaker 1>Good set of sync tools. Okay, last big area. Interacting

641
00:30:25.039 --> 00:30:25.920
<v Speaker 1>with the filesystem.

642
00:30:26.119 --> 00:30:29.039
<v Speaker 2>GO has several packages. Path filepath is for a platform

643
00:30:29.079 --> 00:30:33.759
<v Speaker 2>independent path manipulation, join xt der base and the AS

644
00:30:33.799 --> 00:30:38.359
<v Speaker 2>package that's for direct OS interaction. M adder ameshturl creates

645
00:30:38.400 --> 00:30:43.680
<v Speaker 2>parents to create files, open file, more control, remove all, recursive, delete,

646
00:30:43.960 --> 00:30:47.240
<v Speaker 2>stat file info, read file reads, whole file write file

647
00:30:47.279 --> 00:30:50.200
<v Speaker 2>reader also handles OS signals like interrupt.

648
00:30:50.519 --> 00:30:52.640
<v Speaker 1>What about the eye box package that's.

649
00:30:52.440 --> 00:30:56.440
<v Speaker 2>A newer abstraction layer for filesystems defines interfaces like fs,

650
00:30:56.480 --> 00:31:00.839
<v Speaker 2>dot FS and f smock file allows different filesystems implementations

651
00:31:00.880 --> 00:31:03.440
<v Speaker 2>like the real OS filesystem via OS dot d S

652
00:31:03.920 --> 00:31:06.480
<v Speaker 2>or in memory ones for testing using fistess dot map,

653
00:31:06.559 --> 00:31:09.799
<v Speaker 2>fs FS walkdor is great for traversing directory trees and.

654
00:31:09.759 --> 00:31:11.559
<v Speaker 1>Embedding files directly into the binary.

655
00:31:11.599 --> 00:31:14.400
<v Speaker 2>That's the embed package. Use the GO dot embed pattern

656
00:31:14.480 --> 00:31:17.440
<v Speaker 2>directive above a variable of type string, byte or mbed

657
00:31:17.480 --> 00:31:20.839
<v Speaker 2>dot f s. The compiler bundles the specified files or directories,

658
00:31:20.880 --> 00:31:23.720
<v Speaker 2>dot embed dot f S implements FS dot f S

659
00:31:23.759 --> 00:31:25.960
<v Speaker 2>so you can use the standard filesystem APIs to read

660
00:31:26.000 --> 00:31:29.279
<v Speaker 2>embedded files. Super handy for distributing assets with your app.

661
00:31:29.440 --> 00:31:32.279
<v Speaker 1>Wow. Okay, we've really covered the core of Go, from

662
00:31:32.359 --> 00:31:35.039
<v Speaker 1>structure and basics to concurrency and fileio.

663
00:31:35.319 --> 00:31:46.400
<v Speaker 2>Absolutely, it's a journey through modules, packages, types, variables, control flow, functions, interfaces, errors, generics, guaratines, channels, context, sync,

664
00:31:46.880 --> 00:31:49.920
<v Speaker 2>and the filesystem. Hopefully you have a clearer picture now

665
00:31:50.000 --> 00:31:52.319
<v Speaker 2>of how these pieces fit together and Go.

666
00:31:52.559 --> 00:31:55.480
<v Speaker 1>Yeah, definitely, and hopefully some of those specifics, like the

667
00:31:55.480 --> 00:31:58.759
<v Speaker 1>implicit interfaces or how gorteines work with the scheduler or

668
00:31:58.799 --> 00:32:02.799
<v Speaker 1>even embedding files. Hopefully those details spark some curiosity for

669
00:32:02.839 --> 00:32:06.359
<v Speaker 1>you listening Understanding those often leads to using the language

670
00:32:06.440 --> 00:32:07.240
<v Speaker 1>much more effectively.

671
00:32:08.160 --> 00:32:10.440
<v Speaker 2>And this deep dive is really just a starting point.

672
00:32:10.480 --> 00:32:13.839
<v Speaker 2>Go is a big language, always evolving. We definitely encourage

673
00:32:13.839 --> 00:32:16.680
<v Speaker 2>you to take this foundation and explore further, write some code,

674
00:32:17.039 --> 00:32:20.160
<v Speaker 2>dig into concurrency or generics if that interested you. The

675
00:32:20.200 --> 00:32:22.559
<v Speaker 2>official docs in the community are great resources.

676
00:32:22.880 --> 00:32:25.480
<v Speaker 1>So what aspects are you now curious about? What kinds

677
00:32:25.480 --> 00:32:28.599
<v Speaker 1>of problems might you try solving with Go? Using these fundamentals.

678
00:32:28.759 --> 00:32:30.279
<v Speaker 2>Yeah. Good Questions to ponder.

679
00:32:30.599 --> 00:32:33.440
<v Speaker 3>In a final thought, consider how goes designs that focus

680
00:32:33.440 --> 00:32:37.400
<v Speaker 3>on concurrency, the practical error handling, the efficient compilation. How

681
00:32:37.480 --> 00:32:40.559
<v Speaker 3>all that contributes to its success in modern software. How

682
00:32:40.640 --> 00:32:44.079
<v Speaker 3>might I understanding these GO fundamentals change how you approach

683
00:32:44.119 --> 00:32:47.000
<v Speaker 3>building software, even if you're using a different language. Something

684
00:32:47.000 --> 00:32:47.559
<v Speaker 3>to think about.
