The video offers a pragmatic distillation of Go’s most common pitfalls, effectively bridging the gap between basic syntax and production-ready logic. It serves as an essential checklist for any developer looking to align their coding habits with the language's specific architectural nuances.
深度探索
先修知识
- 暂无数据。
后续步骤
- 暂无数据。
深度探索
10 Go Mistakes That Scream Junior Dev本站添加:
In this video, we're going to cover 10 of the most common noob mistakes that beginners make in Go. Number one, strings are bytes and not characters.
Here we have two strings, hello in English and hallå in Swedish. So, let's run it and see what we get. We can see from the first string we get five and from the second string we get six. And that's because strings are bytes. So, here is one byte, here is two, three, four, five. But, what happened with the Swedish string is that this letter, it counts as two bytes. What can we do if we wanted to know how many characters there are in these strings? In that case, we would use the UTF-8 package from Go. And this one has a method called RuneCountInString.
If we try to run this again, we can now see that we get five back for both of these strings. Another situation when this can cause problem is when you want to slice a string. Here I have a function called preview one. And what it does is it will take a string and you will pass a number that tells how much of the string you want to see. And then here we have a second function that's called preview two. So, this one is wrong. It will not work as you expect it to do, but preview two, that one will work because when you're using range, it will give back a rune offsets and you are no longer working with bytes. And then, if we would run this, here I have a sentence. It mean hello, how are you in Swedish. And when running this, here is the result. We can see here for the first function, we lost a lot of characters. And this is probably not what we wanted at all. Do you want to become a senior Go engineer? Visit levelupgo.dev.
It teaches you the back-end skills that company pay for when they are hiring.
You learn by coding directly in the editor with exercise based on real production code. Courses take you from Go fundamentals all the way to shipping microservices and building real back-end projects. The first course is free. Try it out at levelupgo.dev.
Let's move on to mistake number two.
When using append on a slice, it discards your updates. Here we have a function called add role and this take one argument of a string slice and then we use the append on it. We want to add admin to the roles. And then here in the main function, we have our role slice.
We call add role and then we print out roles. If we run this, what do you think the value is going to be of roles? Let's see. We only have viewer and editor even if we called add role. And in this function, it should be adding the value admin to the slice. What's happening here is when you pass a slice to a function in Go, it pass it by value.
Here we are updating a copy of the roles slice. What you should do to be able to fix this is in this function, you will return the new slice. Let's just update the return value here. It will be a string slice and then where we call it from, we just assign roles to the new struct that is returned. So, we can say roles equal to add role. And then if we run it again, let's see what we get. And this time we can see we get viewer, editor, admin. Because slices are using arrays under the hood. And here we have a example. We have first one slice and then we create a sub slice. And these two slices, they share the same array.
What this means is if we modify T, that is also going to affect the other slice.
If we run this, we can see that we get 99. Sometimes the slice, it will resize.
And when it resize, it will move all the elements to a new array. Here's a example. We are using append again and here we are not reassigning the result back of append to S. If we run it, we can then see that the value that we appended, they are not here. And that's because a new array was created because the old one was too small. Always reassign the result back to the variable. Here we would say S equal. And then if we try it again, we can then see that we get the values that we expected to get back from append. Let's move on to the third mistakes. And that is zero values from maps look like real data.
Here we have a map of fruits and the key is the fruit and then we have a number here that is supposed to represent the price. And then we try to access mango and mango doesn't exist in this map. If we run this, we will get zero back. And what if we would just process this? This can leads to all kinds of errors because here we don't know if the price is zero or is it because mango doesn't exist.
How you would solve this is when you want to check if a key exist in a map, you can create two variables. So, the first one will be the value and the second variable, that will be a boolean if the key exist or not. So, here we can see that we do a check if this key exist and if it doesn't exist, we just say unknown product. And if it does exist, we just keep going and process it as normal. Mistake number four, wrong format verb makes the error undetectable. So, you can imagine we are working with a database. Then we are trying to retrieve a record from the database, but we get a error. It cannot find this record. In that case, you might want to wrap the original error with your custom error. The problem is you use the wrong format verb. So, if we run this, we can then see it says that this error is not of type error no rows.
And that's because when you're using percentage V, it will throw away the error chain. To solve this, what you should do instead is use W instead of V.
And as you can see here, this is a very easy mistake to make. So, let's run this.
On the second example, we can see that error is of type error no rows. Mistake number five, value receiver don't mutate. So, here we have a counter struct and it has a count field. And then we have a method here and this method will increment the count in the struct. However, there is a bug here.
So, this will never work. If we then would initialize the struct and then when we would try to call this method and then after that we would try to print the count. When we run this, we get zero even if we call this method three times. And the reason why this happen is because the counter here is actually a copy. What we are doing here is we are updating the copy and we are not updating the struct. To solve this, we will use a pointer receiver. So, here we put a star in front of the counter and that means instead of a copy of the value, this will be a address in memory to this counter struct. Let's try to run this. It will say three and it works as expected. Mistake number six, imagine you have a function that pings the DB connection to see if the connection is working as it should. And this connection will return an error. And then when we try to ping this connection, what we do first is we declare a error variable and then we don't set a value to it. So, this will be nil. And inside this if statement, we call our ping DB function and this will return an error. The problem with this code is we are creating a new variable here. And then we also assign the value that is returned from the ping DB function. In a if statement, variables have their own scope. So, when we are returning here, we are actually returning this variable. And this variable will be nil and we look like everything was okay even if it's not.
Mistake number seven, struct fields vanish in JSON. Here we have a struct that has some field. We have a name, email and age. Then we initialize the struct and we try to convert it into JSON and then we are printing out the JSON. So, if we run this, let's see what we get. And then we can see we get Patrick and we get age. However, email has been removed from the struct. And the reason for this is JSON marshal only sees the upper case field because they are public. If a field has lower case, that means it's private and it will not be exposed to the JSON marshal. To fix this, here I have created a new struct and we can now see all these field have the first letter is upper case. And if we want different names of the fields when they are converted to JSON, we can use struct tag. All of these field will become lower case once we convert them into JSON. Same here as example number one. And now let's try to run it. When we run it here, we can see the wrong one. And then we have the right one here and we can see all the fields are included and they also been converted to have lower case in JSON. Mistake number eight is use defer in a loop. Here we have a function that takes a slice of different paths to files and then we will loop over these paths and try to open the files. The problem is you shouldn't use it in a loop. Why is that?
Because defer only runs when the function returns. And then, let's say here we want to process maybe 20,000 files. What would happen in this loop is for the first file, we open it, and then it say defer close, but we don't close it. We then process the next file until we processed all 20,000 file. Then those file will be closed, but you are going to run out of memory before that happens. And the program is going to crash. To solve this problem, what we can do is we create a helper function.
So here, I would create a function called process one, and this function deals with the defer, and it return once per file. And then we could rewrite the function that is doing the looping.
Here, we have this function. Instead of calling defer in the loop, we call process one that take care of defer. So that means we will not have 20,000 file at the same time waiting to be closed.
Mistake number nine, discarding errors with underscores. So here we have a function and is using OS stat. And what OS stat does, it gives you back different information about a file.
Here, we want to get the size of file.
The problem here, because we are ignoring the error, and if that file doesn't exist and we try to call size on it, this will panic. And then, let's try to call it, and we can then see we get runtime error, invalid memory address or nil pointer. The way to solve this is don't ignore errors with the underscore.
Sometimes error handling can be quite tedious in Go, but if you ignore it, it can lead to very bad behavior in production.
So here's the right way of doing it. So we use the same method, but we check for a error. And if there's a error, we return it, and in other case, we just call the size method. If we would call it from the main method, it would look something like this. And let's try to run it again. We can then see here we have the output from this function, and it will say it couldn't find the file.
And for this example, it still panics here. So always remember to handle the errors. And last mistake beginner makes, and not only beginner for this mistakes actually. A lot of senior developers also make this mistake.
Here we have a function that create the unbuffered channel, and then we have a loop, and inside this loop, we are creating go routines. And these go routines are sending data to this channel. And when we call this from the main function, we will get a response from the first go routine. And what will happen is with the other two go routines, they will be stuck, and they will be leaking memory. And those go routines, they are waiting for a receiver. But because we are using a unbuffered channel, there is no receiver.
Those go routines will just be there forever and waiting. So main took one value, but for the other values, they are just waiting. And if we run this, we can then see we say worker three sending, worker three done, main got worker three returning, and then worker two sending, worker one sending. So these two are stuck. Now, how you would solve it is instead of using a unbuffered channel, you would use a buffered channel. So the difference here is this channel can store values, and it can store up to three values without anyone receiving it. What will happen here is each worker will send off their value, and it will be stored here in this buffered channel. In the main function, we will still only get the first value. It takes one value, and then it leaves. And the other two values, they will sit in the buffered channel, but that is not a huge deal because when this function returns, they will be garbage collected. If we run this, we can see we have the first example as before, and then we have the correct one. So here we're sending, and main got one, and then it's returning, and then it moves on. And then we have the other one, we send one, and then here worker two is done, worker three is done, and then worker one is sending, and then done. So here, there are no memory leaks, and compare that to the first one where worker one and worker two are stuck after they sending. I hope you enjoyed this video, and I will see you in the next one.
相关推荐
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
So What's Odin Lang Even Good For
TechOverTea
131 views•2026-06-01











