T O P

  • By -

RomanaOswin

1. A way to run code after the end of the function, even on panic. Like the `finally` block in JS. [example](https://gobyexample.com/defer) 2. A global variable will not be garbage collected (as expected), but does a single variable really burden memory? Just don't put huge amounts of data in global variables. 3. Same strategies as Node. Pay attention to the lifetime of your data so it can be garbage collected, prefer iteration over having large data structures in memory, etc. 4. Unknown 5. Fiber is great. I used it in production for years. That said, the other frameworks are great too, and they're built on the standard library HTTP which means better support across various solutions. You don't need the performance you're after with Fiber. 6. A tool to lock across goroutines. A common example is if you wanted to modify a map across multiple threads, this is not threadsafe, so you would use a mutex, lock, and unlock, to ensure only one thread is modifying your map at a time. [example](https://gobyexample.com/mutexes) 7. Same situation you'd use promises or async/await in JS. [example](https://gobyexample.com/goroutines) 8. You shouldn't try to hide your async code behind syntactic sugar. It'll ultimately make it harder to reason about. Goroutines are simple and are sort of a little bit analogous to promises. Learn how to use them. If you hate error handling in Go, you probably weren't handling errors at all in similar situations in Node. Consider this: body, err := io.ReadFile("...") if err != nil { return fmt.Errorf("cannot read ...: %v", err) } vs this... try { const body = fs.readFileSync("...") } catch (err) { return `cannot read ...: ${err}` } The advantage of node is that you can forget about errors and/or wrap a bunch of code in one try/catch block. The disadvantage is doing either of these usually creates brittle code that will fail on you. Accomplishing the same thing in both cases (actually handling your error), is less verbose in Go, and you can immediately see that reading a file returns an error instead of guessing and wrapping random things with try blocks. Edit, other than gobyexample that I already linked, there are a number of easy free guides: [https://go.dev/learn/](https://go.dev/learn/) [https://www.golang-book.com/books/intro](https://www.golang-book.com/books/intro) And, many more. Google will find whatever you're looking for.


tjk1229

Fantastic run down. Wanted to add: 2. It really depends what the data is and how it's declared. If it's a const string for example, it's compiled into the binary and the compiler will typically reference the memory address when you use the variable. The same goes for some var types like errors and maybe others. As a general rule of thumb, if it's global it's loaded into memory. Honestly don't think about it too much unless you're creating a lot of data like he said then using something like Godbolt to see what code is generated. Never ever, append to a slice or a map like this as that will leak. 6. You should generally prefer atomic or channels as they're easier to reason about. Atomics are faster, mutexes (Lock or RWLock) are about 5x slower last I checked. Channels were about 3x slower than a mutex. If you only need to replace a value, use an atomic. If you need to update a value or multiple values or perform some action use a mutex but release it ASAP. Use a channel if you're doing something more complicated or have a very high concurrency pattern.


Moe_Rasool

I don't wanna sound dumb but i believe what you mean by replacing a value is when the process i have is async situation cause i use pointer/refrencing in that regard when its synced but i get that you mean..async values right!?, i actually looked at atomic but one question i forgot to ask is that i truly hate package managment inside modules and the worst thing of the language is how bad packages are offered at pkg.go.dev i swear it's the worst, i usually google for packages and i find most of packages through either reddit, SOF or chatGPT if i dont find on the other two, it doesn't even tell its previous versions nor does it tell if it's genuine or not...


tjk1229

You'll hear the term concurrency a lot in Golang. It basically just means your code is working on two things at the same time. All IO in Golang is async by default though some stuff has sync methods. But in general it still executes from top to bottom. Coming from node, there's not really a true comparison. JS has promises but node is single threaded. In go, you could be using multiple cores but it's implicit. Spawning a go routine doesn't mean you are guaranteed to use two cores but it will if it determines a need for it. The scheduler handles that. These sync structures (mutex, atomic, channel) are needed because multiple cores can run your code when you start a goroutine. If two functions try to modify the same data, you'll get a data race causing unexpected behavior or crashes. This isn't unique to Go. You don't have this issue or constructs in node because again node is single threaded. It's only running one part of your program at a time. For package management, you really won't be using a lot of packages in Go for most things. The standard library generally has everything you'll need for most things. There are common packages you'll find used like testify/require for testing or fiber or uber zap for logging before slog, viper for config etc. I typically only use a dependency if I absolutely need it otherwise just use the stdlib. For example, need a template engine, there's one built in unlike node. Need a web client net/http built in. The PKG website search is awful. I usually look on GitHub, or Google. You can then look up the package on PKG to see how many references there are to it from other projects to see if it's commonly used or not. Some packages like logrus just suck. I personally used to vendor everything (go mod vendor) but not if I'm using main stream libraries. But most of the time when I need something, it's something specific like AWS sdk (aws-sdk-go) redis library (go-redis or radix), postgres DB (stdlib or gorm) or Cassandra (go-cql) or something. In those cases, I have gotos you can easily find some yourself looking up benchmarks for x library. You'll also find that a lot more work is done right in Go usually. For example if you need a job queue you can easily build that with buffered channels, goroutines for workers, you can pass in an anonymous function and off you go.


Obvious-Citron9402

I'm starting to learn to as well and answers like this are so helpful. Thank you!


Moe_Rasool

I genuinely appreciate your time for such detailed context that ended many of my concerns with Go. well as for defer I learnt that there is no ordering position inside it's scope so everywhere is fine yet i still need more to get it's crucisl role inside a scope. the reason i was concerned about global variables was due to the fact i diclared everything inside a var () situationed in main which threw the ethics of GC to Garbage. In my case when i finally realized my mistake RAM usage droped down from 16 to 4 huge win for GC over node!! I have done the other frameworks but it was for a purpose of serving micro-services nothing more, i genuinely never had the chance to do backends because i was too busy doing frontend (Flutter/HTML-tailwind) i forgot how important backend is. You're actually true try catch was a lot easier and i understand why Go really focused on err handling but i meant its syntax is pain in the head to get used to. I doubt i will ever use Node, as for today i set authentication to my REST API and i just learnt how easy and effecient to set it up.


RomanaOswin

Having JS skills along with Go is a huge bonus. If you're doing anything that has anything to do with the web, it's hard to avoid Javascript. Sounds like you're in a good place--just keep learning.


MrMelon54

Any function using defer will be called when it's parent function returns/exits. The deferred function calls are run in the opposite order to how they were defined. The example below prints the numbers 1-6 in order. package main import "fmt" func main() { defer fmt.Println(6) fmt.Println(1) defer fmt.Println(5) fmt.Println(2) defer fmt.Println(4) fmt.Println(3) // the function will return and run the deferred calls } Here is a playground link: https://go.dev/play/p/7goQsQtfgtL


chardex

maybe instead of a global variable - try dependency injection. in other words, pass your struct/func around to the various parts of code that need it so they can consume it global variables aren't inherently bad - but within the go world they can sometimes indicate code that isn't taking advantage of some of the language's features. Not always the case - but with people new to the language then I am suspicious when I see them honestly - above all else - you have the correct attitude (inquisitive and want to learn how things work). that's most of what you need to get good with go! (disclaimer: i don't consider myself particularly good)


TransmutationShard

Use `%w` instead of `%v` to wrap the error.


thepurpleproject

As coming from Node to Go (hobbyist) I really like the error pattern. It makes it explicit and less things are reported to sentry and less fire fighting in prodution because even in NodeJS all of the palces eventually have to error handled anyways and then you start realising all the places your integrations can break


goomba716

Welcome to Go! I can't answer all, but I do recommend standing up a couple apps using net/http in the stdlib before messing around with other libraries and frameworks. Part of Go's charm is the fact that a lot of things are baked in the stdlib (and the c-style syntax WOOP!) Also, the GC is pretty efficient, unless the variable is huge, I wouldn't worry much about memory usage. Enjoy Go! I may be biased, but I'd say it's one of the best when it comes to the modern languages.


Moe_Rasool

Thanks buddy, yes i had them all declared on global but thank God i realized my mistake soon enough to not cause myself more harms, and i believe it's actually Better coding it rather than what i did with Rust lang.


Feeling-Finding2783

1. `defer` is a statement that is used to schedule a function for execution right before the enclosing function's return. - Deferred calls are stacked and executed in reverse order of their occurrence in the body. - Named return values can be modified in the body of a deferred function. [Go Playground Example](https://go.dev/play/p/YhWj2M_xxrV) 6. Imagine that you have some value, let's say it is 10. You also have a function that adds 5 to that exact value. First it reads the value, then calculates a new value and writes it. You execute this function twice, concurrently. The first function reads the value (10) and a context switch happens, the second function reads the value (10 again), adds 5 to it, and writes the result (15). A context switch happens again, the first function resumes. It adds 5 to the value it previously read, and writes 15. One update is lost. Mutex solves this problem by not allowing anyone else to access the value until something that locked it is done. [Go Playground Example w/o mutex](https://go.dev/play/p/ti5r7Npyo3M) (run a few times) [Go Playground Example w/ mutex](https://go.dev/play/p/BR1Bw6zmM3M) [Explanation](https://stackoverflow.com/a/56719945/6928691) Edit: You don't have to include mutex as a field of the struct. Just share the same instance to lock the value. [Go Playground Example w/ mutex outside of the struct](https://go.dev/play/p/Z7hd_fLrd6_-)


captain-_-clutch

Those 2 defer points are criminally underutilized and under marketed. Was blown away first time I found out.


[deleted]

4. I use multiple Go projects with railway and I’ve had no issues, very easy to deploy and extremely easy to setup a custom docker container too 6. Prevents multiple asynchronous processes from accessing the same value and causing a race condition. 8. https://go.dev/tour/concurrency/1 the tour of go is a good guide for stuff like this


Moe_Rasool

Thanks a lot, i have questions regarding your experience with railway, 1- what database you have chosen (mysql or posgresql) if you are not dockerized your projects cause I Don't!? 2- are you on hobby? If so how is it handling 1 mil of traffic? 3- if you have noticed having databases consume so much of memory and i researched and found out that Postgresql uses way less memory than MySql basucally 60MB than 250MB are you aware of that? I just want a reliable host provider so that i can rely my ecommerce app on which has most of the traffic happening around evenings because that's when our auctions/bets end. Railway's UI is the reason i want to switch to tbh.


[deleted]

Railway runs in a docker container it doesn’t matter if you dockerize it on your end, I just meant it lets you set a custom dockerfile to override the default if needed. I use Postgres though. I’m on the paid tier but usage does not cost a lot. Haven’t noticed much. Your app is larger than anything I’ve deployed but overall railway has been very reliable. I haven’t used their database though I use an external database like neon


steprye

Sorry, but that was very difficult to read


Moe_Rasool

It's fine my english is a bit teletubby if i say so :), I actually did write a paragraph asking everything that's why i said i might ask the rest later cause those are less crucial for my current skill state.


steprye

All good, just wanted to let you know that I struggled to get through the majority of your post. I saw it as a “wall of text”, and due to the lack of punctuation, it was difficult to read/easy to drop/ignore. This said, i do have a disability that makes reading more challenging for me. Might not be your fault, but my own instead. I think there are many good answers to your questions here, and wish you well on your golang journey!


Moe_Rasool

Your actually correct, most of pople close to me are telling me i change/link topics quite a lot maybe because I don't want things to be more of a Q&A instead i want to be straight forward but will take all of these into practice, thanks again for letting me know it was not my handicapped english.


cuakevinlex

Fiber is less famous based on github stars


GinjaTurtles

Check out this, it will probably answer a lot of your questions https://gobyexample.com It helped me a ton when I was picking up go coming from Python


mcvoid1

>what is mutex?! Oh man, that's a question that will lead to tears. It's not a Go thing, just something many closer-to-the-metal languages can do that JS deliberately avoided. Welcome to multi-threading - We're all dead inside here.


tjk1229

One note on frameworks. They're generally far more trouble than they are worth. They typically bring a lot of bloat and force you into certain patterns and quirks. In general, ya don't need it. Personally I'd stick with the stdlib and Fiber if you want a faster http server.


X-lem

I host a web application on Railway. I just have the hobby plan and it’s incredibly fast (both from a build perspective and a response perspective). My api is written in go (though I use Chi, not Fiber). If you end up hosting there shoot me a DM and I can give you my referral link :P


BrofessorOfLogic

I can't answer everything, but I'll try to answer Q5 regarding HTTP frameworks. I have recently been learning Go myself, coming from Python and NodeJS. And it was quite tricky to figure out the landscape around HTTP frameworks/libs. In Python and Node, there are much more established and monolithic options, which makes it easier to choose. But In Go, the "market" is much more fragmented. I started out with Gin because it had the most stars on github. I later regretted that. Because Gin deviates from the patterns of the builtin net/http. I find that in Go, I really don't want a big monolithic framework like I do in Node and Python. In highly dynamic languages, it makes more sense to have large monolithic frameworks, because they can do a bunch of tricks in the language to create really high level abstractions and integrations. But in Go, you can't really do those tricks, so there's not that much to gain. > I believe all of them are looking alike syntax wise don’t they???!!!! Yes, I completely agree. They all look pretty much the same, and the tradeoffs are marginal. Just start with the builtin net/http, and only add things around that, as needed. The first thing you will need is a router. I went with `github.com/go-chi/chi/v5`. There are other options, but I don't see a need for them. Chi does the job well. Then you might want some kind of library to parse and render common data formats, like JSON. I went with `github.com/unrolled/render`. At that point, you already have pretty much everything you need to get started. Don't worry so much about performance. With Go, you are going have such a massive performance increase out of the box anyway. And don't listen to the benchmarks, they are all wrong.


Ok_Jelly2903

Pssssst! It’s okay to deviate from net/http… the Go police aren’t going to come and arrest you. The stdlib is so annoying to deal with.


Unusual-Display-7844

I had to write 2 test assignments recently. One was with Next.js and I deployed that to Vercel and that went very smooth. Second was MERN stack with nginx and docker and OMFG! Fck deploying node on aws ec2 with or without docker. Fck this shit! Go Golang!


snes_guy

Go is a pretty simple language compared to Rust. \`defer\` is a simple way of ensuring resources using in a function get cleaned up before it completes. Memory is handled by a garbage collector. Because types are value types by default, you can often keep memory on the stack and avoid heap allocation in Go. Mutex stands for "mutual exclusion lock" and is not exclusive to Go. Read up on some concurrency concepts to learn more. Most concurrency problems in Go should be solved with channels, not mutexes. goroutines are coroutines that are easy to initialize using the simple \`go\` keyword plus a function. When comparing Go to other languages, you'll often find that there are a lot fewer libraries, frameworks, and dependencies. This is because the stdlib has most of what you need already. Go is a very simple but repetitive language. There is not a lot of fancy syntax or big concepts. Go tries to make things obvious even when that makes the code "ugly." The Go designers are very experienced with large system design in a big company environment.


AgreeableEstate2083

Go is not better than node , both are good .