32 Reasons WHY TS IS BETTER Than Go

  Рет қаралды 227,084

ThePrimeTime

ThePrimeTime

8 ай бұрын

Recorded live on twitch, GET IN
/ theprimeagen
You Like Melkey? GIVE HIM A FOLLOW:
/ melkey
/ @melkeydev
Reviewed Reddit post: / anyone_who_tried_to_li...
By: simple_exporer1 | / simple_explorer1
MY MAIN YT CHANNEL: Has well edited engineering videos
/ theprimeagen
Discord
/ discord
Have something for me to read or react to?: / theprimeagenreact
Hey I am sponsored by Turso, an edge database. I think they are pretty neet. Give them a try for free and if you want you can get a decent amount off (the free tier is the best (better than planetscale or any other))
turso.tech/deeznuts

Пікірлер: 548
@roccociccone597
@roccociccone597 8 ай бұрын
As so often is the case... The guy in the article tries to write TS using Go. If you want to write TS then use TS. Go is great but not if you treat it like TS.
@ryangamv8
@ryangamv8 8 ай бұрын
No immutable variables tho. Tf is up with that
@roccociccone597
@roccociccone597 8 ай бұрын
@@ryangamv8 yeah sometimes it would be nice. Constants can cover some of those cases but since they're compile time constants they're not the same unfortunately. It would be nice if they introduced that eventually.
@gilbertovampre9494
@gilbertovampre9494 8 ай бұрын
Or any other language, I’m tired of people trying to write Java, C++, JS and other stuff in Go. You look at the code, you see the mess, you think “this looks like this person is trying to write in X language”, and than you go check their background and as it turns out, in their previously job they were writing in X language, you can see it right through it.
@cranberry888
@cranberry888 7 ай бұрын
​@@gilbertovampre9494how Go style different from x language?
@gilbertovampre9494
@gilbertovampre9494 7 ай бұрын
@@cranberry888 like, when I see "IRepository", "IClient", etc. or getters and setter for everything and everywhere, named "GetThis", "GetThat", they all came from some OOP language like C# or Java. When I see too much reflection or Generics, they probably came from JS, and so on. I might be wrong, I'm just stating about my own experience, and to this day it was never wrong. It's just minor things that give up their background.
@dryr-mp4pp
@dryr-mp4pp 8 ай бұрын
I've written a lot of code in both. I like the simplicity of Go, for sure. Fewer ways to shoot yourself in the foot...kind of. There are just fewer choices to make in Go, which can be a good thing. TypeScript is more like Scala. It can support about any paradigm you'd like to use. There are 10 ways of doing anything. You can easily over engineer a problem by adding layers of generic inheritance or something like that. Then, there's the layers of configuration. Not all TypeScript is the same. Max strict TypeScript, in practice, ends up looking much different than minimally strict TypeScript. The point about no union/sum types is really important. Not everyone uses these features, but once you start using patterns like tagged unions, everything starts to look like a tagged union problem. The simplest example is an Option type, which you can't make yourself in Go today.
@Tresla
@Tresla 8 ай бұрын
Option types are possible in Go, using Generics. They're just not as nice to work with, compared to a language like Rust which has very powerful pattern matching. Go Generics, at least in their current state, are very basic/underpowered. You could argue that that's perfect for Go, but I'd have to disagree. If you're going to add a feature like Generics, you can't half-ass it. type Option[T any] struct { Some T Valid bool }
@derschutz4737
@derschutz4737 8 ай бұрын
The difference is that Scala is half decent.
@anon-fz2bo
@anon-fz2bo 8 ай бұрын
​@@Treslahey thats a creative way to implement an optional type. but having it as a struct vs a enum just feels wrong like u mentioned. since an optional can only have 2 states, it makes more sense to abstract it as an enum, which u cant do in go unfortunately since enums in go are just untyped uints.
@Tresla
@Tresla 8 ай бұрын
@@anon-fz2bo I wholeheartedly agree. Go's lack of a truly generic enum type is one of its sore spots.
@Speykious
@Speykious 8 ай бұрын
As a Rust programmer, the one thing I dont like in Go's error handling is that you can still technically access the value even if there's an error. You get both the error and the value at the same time returned. In Rust you're guaranteed to only get one or the other thanks to ADTs.
@krux02
@krux02 8 ай бұрын
It has been repeated 1000 times. Yet as a go programmer, it doesn't bother me, or cause any bugs. I had to get used to it, sure. But after that it's just smooth sailing.
@Tresla
@Tresla 8 ай бұрын
​@@krux02 The issue is that it CAN cause bugs. Not to mention, not every function follows the rule of "if it returns an error, the value should be regarded as invalid". And it's not always clear without reading through all of a function's documentation (io.Reader is a perfect example of this). I've been programming primarily in Go for the past 7 years, and can say with confidence that Rust's way is just plain better.
@johnyewtube2286
@johnyewtube2286 8 ай бұрын
"as a ___" why do people feel the need to state they are writing as something or other? Is it just readit brain?
@deformercr6680
@deformercr6680 8 ай бұрын
​@@johnyewtube2286it helps the reader gain perspective about where someone might be coming from.
@SimonBuchanNz
@SimonBuchanNz 8 ай бұрын
​@@johnyewtube2286because it informs you of why they're saying the thing they're saying? You might have had a point if you saw "as a hair dresser, I think roundabouts are better than lights"
@bitmasked
@bitmasked 8 ай бұрын
Go's error handling is amazing because it keeps it as part of the control flow. Exceptions are the bane of new and "mature" codebases alike, especially within a 20 mile radius of any junior engineer.
@ThePrimeTimeagen
@ThePrimeTimeagen 8 ай бұрын
i hate exception handling with try catch
@OnFireByte
@OnFireByte 8 ай бұрын
Go error handling is better than ts for sure, but most of the time i just wish they do something like rust that wrap error in Result enum, or at least have some syntactic sugar like “?” operator in, again, rust
@thewarsawpakt
@thewarsawpakt 8 ай бұрын
@@ThePrimeTimeagen thoughts on elixir/erlang error handling?
@jarvenpaajani8105
@jarvenpaajani8105 8 ай бұрын
​@@ThePrimeTimeagen except in zig
@KevinCaffrey
@KevinCaffrey 8 ай бұрын
The biggest gap in Go error handling imo is the lack of a “must use” annotation like Rust has. If a function returns only an error, it can be easy to accidentally forget to check for error.
@vitiok78
@vitiok78 8 ай бұрын
The main problem of this article is that the author just wants to write Typescript code using Go. This is the stupid idea that doesn't work with any programming language. You just need to learn how to write idiomatic Go and most of those "problems" won't even appear in your project.
@elevationsickness8462
@elevationsickness8462 8 ай бұрын
Doesnt it give you inspiration. Anyone (with the right connections) can become a journalist these days
@gmdias0_
@gmdias0_ 8 ай бұрын
makes sense
@anon-fz2bo
@anon-fz2bo 8 ай бұрын
for real, the nil pointer arguement is dumb, u just have to remember to check if its nil. which if u write c/c++ you should already be comfortable with.
@vitiok78
@vitiok78 8 ай бұрын
@@anon-fz2bo I think he meant that in Go interface that contains nil is not nil. For example: var i *int // initializes to nil var something interface{} = i fmt.Println(something == nil) // prints false That's why it is very bad to write your own error type that implements error interface. Because it won't be nil when you return it
@jonasstrmsodd6352
@jonasstrmsodd6352 8 ай бұрын
I think I just like Go now. The whole try-catch blocks in TS is a nightmare, and I'm fairly sure it nudges you towards just "YOLO: Hope it doesn't fail".
@adambright5416
@adambright5416 8 ай бұрын
arrays are values, slices are pointers to an array. append returns a copy of a pointer to the same array; BUT if underlying array grows because of append, it will create a new underlying array and return new pointer to new array.
@thinhle462
@thinhle462 8 ай бұрын
For number 7 and your example, i would use json instead of map. In number 14, we could utilize struct and pointer to construct a optional value parameter or u can say dto
@maximiliandollinger4804
@maximiliandollinger4804 8 ай бұрын
A slice is a descriptor of an array or part it. It holds the length, capacity and the pointer to the starting item in the array. The descriptor is passed by value. If you pass a slice and change the length or capacity, nothing will happen outside the current scope. There is an article on the go dev blog.
@Daniel_Zhu_a6f
@Daniel_Zhu_a6f 8 ай бұрын
function overloading is a good alternative to OOP and object.verb(subject) notation. overloaded function call is essentially pattern matching on a tuple of types. so it's a good option to have
@ntrrg
@ntrrg 8 ай бұрын
25. A slice is a portion of an array (which may be the whole array if you do x := [5]int{0, 1, 2, 3, 4}; s := x[:]). They work on top of the array you slice. Mutating a slice element (s[0] = 5), will mutate its backing array (x[0] is also 5 now), and those changes will be reflected on any slice from that same array, if you need a copy, you have to use the builtin copy functiom or make a copy manually (for loop and copy to new slice with a different backing array, for example). Slices are passed as copy, but it doesn't mean you will get a full copy of its elements, you just get a copy of the slice data structure, which is a struct { length, capacity int, data uintptr }, but data is still a pointer, so if you do s[0] = 0 inside a function, it will mutate its backing array. If you pass s to a function, and do s = s[1:], s is now [1 2 3 4] in the function scope, but it will still be [0 1 2 3 4] outside the function. I actually find it quite easy to understand, and I am pretty stupid, its like any user defined data structure would behave when it is used as argument in Go. There are some other rules like appending to a slice with not enough capacity, but once you know the rules about slices, it is easy and makes sense. P.S. having unmutable data structures in Go is not possible, you can make copies, but mutating it is not a compile error.
@a-yon_n
@a-yon_n 8 ай бұрын
It took me a very long time to understand slice and yet I don't think I have fully captured it. Currently I see it as a view of the underlying array, when we cut a slice, we just create a new view of the same array, so manipulate one of the views will affect all the other views. It's so silly that Go designed it this way, make something very simple so hard to understand.
@ntrrg
@ntrrg 8 ай бұрын
@@a-yon_n I think sometimes we overcomplicate some concepts, in simple words, arrays are static arrays and slices are dynamic arrays.
@Nenad_bZmaj
@Nenad_bZmaj 3 ай бұрын
You have to be careful when appending to a slice within a function, if you want to observe that change in the caller function. If the capacity is exceeded, the slice inside the function will start pointing to a new array which is a copy of the old array but with double capacity. The original array remains unchanged and at the same old address, at which your outside slice points to. Thus you won't see the change. In that case pass the pointer-to-slice, instead of the slice. It points to the address of the slice header, not of the array, and so any change within a function works on the slice residing in the caller. Also consider this: you pass the instantiated but empty slice 'a' to a function which should populate it, and suppose your function makes slice 'b' with some elements, or calls another function whose return value is equivalent to slice b. And you just assign: a = b or a = g(...) (function g returns a slice). Now, slice 'a' inside the function (and, of course, inside the function that slice can have a different name i.e. the name of the parameter, but we tend to use the same names for arguments and parameters) - points to the underlying array of b, but the slice a in the caller still points to the same empty array as before. In that case, also, pass the pointer-to-slice to the function parameter and assign like this: *a = b, since by 'a' now you call a pointer variable, so you deference it to get to the slice header in the caller. And now slice in the caller points to the underlying array of b. You didn't have to copy each element in a loop. Also use *a = append(*a, c...) when appending inside the function, slice 'c' to slice a in the caller and you are not absolutely sure that you won't exceed capacity at runtime.
@Kane0123
@Kane0123 8 ай бұрын
Watched a few of Melkey’s videos recently, seemed to have a fairly reasonable opinion on most things… where is he on the Theo-Prime scale?
@gastrader9993
@gastrader9993 8 ай бұрын
An absolute beauty. Best of both worlds
@ejazahmed4609
@ejazahmed4609 8 ай бұрын
He seems like a junior in comparison. I don't know about his qualification but that's the impression I get.
@antonpieper
@antonpieper 8 ай бұрын
Can you elaborate on the Theo-Prime scale?
@orelweinstock
@orelweinstock 8 ай бұрын
Theo gg is a startup hacker developer productivity focused get stuff out the door Prime is a high scale optimal code, ergonomics freak, elite coder
@joseandkris
@joseandkris 8 ай бұрын
Actaully a good comparison
@CheefCoach
@CheefCoach 8 ай бұрын
26: Slice is a reference to some array. Length of slice is how many elements are in slice, and capacity is the length of the array that is point to. If somebody is using antipattern in go that sliceb = append(slicea, something) than sliceb can be either pointer to slicea or copy of slicea+something. If slicea is on full capacity, than go will create new array with larger capacity and put sliceb there, but it won't move pointer to slicea to the new array.
@Gusto20000
@Gusto20000 7 ай бұрын
It helps to remember that append is “value semantics mutation API”.
@codeChuck
@codeChuck 3 ай бұрын
@ThePrimeTimeagen, your point is very valid! If function signature in ts accepts a union type of arrays, it will be a runtime error in js! So, before pushing something into an string[] array, you should check for argument type to be a string with typeguard: ```ts if (typeof arg !== 'string') return; ```
@ryoriotwow
@ryoriotwow 8 ай бұрын
We take use of point 8 a lot actually. Some of our endpoints can have both "use and toss"-data, and something we want to keep in a state-container. Omit comes handy. Sure, the data-structure is the real culprit, but old and reliable monoliths and all. Point 11 is also fair enough. Function overloading is very useful. It allows you to break up huge conditionals into smaller segments. That way you can jump right in on step Z instead of step A if you for some reason already know all the conditionals in a given context, without having to extract some of the logic of already written code. But Typescript doesn't really have this either. Last I checked Typescript demands the same number of parameters, which sort of defeats the entire purpose all together.
@CapsAdmin
@CapsAdmin 8 ай бұрын
I've never used go but from the looks of it the error handling reminds me somewhat of a common Lua convention. The standard library is like this. Opening a file is like local file, err = io.open(...), then you can do local file = assert(io.open(....)) if you want to "panic" when opening a file. It also has something a bit like throw catch but it's handled by doing local ok, f_or_err = pcall(function() local f, e = io.open(...) if e then error("LOL") end return f end) I feel like its downside is that you have to drill res,err everywhere and it can get a bit cumbersome sometimes. Sometimes it's nicer to just throw an error and catch it at the top, at least if it's all your own code. If you remove try catch and throw in javascript and just did return [result, new Error("uh oh")] around in a "tuple", is that the same thing as golang? Or am I missing something?
@NowHereUs
@NowHereUs 8 ай бұрын
Slice is a reference to the underlaying array. Many slices can be constructed from one array. When you update slice your array gets updated. Similarly when you update array your slice may get updated if it has the range from the updated area of array. It is simple..
@davidsaint8866
@davidsaint8866 5 ай бұрын
for point 7, I think it's better in GoLang, as they can pass variables that don't exist in your struct. What I do in that scenario is create a function, loop through the filters and have a swith case statement that handles the supported properties, and a default. It's a bit more work, but it ensures the integrity of the system is not compromised.
@bcpeinhardt
@bcpeinhardt 8 ай бұрын
IME people use function overloading to 1. create a function that works on a couple different types instead of using full blown generics and 2. mimic default arguments (shorter signatures pass nil as arguments to longer signatures and the longest signature actually does the thing). At least that's what I use it for when I'm writing Java. It's fine but certainly not my favorite. Elixir's pattern matching based overloading is fabulous though, would be interested to see what it might look like in a strongly typed language.
@LusidDreaming
@LusidDreaming 8 ай бұрын
Just a quick PSA, accessing JS object fields by variable is a security vulnerability if that field can be defined by user input.
@aimanbasem
@aimanbasem 8 ай бұрын
by the same token, indexing a list with a variable is also a vulnerability, isn't it?
@LusidDreaming
@LusidDreaming 8 ай бұрын
@@aimanbasem if there is no bounds checking, which i believe there is in JS. But in C there is no bounds checking so if an array can be indexed arbitrarily (or even just access OOB), there are ways for a user to take control of the program and start trying to execute OS commands with whatever access the program was given. This is also why you should assign specific users/roles to processes and never run them as root unless absolutely needed
@oakley6889
@oakley6889 8 ай бұрын
Functional overloading exists in alot of langs, and its quite useful. Im pretty sure c++, java, a good handful of functional langs, etc Its good if you have some optimisation that uses a lookup table or premade collection that needs to be searched, if its created before, it can be passed in, or the function does it itself
@tokiomutex4148
@tokiomutex4148 8 ай бұрын
The only thing function overloading is good at is making the code more confusing, change my mind!
@Ryuuzaki145
@Ryuuzaki145 8 ай бұрын
​@@tokiomutex4148 with proper naming, I'd disagree. The method "String.toString()" in C# has many overloaded methods that still does exactly what the function means, the algorithm just is different depending on what data type is converted into a string. Building multiple constructors is also great, but you could argue we could simply create an empty constructor first then chain set properties to accomplish the same goal (such as " New Object().property1 = value .property2 = otherValue .property3 = value3; ) I find that function overloading only makes sense in OOP though. In Go, it would feel weird, kind of out of place
@atiedebee1020
@atiedebee1020 8 ай бұрын
​@@tokiomutex4148and they cause name mangling...
@edoga-hf1dp
@edoga-hf1dp 8 ай бұрын
Function overloading can be good for optional arguments or handling of same functionality for different types
@tokiomutex4148
@tokiomutex4148 8 ай бұрын
@@edoga-hf1dp Until someone modifies the code and a different definition of your function ends up called, good luck debugging it!
@yapet
@yapet 8 ай бұрын
About your "zod competitor" idea. Instead of doing a build step which will codegen validators, you can use the "new Function()" pattern to generate code in runtime. It’s the same approach that fastify uses to generate fast json serializers / deserializers given json schema definitions.
@majorhumbert676
@majorhumbert676 8 ай бұрын
This idea was already implemented. Look up "Typia"
@andrewnleon
@andrewnleon 4 ай бұрын
I use try catch a lot in c# and it has helped me in capturing specific errors as well presenting the error to the user. I used it most though when handling data calls and bindings. In JS i just do if statements and types to create a more concrete sense of error handling. Before not knowing this development was very complicated, i agree every engineer should be keen on error handeling.
@chrism3790
@chrism3790 8 ай бұрын
To me, a telling sign that someone is inexperienced in programming (or that they're using the wrong tool for the job) is that they complain about error handling being cumbersome. It tells me that they haven't been bit in the ass enough times to realize that handling errors is orders of magnitude less painful than dealing with run time bugs and crashes. Go's approach to errors might not be elegant, but try/catch is 100 times worse, because it gives programmers a responsibility they're usually are too lazy to handle.
@felixjohnson3874
@felixjohnson3874 8 ай бұрын
I'd rather the program fail than clobber itself or anything else
@zhamed9587
@zhamed9587 8 ай бұрын
It turns out that it's easy to mistakingly ignore or overwrite errors in golang. I've worked on large golang code bases, and I've seen this issue many times. It's a mediocre and badly designed language at the end of the day.
@sergisimon9620
@sergisimon9620 7 ай бұрын
I still feel like errors should be sum types, like in Rust with Result or Either with Haskell. That being said, I'm 100% on having error handling as values and that the compiler forces you to know that something can error.
@sinom
@sinom 8 ай бұрын
Golang's value errors would be nicer or they instead were some result return type with monadic operations on it
@Entropy67
@Entropy67 8 ай бұрын
Agree but you get some interesting freedom with what it is right now 🤔
@Qrzychu92
@Qrzychu92 8 ай бұрын
​@@Entropy67you don't have to use the monadic things everywhere
@OzzyTheGiant
@OzzyTheGiant 8 ай бұрын
I don't want to resort to whataboutism but C has the same thing, if I recall correctly, and yet no one bats an eye
@llIlllIIlIIlllIlllIl
@llIlllIIlIIlllIlllIl 8 ай бұрын
19:40 When making a custom List element (as a toy project) I had to write the same code inside two classes, one extending OL and another extending UL. Or I could use a mixin which isn't the world's prettiest thing but at least it works. I wish CustomElements received some set of behavior as a constructor argument to compose from so that mixins are less ugly and easier to reuse.
@AScribblingTurtle
@AScribblingTurtle 8 ай бұрын
35:42: A Slices capacity describes how many elements it can potentially hold, before the Memory manager needs to reallocate and copy it somewhere else. Until you exceed the capacity of the slice (with something like append()) The Slice stays bound to the initial array and does not use memory of its own (using the array instead) As soon as you exceed the capacity, the slice and its content are copied to a new memory location. (Thus becoming independent and creating memory, that needs to be handled by the GC) When creating a slice from an existing Array, The Slices capacity is the "arrays length" - "the slices start index". If you create two slices, from the same array and they overlap, it is possible to change one slice's values by manipulating the other slices's data. (Since both slices would share the same memory locations) 56:42 : Dang it, I should probably continue watching before writing comments. Slices are not jus sugar though. Arrays are always static. Aka an Arrays capacity is always its length and that length cant change. Slices are more what you would expect from a PHP or Javascript Array. Meaning a dynamic length and no control over where in memory it lives. A Slice can be both a ref or copy (Depends on context) . Initially it is a ref. If you exceed the capacity, it becomes a copy.
@Josh-hv4wo
@Josh-hv4wo 2 ай бұрын
Typia allows for runtime validaton of TS objects using TS types/interfaces. Write an interface. Validate some incoming json against it. Beautiful. All the other runtime validation libraries have you operate kind of backwards to that.
@macsmola
@macsmola 5 ай бұрын
What's the problem with dereferencing nil in go? I've just tried it in the online sandbox. You get a neat stacktrace just like in Java. That's super easy to fix. If it looked like in C where you need a valgrind then that would be other story. Or am I missing something?
@Nenad_bZmaj
@Nenad_bZmaj 3 ай бұрын
#26 - slices are NOT messy if you first read the language specifications. A slice holds three numbers: memory address, len and cap. The first one is a pointer to an allocated array. That address is the VALUE of the slice. In assignments to other slices/new slices, as any other value, it is copied, thus the memory address of the underlying array is copied. Therefore, all slices derived from one slice point to the same array UNTIL YOU CHANGE their value. Example. a := []int{1,2,3}. There is an array holding 1,2 3 and some more space where you can append new elements. Now, b:= a. b points to the same array. c:= b[1:] . c points to the same array but starts at index 1 of b, so it represents 2, 3 elements. e :=c[1:]. e represents element 3, because it starts from index 1 of c. You can't retrieve the leading elements, i.e 1, 2 (as you can with tailing elements), but you still have slice a if you need them. But let's have d:= []int{1,3,5.7}. This points to another array. Now lets assign: c = d[:len(d)-1]. Since value of d (memory address of the second array) is assigned to the value of c, c NOW DOESN'T POINT TO THE FIRST ARRAY but points to the second array and represents numbers1,3,5 , but last element is sliced away by slice operation. You can retrieve it: c= c[: len[d)]. Just as with x:=3 , x changes its value when you assign x=7. A slice behaves the same way, only its value is some memory address. Now, his objection was (probably) this: When you pass a slice to a function as value (it is still reference to an array, and thus light-weight), and use the builtin append function to append the receiver var inside the function, if the slice capacity is exceeded, Go runtime will copy the ARRAY to a new location but with a double size (new cap = 2*(old cap + num of appended elements).Of course, the value of slice inside the function changes: it now points to this new array. The slice in the caller still points to the old array and thus that array is not appended beyond its capacity. In order to obtain the wanted result in this case, don't pass a slice to the function, pass a pointer to slice. The receiving parameter points to the slice header on the stack of the caller function, and whatever you do with it affects that slice header, and that one, as any slice, is always pointing to its underlying array on the heap, no matter if that one was copied to another place in memory (at least until you change the value of the slice). OR, return the slice from the function, and you don't have to use pointer to it. But if your function parameter ap received &a (a being some slice from the caller), and then the function did this: *ap = c (c being some other slice pointing to a different array), then you changed the value of a from within the function, and now a points to that different array. This is perfect for populating a slice from some function that spits out the slice, all at once, and you don't have to copy element by element, UNLESS you want, for some reason, to have exactly the old array repopulated and you care about the address. In that case you wouldn't use *ap = c, but builtin copy function: copy(*ap, c). The copy function copies all elements to the underlying array of a, and the value of a (the address of that array) is not changed. In fact, in this case, you can pass a (not pointer to it) and do: copy(a, c) in the function, and you don't have to return a.
@LusidDreaming
@LusidDreaming 8 ай бұрын
This whole article is basically saying "I don't know how to program if I don't have the full set of TS features."
@ivanjermakov
@ivanjermakov 8 ай бұрын
This whole article is basically saying "I like dynamically typed languages"
@UxerUospr
@UxerUospr 8 ай бұрын
Not just TS, but the JS frameworks and sundry other packages he must use. Apples != Oranges
@teejaded
@teejaded 8 ай бұрын
For me, less language features means when I have to read your shitty code (don't be mad, all code is shitty) I don't have to spend as long figuring out what the fuck you were doing.
@Titousensei
@Titousensei 8 ай бұрын
About point 7 dynamically looking at struct field names, isn't that what the reflect package is for?
@lollol012
@lollol012 8 ай бұрын
Holy shit, 1 hour. Lets go
@avi7278
@avi7278 8 ай бұрын
yeah let's go. what your name?
@trapexit
@trapexit 8 ай бұрын
@14:00 An uncaught exception is an abort()/assert(). It's pretty trivial to do that around the code if that is in fact the behavior you want.
@AlecSorensen
@AlecSorensen 5 ай бұрын
There is function overloading in TS where you can define a function that can different definitions for types in your params. In regular JS, you don't need it, since there are no types.
@nodidog
@nodidog 8 ай бұрын
As someone who actually has a couple of years experience with Go, there is NO WAY that this blogger does. They're not even aware of a lot of the basic functionality and idioms. Yikes that they felt confident enough to write an article and share it online 😂
@kidus_f1
@kidus_f1 8 ай бұрын
I'm wondering how Melkey could have a Go course on Frontend Masters when he doesn't know how slices work, it's basic stuff
@MrToup
@MrToup 6 ай бұрын
I really like when you take a really small snippet to explain your point. Would love to see more.
@rosehogenson1398
@rosehogenson1398 8 ай бұрын
go doesn't have a "dynamic array type," it has the append() function append() writes the new value in place if the capacity is large enough, otherwise it makes a copy
@Warflay
@Warflay 8 ай бұрын
You need function overloading especially when working with generics, e.g. in C++ the recursive definition of varardic template functions. Example: void write() {} template void write(T const &val, Args && ...args) { std::cout
@joejoesoft
@joejoesoft 8 ай бұрын
Overload isn't just "generics", but it's the main usage pattern. You can use overload for optional parameters, default values, and for function wrapping (did I miss a usage?). The Quicksort example of "sort" in this video is a good example of function wrapping. Another good example is when you have the data of an item in a collection, but your API wants the index of that data. Just overload the function name with a version that does the index lookup and calls "wants and index" version. I'd rather the LSP/IDE do the work than having a bunch of similarly named functions with suffixes like ByValue/ByIndex/ByNameAndIndex/Etc in the name. It's just a poor duplication of the parameter signature information. This is assuming a typed language, of course. I don't have to write a bunch of logic code to test if the signature is valid, don't have a monolithic parameter list, create a wrapper struct/object, or use a vague undefined parameter array.
@Sz4mar
@Sz4mar 8 ай бұрын
😊
@rosehogenson1398
@rosehogenson1398 8 ай бұрын
Does an LSP actually help you with function overloading? rust-analyzer never gives me a helpful result on a .into() call
@joejoesoft
@joejoesoft 8 ай бұрын
@@rosehogenson1398 The most helpful part is that you don't have to pick from a list of function names and don't have to mentally translate a variable to a type. These actions clear your short-term like a GOTO statement. You have the tools auto-complete the function name and you plug in your variables that you already had in mind. Breaking mental flow is in the top 5 reason for why users hate a feature - especially in UI design.
@huge_letters
@huge_letters 8 ай бұрын
17:50 - I don't think that's really TS unions fault but more fault on the part of how TS treats mutations. I think TS type system is very "math-y" with how sets relate to each other and that's the artifact of that - Array is indeed a subset of Array, there's nothing inherently wrong with TS "thinking" that.
@llIlllIIlIIlllIlllIl
@llIlllIIlIIlllIlllIl 8 ай бұрын
Fwiw the subset relationship is only correct on immutable arrays. For mutable arrays neither is a subset of the other. (Because Array cannot have a string pushed but Array can)
@huge_letters
@huge_letters 8 ай бұрын
@@llIlllIIlIIlllIlllIl fair point, yeah. Cause then the operations available on set members also are a part of the set. So a mutable Array set also includes an operation .push(string). And then you have that .push(string) is not a subset of .push(string|number) but vice versa so neither Array set is a subset of each other.
@nexovec
@nexovec 18 күн бұрын
OP: "Why can't you be like typescript?" Go: "I'm sorry, dad"
@nevokrien95
@nevokrien95 8 ай бұрын
For api design inherentance is a great tool. U don't want more than like 2 layers deep. The nice part with Inherentance is that it let's u define a functi9n for the api. In a waybits an api api
@linkfang9300
@linkfang9300 8 ай бұрын
11:34, I think the 2nd point was trying to argue that if you don't have the if statement to check "err != nil", then you have no idea what goes wrong? I am not familiar with Go, but that's what I get from the article. In the other hand, in JS/TS, if you don't have try catch, your code will stop there and show you the error. You don't need try catch to know where goes wrong when you develop things. And also for try catch, you can put all logic related to tmpls inside try block so you don't need to use let to defined it outside the scope, right? The error in catch is some kind of dynamic, depends on where it goes wrong. So, err is not a static general object but will tell you where and what goes wrong. And if the function that returns the value is your own JS/TS function, then you can make sure it will return an object like, {value: "some value", err: ""}, so when anything wrong happens in the process so you even don't need the try catch to log the error message, you can just const tmpls = func(), and then check if tmpls.value = undefined, and log errorr (tmpls.err), pretty much similar to the way you like in go. So you could actually do it differently using JS/TS. I know you don't like JS and TS, but sometimes, you are a little bit too biased on them. I do enjoy when you argue some facts, but not when it's bias.
@u007james
@u007james 8 ай бұрын
yeah thats good practice for handling each line, but sometimes people just try and catch the entire block once and log the error and line later,
@KevinCaffrey
@KevinCaffrey 8 ай бұрын
In Go, the equivalent of “implements XYZ” is “var _ XYZ = (*MyStruct)(nil)”. A bit clunky, but does just about the same thing as an “implements”.
@white-bunny
@white-bunny 8 ай бұрын
Interfaces are intrinsic. You're not supposed to write implements in the code, Go is supposed to find that out itself.
@KevinCaffrey
@KevinCaffrey 8 ай бұрын
The pattern I described can be found in Go’s FAQ. Sure, it’s not necessary to have such a statement, but it can’t be that unidiomatic if it’s in the official documentation. I find that it can be useful in certain scenarios, providing a helpful guard rail when I refactor interfaces.
@houssamabouiba9848
@houssamabouiba9848 8 ай бұрын
on the point number 5 the notion of saying explicitly struct a implements interface b a seems good i think the golang way batter because in compile time you have to know who implements who and especially when it goes like 5 6 8 deep it can make compile time a lot slower.
@burdenedbyhope
@burdenedbyhope 6 ай бұрын
the Result | undefined return type is actually pretty nice, you must check for undefined before accessing the Result. But try-catch feels very frustrating, just like old day Java, and even worse, no checked exception, all runtime exception. Maybe typescript can improve on this in the future.
@synthatik
@synthatik 5 ай бұрын
nil pointers are only an issue in untested Go, if you're encountering nil maps or nil pointers after deploy - you didn't test the code properly
@grug_smash_keyboard
@grug_smash_keyboard 8 ай бұрын
7:23 im not a experienced go dev so i dont really know what the standard practice is, but golang-ci includes a linter that catches errors that are assigned to underscores.
@redpillsatori3020
@redpillsatori3020 8 ай бұрын
58:40 - Another complaint about Go: "Slice/capacity gotcha with pass by value/reference" What are they talking about here? ChatGPT: Ah yes, the good ol' Go slice behavior. What's funny is that people get caught in a kind of cognitive dissonance with Go slices. They look and act like dynamic arrays from other languages but have some unique behavior that can make you pull your hair out if you're not careful. A slice in Go is actually a lightweight data structure that wraps around an underlying array. It contains a pointer to the array, the length of the slice, and its capacity. While arrays are passed by value (meaning a full copy is made), slices are header values that get copied, but they still point to the same underlying array. Here's a gotcha: ```go func main() { original := []int{1, 2, 3} modified := original modified[0] = 9 fmt.Println(original) // prints [9, 2, 3], not [1, 2, 3]! fmt.Println(modified) // prints [9, 2, 3] } ``` You modified modified, but original also changed. Why? Because both slices share the same underlying array. Here's another one related to capacity: ```go original := []int{1, 2, 3} newSlice := original[:1] // newSlice is now [1], right? newSlice = append(newSlice, 4) fmt.Println(original) // prints [1, 4, 3] Surprise! ``` Wait, what? You only modified newSlice, why did original change? This is because the underlying array had enough capacity to accommodate the new value. append doesn't always create a new array; it reuses the existing one if it can. It's efficient but can lead to confusing behavior if you're not careful. This can really trip you up if you're not aware of it, especially if you come from languages like Python or JavaScript where you don't usually have to think about these things. But once you understand it, it's incredibly powerful because you can do very efficient array manipulations without a lot of extra memory allocations. So, the advice here is: Know what you're dealing with. Understand the slice header and its relationship with the underlying array. If you need a true copy, make one explicitly.
@llIlllIIlIIlllIlllIl
@llIlllIIlIIlllIlllIl 8 ай бұрын
16:33 This is not about union types but mutable arrays not being invariant (violating Liskov Substitution Principle). Java arrays and C# arrays also has this problem. Other generic types don't have this problem for all three languages. Edit for clarity: SubType[] should not be allowed to be assigned into where a SuperType[] is expected when the arrays are mutable, but all the languages I mentioned allow this. (Here SuperType = number | string, SubType = number)
@ivanjermakov
@ivanjermakov 8 ай бұрын
Not sure about C#, but in Java generics are invariant, so you cannot pass List argument into List parameter, so this example will not compile.
@llIlllIIlIIlllIlllIl
@llIlllIIlIIlllIlllIl 8 ай бұрын
@@ivanjermakov I did a google search and Java Arrays are covariant, contrary to Java Generics, no?
@llIlllIIlIIlllIlllIl
@llIlllIIlIIlllIlllIl 8 ай бұрын
Oh but JS arrays are like Java ArrayLists, that's fair.
@flyingmadpakke
@flyingmadpakke 8 ай бұрын
Are you sure about C#? Last time I wrote C# you would have to explicitly declare your generics as being either covariant or invariant (contravariant) if you wanted to use them in such a way. Then, if you wrote a method that returned an invariant generic, you would get a compile error.
@llIlllIIlIIlllIlllIl
@llIlllIIlIIlllIlllIl 8 ай бұрын
@@flyingmadpakke I was specifically referring to arrays, not all generic types. I'll edit the op for clarity.
@chaorrottai
@chaorrottai 6 ай бұрын
off topic: something i don't undertand about c++, why not just have the compiler manage inserting delete(var) in the code at relevat code locations. Like if a pointer is declared but not returned in a function, then insert a delete(pointer) and if it is returned, then the delete function could be inserted before the pointer reasignment or the end of the scope containing the pointer. It would litterally be one compiler pass and it should be fairly easy to program. Just follow the pointer to it's scope ends, including function returns.
@00jknight
@00jknight 5 ай бұрын
In go, you can recover from panics and return a 500, or treat it basically like try/catch. It's kinda wild but it's useful to use at the root of your request handler in a http server for instance.
@cosmicspice9477
@cosmicspice9477 24 күн бұрын
In rust it is not feasable to have a `struct Hello implements Greeter {}` kindof deal, because at any moment, foreign code can implement their traits on your types, breaking this neat model. The best solution is rust-analyzer's hints, that write `2 implementations` above the definition
@waffles3782
@waffles3782 8 ай бұрын
A good use case for [8] that was explained to me was say, creating a new entry in something. For example a user obj/struct that has fields for name, email address, phone number and a unique ID. When adding a new user, you might not have an ID yet, that could be automatically assigned from the DB, so your create user gets filled out as a (not the right syntax, but whatever). So this way when the User type gets more fields added to it in the future, your adder still needs to be modified to support that because it's linked through. Whereas having two versions, effectively UserWithID and UserWithoutID means there's no linking and you have to remember to add/remove fields in both whenever it changes. I guess the alternative is having inheritance maybe? But fuck that.
@Luxalpa
@Luxalpa 6 ай бұрын
Yes, this is what I'm missing as a Rust developer. I really enjoyed composing the types in Typescript even though it was quite hard at times. But in Rust I need a variation of similar types (think of builder pattern for example) and it's a hassle!
@Nenad_bZmaj
@Nenad_bZmaj 3 ай бұрын
In Go, you can embed struct as a struct field: type( UserData struct { ID string somethinElse int } User struct { name string email string phone string otherData UserData } ) //In func : var ( usrDatas []UserData users []User ) //For index i: user, usrData := new(User), new(UserData) user.name = usrData.ID = user.otherData = usrData users = append(users, *user) usrDatas = append(usrDatas, *usrData) // //updating: users[i].otherData = usrDatas[i] You access users[i]'s ID by: users[i].otherData.ID
@svenyboyyt2304
@svenyboyyt2304 8 ай бұрын
I think you have to differentiate to errors in your code to errors from user errors, like a fetch failing. If my code doesn't work, I want it to throw. If a fetch returns a 400 because the user forgot to input their age, I want Go style errors.
@Luxalpa
@Luxalpa 6 ай бұрын
Exactly that, that's why I love Rusts error handling.
@LusidDreaming
@LusidDreaming 8 ай бұрын
I will say Omit type is nice for DTOs. Like I can say this DTO is the whole object except the DB generated ID, and now any time I modify the object my DTO mirrors it.
@mage3690
@mage3690 8 ай бұрын
Oh, _that's_ what that is? Just a slice of a struct? Why isn't that a thing?
@LusidDreaming
@LusidDreaming 8 ай бұрын
@@mage3690 the only thing that is a little frustrating is the type hint will always just show Omit instead of the whole object, but it really is a really convenient feature otherwise. And it makes refactoring things easier. When you update a class, you don't have to update all the partial DTOs and you don't even have to modify much code unless the code specifically access a field that was changed.
@kowalkem
@kowalkem 8 ай бұрын
Why not use struct embedding?
@minikame2272
@minikame2272 6 ай бұрын
I'm just saying this to be contrarian low key but if having the *option* for granular handling is what makes Go's approach so awesome: function jsonParse (input) { try { return [JSON.parse(input), null] } catch (e) { return [null, e] } } const [output, err] = jsonParse('{"abc": 4') console.log(output, err)
@mohammadhosseinroostaei8325
@mohammadhosseinroostaei8325 8 ай бұрын
You can do the same error handling in promise based situations in JavaScript (Typescript) as well: const res = await promise().catch(err => err) if (res instanceof Error) console.error(err)
@NuncNuncNuncNunc
@NuncNuncNuncNunc 8 ай бұрын
Errors are values but not the desired value so this sounds like a use case for Either. If you use Either and pattern match on the result you will always handle the error assuming unhandled cases are treated as errors.
@whoopsimsorry2546
@whoopsimsorry2546 8 ай бұрын
First thing I did when I was writing go was reinvent Result from rust into it. I see it as more like do it the way you like rather than something premade for you, they would have to implement 100 versions to satisfy everyone instead of just letting you pick out and implement a specific one to your liking. I wrap everything into my Result, takes 10 more characters and I've never crashed. That's the great thing about Errors as values, they can easily morph into anything else without much overhead.
@baobaobiz
@baobaobiz 6 ай бұрын
In practice, with golangci-lint (a huge collection of validation), I feel like Go's 'security' is pretty good, a weakness that people make comparing to Rust. I have a setup using Task (makefile in Go) that runs the whole suite of checks and output good code before commit. I feel the people often compare languages based on the 'out of factory, default' DX that they provide, which I think it's valid but also not practical, when serious project are a work of engineering system with carefully setup pipelines, no one just use the default language toolings itself in real project.
@chris-pee
@chris-pee 8 ай бұрын
Prime, I think your idea for a Zod competitor already exists. I recall 2 libraries that do what you want, one of which is "Typia", IIRC
@majorhumbert676
@majorhumbert676 8 ай бұрын
Exactly! I wanted to try out Typia myself. It's supposedly very fast. Though, I am not sure it's mature enough to use in a serious project.
@josefnymanmuller374
@josefnymanmuller374 8 ай бұрын
Your Zod competitor already exists, it's called Typia. It does types => validation, types => json schema, types => protobuff schemas.
@justsomerandomguyman
@justsomerandomguyman 8 ай бұрын
io-ts existed before both and did the same.
@RicardoValero95
@RicardoValero95 8 ай бұрын
I didn’t get point 8, how would you define in go for example User and UserWithId (or User and UserWithoutId)
@danko95bgd
@danko95bgd 8 ай бұрын
In go you should ideally embed smaller types into bigger types, basically compose them. say i have type username struct { name string } and type userid struct { id uuid } and then you define type user struct { userid, username, othercrap: here }. If you go from type with 20 stuff inside and you want type with 17 then yeah you have to do it manually or use a library that can do that.
@RicardoValero95
@RicardoValero95 8 ай бұрын
@@danko95bgd thanks 😊
@arnerademacker
@arnerademacker 8 ай бұрын
This was basically programming slander in all directions for like an hour and I love it
@ndrpeverelli
@ndrpeverelli 8 ай бұрын
I think that the 9 point of the list he intended the usage of $ref into the JSON file tò combine multiple jsons or to self reference some value. Btw never used go so idk if it handles it badly
@joaodiasconde
@joaodiasconde 8 ай бұрын
Errors by values is definitively the best. Rust does it better leveraging sum types to force engineers to handle the error to unwrap the value. I think what is also missing in Go is a sort of propagating the error up the callstack feature, like Rust's question mark operator. That allows the example of one mechanism to catch all and handle the same way. Also, yeah dead locking yourself could be argued as being a skill issue, but so could every C++ footgun and we still dunk on C++ for it... as an industry we need to push for languages with fewer footguns.
@dongueW
@dongueW 8 ай бұрын
Valid points!
@matheusjahnke8643
@matheusjahnke8643 6 ай бұрын
If not every, an overwhelming majority(like, 90% or more) of language disadvantages could be compensated with skill... so technically they are all skill issues.
@ferahl
@ferahl 8 ай бұрын
Yes but TS is more like Option|Result since the returned value can be the thing, or an error/undefined etc. And TS will error if you try to operate on that returned value without first narrowing the type down to the thing (i.e. check if it's an error or undefined etc). So it's actually safer and forces proper error checking.
@bryanleebmy
@bryanleebmy 7 ай бұрын
TS has error throwing, which just sucks. There's also no `Option | Result` built into TS, and if you pick any one of the "Rust-like" error handling libraries on npm, you're locked into that one library and you have to write wrappers for every other library you use because they're all incompatible. And every single one of those libraries introduces a runtime overhead for every Result / Option they return, since you have to create a new object for each return. Returning `Error` is about the closest thing you can get that's natively supported, but again there's no standard error handling pattern in TS, so different dependencies will use different patterns. Go is infinitely better on that regard, and improvements can be made to the language server to check mutually exclusive access to either `res` or `err`.
@kubre
@kubre 8 ай бұрын
32 best reasons to develop depression
@LHMATIAS
@LHMATIAS 8 ай бұрын
at 14:47 I did not understand the idea. Someone can help me to understand what he said?
@bilbobeutlin3405
@bilbobeutlin3405 8 ай бұрын
What watch is Melkey wearing?
@ShawnPMurphy8
@ShawnPMurphy8 7 ай бұрын
Ok I have tried and tried to figure out what the actual problem is with the CrappyUnion complaint around 17 minutes in. Can someone please enlighten me? IMO it does precisely what I would expect. The parameter of the function takes in an array of type CrappyUnion which means the array can be a mix of strings and numbers or all strings or all numbers. You are guaranteeing nothing other than the fact the array has to be made of items that are either a string or a number. So when you then pass in “a” to the function, it is an array of all strings…. that satisfies the requirement for the parameter type of CrappyUnion[]… so what is the problem? Can it be a little weird working with an array like that? Yes I agree, but that is more of an implementation/design issue than a TS Type system issue. That example also isn’t really practical IMO having a parameter with an array type of string or number but then all you do is push a number to it. In that simple scenario the issue is the parameter should just be number[] given that is all the function needs. And yes if you added another push of a string in the function you could say now it needs the union type of string | number for the array but I would argue that is just poor design then. First off to me this scenario would be a bit of a code smell as a mutability issue passing that string array in like that to a void function without a return. I think a more typical realistic pattern would be setting a = to return of the function which at that point then it would indeed give you a type error because it would know “a” is a string[] but the return of the function would be a (string | number)[] … OR if just using the specific simple example and it returned the array after just pushing a number, it would return number[] which would obviously also cause an error during compile / transpile. TLDR: to me that is a bad implementation example along with the fact mutating an array with a void function is an anti pattern in my opinion 🤷🏻‍♂️ This is kind of like the parseInt() example later in the video where yes you can create some weird scenarios to prove a point but it shouldn’t be used as a qualifier for whether a language feature is good or not when in reality it is more of a quark or idiosyncrasy than a bug or bad feature. But I would love it if someone enlightened me if I am just wrong or missing something?! 🤷🏻‍♂️
@ShawnPMurphy8
@ShawnPMurphy8 7 ай бұрын
Typed this original comment on my phone yesterday which is why no real code examples and potentially was a bit confusing, but ultimately here is my point... this is the way I would write this code in the first place (assuming it was a legit use case / example) given the function will be mutating the "a" array. You will then get a TS Type error: ```ts type CrappyUnion = string | number; let a: string[] = []; function addToCrappyUnion(b: CrappyUnion[]) { b.push(123); return b; } a = addToCrappyUnion(a); // TS Error: Type 'CrappyUnion[]' is not assignable to type 'string[]' ```
@Fan_of_Ado
@Fan_of_Ado 8 ай бұрын
I've had to write some TypeScript this week despite being someone who usually only does Go. TypeScript was pleasant BUT WTF is the difference between cjs, node, esm2014,esm2020 and on and on. The tooling also sucks. `tsc` for some reason doesn't handle imports correctly and I had to use esbuild to bundle stuff then use tsc just for the d.ts type declarations. I could probably spend a month learning how to use it "properly" but why must it be so painful? I tried bun. It was great except for the fact that the cryptography implementation is incomplete and thus I can't use `bun build`. It's meant to be a simple npm library. It shouldn't take this much effort.
@jhonyhndoea
@jhonyhndoea 8 ай бұрын
true. the ecosystem sucks. you can give Deno a shot, my favorite so far.
@oserodal2702
@oserodal2702 8 ай бұрын
Welcome to the Javascript ecosystem.
@Fan_of_Ado
@Fan_of_Ado 8 ай бұрын
The bun developers are VERY helpful. They solved my issues with their crypto implementation in an hour
@Dipj01
@Dipj01 8 ай бұрын
Almost everything has to be convoluted in javascript. Almost everything.
@buc991
@buc991 8 ай бұрын
It’s not much effort just ppl trying to use stuff without learning anything about it first. Oh JavaScript have versions oh noo so hard 😮😂
@ShadoFXPerino
@ShadoFXPerino 8 ай бұрын
25:30 * is a dangerously leaky abstraction. Option and ? are less leaky.
@ameer6168
@ameer6168 8 ай бұрын
we have to write 2x more code to make typescript type safe
@thepotatokitty
@thepotatokitty 8 ай бұрын
Composition, just create a new struct with those 3 fields and then embed that in the structs which need the common fields.
@flyingmadpakke
@flyingmadpakke 8 ай бұрын
But programmers are lazy, we don't want to use two dots to access a nested object property :)
@thepotatokitty
@thepotatokitty 8 ай бұрын
Skill issue. You can embed a struct and it will inherit all the properties and you won't have to use the dots.
@flyingmadpakke
@flyingmadpakke 8 ай бұрын
Didn't know that is a specific GO thing. I thought you were referring to TS Omit.
@Friskni
@Friskni 7 ай бұрын
isnt your zod alternative just ajv?
@oakley6889
@oakley6889 8 ай бұрын
People taking about elixir are actually dead on, kinda insane how much it taught me about alot of these areas
@ShadoFXPerino
@ShadoFXPerino 8 ай бұрын
Try catch is desired because solving all your problems at one place is a ludicrously attractive proposition. The bigger the problem space, the more attractive it becomes.
@emeraldbonsai
@emeraldbonsai 8 ай бұрын
hearing how go handles errors and i realize thats exactly what i use rust for i just use match to then set a variable to a err json output XD
@christian15213
@christian15213 4 ай бұрын
there is definitely overloading in JS/TS. this helps with variations of the function
@CTimmerman
@CTimmerman 6 ай бұрын
The benefit of try catch is that you don't have to repeat the catch block after every statement.
@user-xw5tj4cb8x
@user-xw5tj4cb8x 3 ай бұрын
at 17:21 typescript does give you an error, idk if your compiler or ide is configured correctly
@jerichaux9219
@jerichaux9219 3 ай бұрын
I was able to execute this without receiving either error or warning.
@joyride9998
@joyride9998 3 ай бұрын
13:00 that's not really true... you can have similar construct as try catch also in go : func HandlePanic() { r := recover() if r != nil { fmt.Println("RECOVER", r) } } func divide(divisor int, divider int) { defer HandlePanic() if divisor < divider { panic("start is greater than end") } else { fmt.Println(divisor / divider) } }
@S4ntia60
@S4ntia60 6 ай бұрын
The definition of error handling used by both parts is different. Some languages force you to make a decision by the type in hand, and there is where the error Handling needs to happen. It's a systematic approach. Making a check of a result type in an if statement feels like calling a programmer logic part of the feature set of the language
@FrankJonen
@FrankJonen 6 ай бұрын
How do you ship a TypeScript binary?
@unicodefox
@unicodefox 6 ай бұрын
I think my main problem with the error handling that Go uses, as opposed to try catch statements is, (as someone who hasn't wrote code in a language that uses that), try catches fail closed. for example, you have this code: (written in js/express because thats what I know 🤷) router.post("/user/:id/update", (req,res) => { let validated = validateUserUpdate(req.body) // returns the new data if correct, throws if not. db.updateUser(userId, validated) }) If you forget to catch that error in a environment like TS,C#,Python, etc etc, that DB update will never happen, and will be caught by say, the http framework, or in the worst case, crash the app, but the integrity of the data is always maintained. In a environment like Go, where you're free to just run past the error, there's a chance that you're going to end up wiping out that user's data.
@Nenad_bZmaj
@Nenad_bZmaj 3 ай бұрын
I guess you just have to make a habit to always call db.updateUser (or equivalent in Go) within if err == nil block, or always after the if err != nil block.
@darvoid
@darvoid 6 ай бұрын
JSON thingy hint: use yaml string tags `yaml:",inline"` and you never miss a object key :'D and you can use yaml tags for json xD (I kinda find this silly xD but works)
@kyleshrader9053
@kyleshrader9053 4 ай бұрын
Have you put together your solution for typechecking?
@soggy_dev
@soggy_dev 8 ай бұрын
Very much on the go team. Just wanted to point out that function overloading is absolutely a thing in TypeScript and I'm fairly certain it actually came from JavaScript. Been writing odin recently, and their approach to overloading has been super convenient and I kind of wish go had it
@majorhumbert676
@majorhumbert676 8 ай бұрын
Overloading is completely unnecessary. Just create two different functions.
@Gusto20000
@Gusto20000 7 ай бұрын
#define true false 😂
@defnlife1683
@defnlife1683 8 ай бұрын
Help me Prime. I started learning Go, went into Rob Pyke’s history and then ended up in Plan 9 docs and writing drivers. Halp!
@iamvalenci4
@iamvalenci4 8 ай бұрын
You're seeing the chat displayed twice. If you'd like to monitor what the user is saying, consider using a separate screen, such as your phone, to keep track of the chat. The current setup may appear a bit chaotic, like a mixed fruit salad.
@LuNemec
@LuNemec 7 ай бұрын
On point 7] although I understand that in TS it is "native" and easy to iterate over object attributes, I think the complaint that in Go you need to use reflect is invalid. That is what reflect is for. Runtime introspection. Usage of reflect is the correct answer, but it would be nicer if these would be first class citizen. Although, when you think about it, after over 10 years of working with Go, I had this problem maybe once. But it depeds what software you work on.
@vedantmatanhelia1016
@vedantmatanhelia1016 5 ай бұрын
With reference to point 8 can't u just make a var struct (temporary struct) that contains the filtered fields and paase that around
@nikitaproit
@nikitaproit 8 ай бұрын
Node js has atomic operations. But you must implement mutexes and atomic types yourself. This is definitely a skill issue.
@Slashx92
@Slashx92 8 ай бұрын
I bet a gazillion dollars that prime also watches fireship in his free time
@ahsanghalib
@ahsanghalib 7 ай бұрын
I don't get why typescript crapy union example @17:30. you have converted it to array to accept the array. but it won't accept other then string or number array. why its wrong ???
@jerichaux9219
@jerichaux9219 3 ай бұрын
type StrNum = string | number; const strArr: string[] = []; function addToArray(arr: StrNum[]): void { arr.push(1); } addToArray(strArr); console.log(strArr[0]); // 1 console.log(typeof strArr[0]); // "number" Executing this code takes strArr (an array of strings), and passes it to function "addToArray", which accepts an array of union type StrNum (string or number). addToArray then pushes a number value into the received array. The problem is that we have passed in an array strictly typed as an array of strings, yet TypeScript still allows us to push a number value into the array, which should ONLY allow strings to be pushed. This behavior is NOT typesafe, as there should be no way to insert a number value into a string array.
Stop Creating Microservices | Prime Reacts
33:35
ThePrimeTime
Рет қаралды 200 М.
Rust vs Go : Hands On Comparison
50:40
ThePrimeTime
Рет қаралды 202 М.
когда одна дома // EVA mash
00:51
EVA mash
Рет қаралды 13 МЛН
How To Choose Ramen Date Night 🍜
00:58
Jojo Sim
Рет қаралды 61 МЛН
Зу-зу Күлпәш. Стоп. (1-бөлім)
52:33
ASTANATV Movie
Рет қаралды 1,2 МЛН
Who Will Eat The Porridge First The Cockroach Or Me? 👧vs🪳
00:26
Giggle Jiggle
Рет қаралды 18 МЛН
Next Generation TypeScript | Prime Reacts
24:45
ThePrimeTime
Рет қаралды 93 М.
Migration Lesson: Don't Use Prisma | Prime Reacts
29:16
ThePrimeTime
Рет қаралды 142 М.
Why I Quit Netflix
7:11
ThePrimeagen
Рет қаралды 476 М.
Rust for TypeScript devs : Borrow Checker
8:49
ThePrimeagen
Рет қаралды 210 М.
[UPDATE] Mojo Is Faster Than Rust - Mojo Explains More
52:09
ThePrimeTime
Рет қаралды 227 М.
Git Is Awful | Prime Reacts
23:10
ThePrimeTime
Рет қаралды 192 М.
They got away with this??
1:21:04
ThePrimeTime
Рет қаралды 1,1 МЛН
How GO Was Created - Less Is More | Prime Reacts
28:15
ThePrimeTime
Рет қаралды 126 М.
Goroutines ARE USELESS
12:57
ThePrimeTime
Рет қаралды 80 М.
Wow AirPods
0:17
ARGEN
Рет қаралды 1 МЛН
Теперь это его телефон
0:21
Хорошие Новости
Рет қаралды 1,6 МЛН
Как я сделал домашний кинотеатр
0:41
RICARDO
Рет қаралды 1,4 МЛН
Apple watch hidden camera
0:34
_vector_
Рет қаралды 34 МЛН