Тёмный

32 Reasons WHY TS IS BETTER Than Go 

ThePrimeTime
Подписаться 591 тыс.
Просмотров 250 тыс.
50% 1

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/dee...

Опубликовано:

 

28 сен 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 559   
@roccociccone597
@roccociccone597 Год назад
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 Год назад
No immutable variables tho. Tf is up with that
@roccociccone597
@roccociccone597 Год назад
@@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 Год назад
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 Год назад
​@@gilbertovampre9494how Go style different from x language?
@gilbertovampre9494
@gilbertovampre9494 Год назад
@@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.
@ntrrg
@ntrrg Год назад
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 Год назад
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 Год назад
@@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 7 месяцев назад
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.
@Daniel_Zhu_a6f
@Daniel_Zhu_a6f Год назад
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
@MassimoLuna-o4r
@MassimoLuna-o4r 3 месяца назад
I love getting a new perspective on things, although I don't think you are always right about everything. I feel like it takes great courage to stand in front of this many people and state you opinion and I admire you for it. - No matter if it is factual or aligns with my views. Thank you. Keep it up :)
@oakley6889
@oakley6889 Год назад
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 Год назад
The only thing function overloading is good at is making the code more confusing, change my mind!
@Ryuuzaki145
@Ryuuzaki145 Год назад
​@@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 Год назад
​@@tokiomutex4148and they cause name mangling...
@edoga-hf1dp
@edoga-hf1dp Год назад
Function overloading can be good for optional arguments or handling of same functionality for different types
@tokiomutex4148
@tokiomutex4148 Год назад
@@edoga-hf1dp Until someone modifies the code and a different definition of your function ends up called, good luck debugging it!
@davidsaint8866
@davidsaint8866 9 месяцев назад
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.
@Nenad_bZmaj
@Nenad_bZmaj 7 месяцев назад
#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.
@josefnymanmuller374
@josefnymanmuller374 Год назад
Your Zod competitor already exists, it's called Typia. It does types => validation, types => json schema, types => protobuff schemas.
@justsomerandomguyman
@justsomerandomguyman Год назад
io-ts existed before both and did the same.
@huge_letters
@huge_letters Год назад
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.
@huge_letters
@huge_letters Год назад
@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.
@joaodiasconde
@joaodiasconde Год назад
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 Год назад
Valid points!
@matheusjahnke8643
@matheusjahnke8643 10 месяцев назад
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.
@nexovec
@nexovec 4 месяца назад
OP: "Why can't you be like typescript?" Go: "I'm sorry, dad"
@kowalkem
@kowalkem Год назад
Guy must've gotten oat milk instead of soy.
@MrToup
@MrToup 10 месяцев назад
I really like when you take a really small snippet to explain your point. Would love to see more.
@oakley6889
@oakley6889 Год назад
People taking about elixir are actually dead on, kinda insane how much it taught me about alot of these areas
@christian15213
@christian15213 8 месяцев назад
there is definitely overloading in JS/TS. this helps with variations of the function
@mattymerr701
@mattymerr701 Год назад
Constructor overloading != function overloading. And function overloading can be generics via syntax sugar.
@ShadoFXPerino
@ShadoFXPerino Год назад
25:30 * is a dangerously leaky abstraction. Option and ? are less leaky.
@arnerademacker
@arnerademacker Год назад
This was basically programming slander in all directions for like an hour and I love it
@trapexit
@trapexit Год назад
@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.
@00jknight
@00jknight 9 месяцев назад
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.
@christian15213
@christian15213 8 месяцев назад
Agree, there are pros and cons for both languages. You can do functional programming in TS and vice versa in GO.
@TahirDibirovII
@TahirDibirovII 28 дней назад
All we need is seperate AOT to machine code compiled engine for TS. Someone please invent this shit!
@joyride9998
@joyride9998 7 месяцев назад
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) } }
@darvoid
@darvoid 11 месяцев назад
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)
@kahnfatman
@kahnfatman 11 месяцев назад
The TS guy has not been thru hell -- he thought Satan is throwing him a party there. The only inheritance you may desire is that which from your great grandpa: The clock. But if you love your great grandma, you would rather borrow his books in your composition :D
@kakwa
@kakwa 11 месяцев назад
1 reason why a balance article is better than any article entitled "N reasons why X is better than Y".
@baobaobiz
@baobaobiz 10 месяцев назад
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.
@JOHN-um2
@JOHN-um2 Год назад
Point 9 is invalid since json you can make a new decoder that doesn’t allow unknown fields. Therefor catching your typo.
@NuncNuncNuncNunc
@NuncNuncNuncNunc Год назад
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.
@soggy_dev
@soggy_dev Год назад
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 Год назад
Overloading is completely unnecessary. Just create two different functions.
@Gusto20000
@Gusto20000 Год назад
#define true false 😂
@waffles3782
@waffles3782 Год назад
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 10 месяцев назад
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 7 месяцев назад
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
@mage3690
@mage3690 Год назад
What's not to like about Go? The colon-equals? Fair enough, I don't like that either. That's a whole extra two keypresses every time I set a variable. No ternary operators is a _good_ thing. If you're stacking ifs that deep, just use an if statement to set a variable that you can use as an rvalue in the next if. My first officially taught programming language in tech school was ladder logic, a dataflow language. I was always trying to stuff more logic into every box (or rung, because ladder logic is primarily written in rungs). I'd ask my prof how to stuff more logic onto a rung, he'd come over, stare at my colossal mess with an expression of horror and confusion, and tell me "if it's that complicated, set a variable." Naturally I didn't want to, stuffing a procedural mindset into a dataflow language is an exercise in futility, but it taught me to seriously think about why I needed that much logic, and to make my code more readable. If there's one language that will make the most trivial code unreadable if you're trying to do it wrong, it's ladder logic.
@justsomerandomguyman
@justsomerandomguyman Год назад
Nah, you should research the difference between expressions and statements and try to better understand how expression oriented programming is better.
@mage3690
@mage3690 Год назад
@@justsomerandomguyman just because you want to use functional programming for concurrency doesn't mean you can't use imperative for creating memory. Matter of fact, I think programming in general would go so much better if everyone just did that: imperatively create all the memory you need, then functionally edit that memory as inputs come in. Let each tool do the thing it's good at without being dogmatic. Also, the idea that somehow an extra colon in my variable initialization makes a language better is just goofy to me. I guarantee you the compiler could trivially know where that colon should go even if I never specified it. Unless you're shadowing a variable, there's no point. And if you are, well, IMHO that's bad practice anyways: the language should just assume scopes inherit everything or nothing from the scope above them and go with that. In this one area, be more like PHP. Assume nothing, at least for function scopes, and force programmers to declare side effects.
@w1-w2-w3
@w1-w2-w3 29 дней назад
I don't know who other guy is but he didn't have his own judgements. Every time Prime said something, his brain turn off and start agreed everything. Lack of confidence. LOL
@nenadvicentic
@nenadvicentic 9 месяцев назад
You guys completely missed the point about difference in exceptions in Go and TypeScript. Errors in Go do not stop program execution, which is completely crazy. That is THE difference. In any normal/sane language errors stop the execution. In TypeScript, as an example of such language, you put try/catch when you have "expected exception" and want to continue execution, which is fairly rare case (>5%?). While in Go, in order to stop execution, which is 95+% situations, you have to handle it manually. And people who are writing try/catch blocks all over the place... they are doing it wrong way.
@ThePrimeTimeagen
@ThePrimeTimeagen 9 месяцев назад
Simply disagree Errors are values
@nenadvicentic
@nenadvicentic 9 месяцев назад
@@ThePrimeTimeagen And when your function returns int 0, because of an error, you code should simply continue running and threat your 0 as result from calculation?
@Nenad_bZmaj
@Nenad_bZmaj 7 месяцев назад
@@nenadvicentic Errors are not some random thing, they have causes which you, as the code author, must be able to anticipate and handle in advance. Errors in calculation are not acceptable. You'll discover bugs by testing, bugs are not errors. Aborting is not graceful. Warning the client side and leaving them options to change parameters or exit, is.
@nenadvicentic
@nenadvicentic 7 месяцев назад
​@@Nenad_bZmaj Half of your reply is stating exactly what I am saying and other half is contradicting it. Errors can be expected (once you can anticipate) and unexpected (e.g. random hardware or network failure). Do you think your code should "continue on unexpected error" by default? I think it should throw by default. And BUBBLE. And if you want to provide user with options after error, you do try/catch on top, user interaction level. Not on every intermediate level, just to re-throw it up. That is anti-pattern and that is what Primeagen constantly throws in as an argument against try/catch. Regarding calculation, parts of data you calculate on, or pre-calculated partial, come from different data sources or a different server. What if IO fails while reading the subset of the data? You catch that with unit-tests? You "continue by default" defaulting, let's say `int` to default 0? This is an argument to say that in 90%+ of use-cases we want code/runtime to throw on unexpected error, not to continue. Therefore, language/runtime defaults should cover 90% use-case, not 10% use-case.
@Nenad_bZmaj
@Nenad_bZmaj 7 месяцев назад
@@nenadvicentic To be honest, I have zero experience in any language other than Go, but I very much like the way I can handle errors in Go, because I feel I am in full control and there is no magic or black box that I have to rely upon. In your example, one should always anticipate reading failure. Each os or io function returns errors as values and they should be called that way. Your function that calls reading a file should not abort the whole application, but back propagate the error to the caller. It is up to the overall design at which level the caller decides what to do with that error, say, request data to be sent again before proceeding with calculations. You know what data structure you expect and the nature of the data, so you can also check the data integrity (in case reading was successful) and your function that does this check should return error as value. But even in the case you mentioned, unsuccessful read will not generate zeros in place of missing data - there will be no bytes at that place (you'll also get the returned number of bytes read). So, if you decide to not handle that error, in the next step, when accessing that missing spot, you'll get panic anyway, so the program does abort. I just don't like that, so I'd handle panic as well at some higher caller level to be able to finish gracefully. To be more precise: you have a slice of int32 and it holds N elements, so you expect to read 4*N bytes. But the read was unsuccessful and only 12 bytes were read. What you were saying is that only first 3 ints were populated but the rest remain zeros and the program continues. But that is not true. You have to have a function that converts bytes to int32 and that function ranges through the slice of int32. When it comes to index 3 it wants to access the byte slice at offset: 3*4 , i.e. the 13th byte. But there is no 13th byte in that slice, so program panics with "out of range" if you chose to ignore the reading error.
@Fan_of_Ado
@Fan_of_Ado Год назад
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 Год назад
true. the ecosystem sucks. you can give Deno a shot, my favorite so far.
@oserodal2702
@oserodal2702 Год назад
Welcome to the Javascript ecosystem.
@Fan_of_Ado
@Fan_of_Ado Год назад
The bun developers are VERY helpful. They solved my issues with their crypto implementation in an hour
@Dipj01
@Dipj01 Год назад
Almost everything has to be convoluted in javascript. Almost everything.
@buc991
@buc991 Год назад
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 😮😂
@shariel9731
@shariel9731 Год назад
Typescript is good for small projects. But after working on a larger scale project. HELLLL NAAHHH, never again...
@emeraldbonsai
@emeraldbonsai Год назад
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
@dryr-mp4pp
@dryr-mp4pp Год назад
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 Год назад
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 Год назад
The difference is that Scala is half decent.
@anon-fz2bo
@anon-fz2bo Год назад
​@@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 Год назад
@@anon-fz2bo I wholeheartedly agree. Go's lack of a truly generic enum type is one of its sore spots.
@PamellaCardoso-pp5tr
@PamellaCardoso-pp5tr 2 месяца назад
The whole thing about optional type is you staying inside the Maybe/Option monad and delegating the error handling to the monadic structure. No need for a enum or some shit like that, thats just a neat sprinkle on top of your chocolate milk, but the chocolate milk itself doesnt need it to be delicious.
@vitiok78
@vitiok78 Год назад
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 Год назад
Doesnt it give you inspiration. Anyone (with the right connections) can become a journalist these days
@gmdias0_
@gmdias0_ Год назад
makes sense
@anon-fz2bo
@anon-fz2bo Год назад
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 Год назад
@@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
@voskresenie-
@voskresenie- 23 дня назад
I've worked with so many of these people when a company I used to work at adopted go. Not only were people not writing idiomatic go, they couldn't even be consistent about what language they _were_ writing via go - java, C++, python, and others. It was a nightmare for the few of us who actually had learned go properly and weren't just angry at the language over it not being a different language.
@bitmasked
@bitmasked Год назад
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 Год назад
i hate exception handling with try catch
@OnFireByte
@OnFireByte Год назад
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 Год назад
@@ThePrimeTimeagen thoughts on elixir/erlang error handling?
@jarvenpaajani8105
@jarvenpaajani8105 Год назад
​@@ThePrimeTimeagen except in zig
@KevinCaffrey
@KevinCaffrey Год назад
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.
@Speykious
@Speykious Год назад
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 Год назад
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 Год назад
​@@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 Год назад
"as a ___" why do people feel the need to state they are writing as something or other? Is it just readit brain?
@deformercr6680
@deformercr6680 Год назад
​@@johnyewtube2286it helps the reader gain perspective about where someone might be coming from.
@SimonBuchanNz
@SimonBuchanNz Год назад
​@@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"
@kidus_f1
@kidus_f1 Год назад
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
@Kane0123
@Kane0123 Год назад
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 Год назад
An absolute beauty. Best of both worlds
@ejazahmed4609
@ejazahmed4609 Год назад
He seems like a junior in comparison. I don't know about his qualification but that's the impression I get.
@antonpieper
@antonpieper Год назад
Can you elaborate on the Theo-Prime scale?
@orelweinstock
@orelweinstock Год назад
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 Год назад
Actaully a good comparison
@PhatPazzo
@PhatPazzo Год назад
Come on… try/catch is the worst, but golang error handling is still not “beautiful”. Please correct me if I’m wrong, but if you ignored the error on line 49 (12:24), go doesn’t catch that without a linter, right? And about readability, there are five statements there totaling 18 lines, that kind of error handling completely throws code overview out the window. In a world where we have algebraic data types such as Result and Maybe/Option, the solution in golang is at best acceptable, but absolutely not beautiful…
@TheCalcaholic
@TheCalcaholic Год назад
Like everything in go, it's not beautiful, it's not the most readable, but it's robust and functional. I much prefer the style of rust over go and I'm kinda undecided whether I like Java's or go's error handling better (at least, both are explicit). But I think we can all agree, that error handling in JS/TS is a pain in the ass. In go, while you can ignore an error, you know that you are doing it (because you need to use a placeholder for the error result explicitly)
@jonasstrmsodd6352
@jonasstrmsodd6352 Год назад
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 Год назад
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.
@sinom
@sinom Год назад
Golang's value errors would be nicer or they instead were some result return type with monadic operations on it
@Entropy67
@Entropy67 Год назад
Agree but you get some interesting freedom with what it is right now 🤔
@Qrzychu92
@Qrzychu92 Год назад
​@@Entropy67you don't have to use the monadic things everywhere
@OzzyTheGiant
@OzzyTheGiant Год назад
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
@iojourny
@iojourny Год назад
Holy shit, 1 hour. Lets go
@avi7278
@avi7278 Год назад
yeah let's go. what your name?
@911Archie
@911Archie 6 месяцев назад
Actually in go this is how you say you implement an interface: var _ Interface = (*MyStruct)(nil) and then it's checked at compile time
@chrism3790
@chrism3790 Год назад
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 Год назад
I'd rather the program fail than clobber itself or anything else
@zhamed9587
@zhamed9587 Год назад
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 11 месяцев назад
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.
@refusalspam
@refusalspam 4 месяца назад
Why not use Checked Exceptions like in Java. If they made it so that you had to either eat the exception or declare that your function also throws it, then the compiler can always inform you if you missed handling any error.
@chrism3790
@chrism3790 4 месяца назад
@@refusalspam Yep, many languages have this. Rust, for example.
@svenyboyyt2304
@svenyboyyt2304 Год назад
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 10 месяцев назад
Exactly that, that's why I love Rusts error handling.
@neociber24
@neociber24 Год назад
TS is just JS, just fancier. The real question, what is the best type system? TS, Go, Rust, Haskell, Kotlin, ...?
@adamsribz
@adamsribz 11 месяцев назад
Bro the CaPiTaLIZAtion thing is great. I hate having to write public on every single var to to export it
@nodidog
@nodidog Год назад
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 😂
@robfielding8566
@robfielding8566 10 месяцев назад
what you really want is to explicitly handle all errors that are the result of a bad input, and a 4xx in all such cases. a try/catch or a panic/recover are only to handle something that got missed, that is presumed to be a coding bug as 5xx. the try/catch or panic/recover is a fault barrier. each thread should have a fault barrier at the top if it doesn't continue with a new session; or in the top-most loop as the fault barrier. fault barriers log things that got missed. reaching the fault barrier IS a bug. you can't always recover for real though. "out of filehandles", and your process can't safely proceed with anything.
@robfielding8566
@robfielding8566 10 месяцев назад
the main thing that IS wrong with Go error handling: returning 'error' isn't specific enough. You should return the most specific type you can that has the error interface. ie: ex FileNotFound ... ex.FileName. If you are in the middle of doing a task, then that task's error should get returned. If it was caused by an error inside of that task, then that error should be used to construct that task's error. That way, you get context about what you were DOING when it errored out. It is pretty important that the task know what HTTP error code to suggest. You should return 4XX errors on bad input, and 5XX on errors deemed to be bugs to be fixed if your own code. This is why it's a bug to hit the top-most fault-barriers. It means that you missed something that was bad input, or something that could have gone wrong internally. You need to update your code so that all errors can tell you definitively whether fault lies outside the process, or inside the process.
@nandomax3
@nandomax3 Год назад
Nil pointer blowing up in production reminds me of Java NPE. The problem here is a skill issue, learn better your language and code around possible nil pointers
@LusidDreaming
@LusidDreaming Год назад
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 Год назад
by the same token, indexing a list with a variable is also a vulnerability, isn't it?
@LusidDreaming
@LusidDreaming Год назад
@@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
@TremereTT
@TremereTT 9 месяцев назад
I only like Try Catch Finally how it was inplemented in Java. And I hate java! Yet that was a thing they did right. The otherthing java did right is to put a monitor in every object, for easy threadsafety.
@tekhiun
@tekhiun Год назад
If you gonna use ParseInt and Number as example of bad behavior of JS you might as well scream that you don't read documentation instead. It's on the same level as people that complain that JS follows floating point standards thinking it's odd behavior on JS side. There are a lot of issues with JS ,like Prime showed with Json parse, but saying that the code doesn't follow your intuition is not one of them.
@LusidDreaming
@LusidDreaming Год назад
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 Год назад
This whole article is basically saying "I like dynamically typed languages"
@UxerUospr
@UxerUospr Год назад
Not just TS, but the JS frameworks and sundry other packages he must use. Apples != Oranges
@teejaded
@teejaded Год назад
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.
@yapet
@yapet Год назад
EDIT: I’ve written this comment before watching the vid completely. Prime does address the sum types in TS, rendering half of this comment honestly stupid. I see the point, but in the end, I do not agree with Prime’s point about unsoundness of ts unions. The is A LOT of ways to break soundness of TS type system, and the presented one is not the worst contender. I never ran into such case, probably because I avoid mutating stuff willy-nilly. Tho I’m not religious about it like at the church of holy haskell. I’m so tired of prime’s dogs**t take on typescript enums. I’m sure he gets this point a lot, but I’ll still reiterate. First of all, the keyword "enum" enums are bs. We can all agree, that those aren’t the best. They do get one thing going for them, if you want to name your ints (which may aid perf, but more on that later). Secondly, the way to do sum types (rust enums, ocaml/haskell variants, discriminated unions, etc.) is to declare a union. Union which you can descriminate cases in some way. The go-to way, is to have objects with "type" property of different literal values, aka: type A = { type: "foo", value: number } | { type: "bar", bazinga: string }. Unions are WAY more powerful feature than plain enums with associated values. But the power is in the ability for tsc to see through discrimintions. Aka, if with the previous type you write: if (a.type === "foo"), typescript will deduce the correct variant in the body. I'm sure we all know this trick. I'm sure Prime knows about it as well. I'm sure Prime used this as well. Then WHY are we still doggin' on TS type system? No-one cares about "enum" keyworded enums. It has sum types. And it is not just a gag. I see time and time again Prime presenting "lack of proper enums" (and by proper he means rust) as a serious downside of TS. TS has problems. JS has a lot. "Lack of rust enums" is not one of them. And about those "enum" perf improvements. Keyworded "enums", do have one thing going for them. They allow you to name integers in the type system. This does provide a form of documentation. If we are to use string literals (as everybody does nowadays) as a union tag, they are self-describing (type Tag = "case-foo" | "case-bar"), not ints unfourtunatelly (type Tag = 1 | 2). SMI’s can give you a bit of that sweet sweet performance oompf, if you use them instead of literal strings. SMIs pack better in arrays. You can do bit twiddling to pack multiple variants into a single SMI. Equality checking ints is a lot faster then strcmp-ing string. Although I speculate that using ints vs strings as a union tag isn't that impactful of a perf jump. Since all of the tag values are likely to be specified in code (not generated dynamically, recieved from the user, fetched from the network, etc.), they are interned strings (judging by the V8's string.h). If JIT is to learn the shape of those tag strings (it should be able to learn that strings in tag properties are always interned), doing the comparison then just equates to a single 64-bit word equality check (comparing if pointers are the same), just like eqality-checking SMIs. And since these are const strings, there shouldn't be any additional GC pressure. I might have missed the joke here, but I don't think it is one. I think that screaming "typescript enums are bad. just look how much they are better in rust" is misinformed and/or just ignorant. Yes, "enum" keyword kinda sucks. Yes, rust enums are a good way to model sum types. No, typescript HAS equivalent capabilities. Typescript allows for far better flexibility when it comes to declaring and using sum types. Thing that is genuinely missing when comparing to rust enums is the pattern matching + a presence of few exhastiveness checking bugs in tsc.
@justsomerandomguyman
@justsomerandomguyman Год назад
He doesn't really understand the differences between enums, unions, and sum types. It's just a fact. I'm guessing he doesn't have any experience with functional programming, and that's probably why he can only relate to Rust's enums and doesn't really see the bigger picture.
@R4ngeR4pidz
@R4ngeR4pidz Год назад
Hey! I'll have you know I like living under my stupid rock, thank you very much
@thinhle462
@thinhle462 Год назад
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
@keoghanwhimsically2268
@keoghanwhimsically2268 8 месяцев назад
10:02 ‘Error catching” is not “error handling”? That’s a … take. And, it’s not really a “skill issue” to have to check for possible exceptions on every call, especially when otherwise valid results can also be returned. It very quickly becomes a code clutter issue. Unnecessary cruft that makes it easier to lose the flow of the program. Plus, in languages with exception handling, it’s not uncommon to see novice programmers check for stuff they shouldn’t or in places they shouldn’t, creating similar problems of cruft. (This is not to say that exception handling cannot be abused or misused. There is no language feature immune to that fate.)
@keoghanwhimsically2268
@keoghanwhimsically2268 8 месяцев назад
Listening further, I do think there is some strawmanning going on here. Global exception handling is not the only alternative to handling all exceptional conditions at the point of the call. The whole point of out-of-band exception handling is that it allows you to decide the appropriate place to handle a particular exceptional condition. For CLI tools and unit tests, that may well be at the top level. But for complex services and applications, that may just be anywhere in the call stack at the point of the call return or above.
@SultanRehman
@SultanRehman Год назад
Oh, so now if Go adds an Option type, it will magically "remove all need for nil"? But not when other langs this dude dun like, like Java, do the same? And speaking of which why how come Go suddenly needs generics anyway? I thought the great Go lang designers didn't see a need? I thought all other langs are stupid and complicated. Go is simple, direct and pure? C;mon, hypocrisy much?
@majorhumbert676
@majorhumbert676 Год назад
Lol, I was also surprised to hear that Go now has generics. "Gophers" (or whatever they call themselves) have been telling me that the lack of generics is a selling point.
@synthatik
@synthatik 10 месяцев назад
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
@unowenwasholo
@unowenwasholo Год назад
ITT: Redditor works backwards from their opinion of enjoying writing TS more than Go. Bro, just say you like TS. It's okay to be a bad developer. I am, too-I write everything in TS. Just embrace it. If it means that you get the job done and push out that application, more power to you.
@nyahhbinghi
@nyahhbinghi 7 месяцев назад
Go is bad *BUT* receiver methods are great because (1) avoid need for `this` and (2) methods don't need to be bound to receiver, they are pre-bound
@nyahhbinghi
@nyahhbinghi 6 месяцев назад
yes
@yapet
@yapet Год назад
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 Год назад
This idea was already implemented. Look up "Typia"
@joseandkris
@joseandkris Год назад
Used both Go and TS. To me, Go wins cause of simplicity, yet it has a lot of power. Sure I miss the occasional ternery, but writing code, "it just works" more then TS
@LusidDreaming
@LusidDreaming Год назад
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 Год назад
Oh, _that's_ what that is? Just a slice of a struct? Why isn't that a thing?
@LusidDreaming
@LusidDreaming Год назад
@@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 Год назад
Why not use struct embedding?
@user-kw9cu
@user-kw9cu Год назад
I like simplicity of Go. You dont need to compile bizzlion types in your head like when yo do TS.
@GaryFerrao
@GaryFerrao 11 месяцев назад
Is this a moustache competition? 😂
@bcpeinhardt
@bcpeinhardt Год назад
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.
@maniacZesci
@maniacZesci 9 месяцев назад
Why do people always talk about Rust fanboys being a cult when Go fanboys are are actually that.
@ameer6168
@ameer6168 Год назад
we have to write 2x more code to make typescript type safe
@burdenedbyhope
@burdenedbyhope 11 месяцев назад
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.
@oninoni
@oninoni Год назад
As a C++ / Assembler / HDL Engineer: This is literally the programmer equivalent of First World Problems :D
@LuNemec
@LuNemec 11 месяцев назад
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.
@chris-pee
@chris-pee Год назад
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 Год назад
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.
@CheefCoach
@CheefCoach Год назад
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 Год назад
It helps to remember that append is “value semantics mutation API”.
@iamrafiqulislam
@iamrafiqulislam Год назад
TypeScript needs lots of Boilerplate codes without getting any runtime safety which is more crucial.
@blenderpanzi
@blenderpanzi Год назад
17:50 and its unnecessary! They could have made it so that you can't pass in a string[] as a CrappyUnion[] parameter, but do allow to pass in string[] as a ReadonlyArray parameter!
@nyahhbinghi
@nyahhbinghi 8 месяцев назад
Poor generics, Nil pointers, inherently unsafe in terms of threading
@nyahhbinghi
@nyahhbinghi 6 месяцев назад
3 bad things for sure
@manofqwerty
@manofqwerty 3 дня назад
We lazy error in Azure Functions a lot. Try catch generic exceptions on the main function, log the exception, cleanup and exit. This makes sense though because C#, like JS, can throw almost anywhere.
@kubre
@kubre Год назад
32 best reasons to develop depression
@redpillsatori3020
@redpillsatori3020 Год назад
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.
@defnlife1683
@defnlife1683 Год назад
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!
@ArgoArgus
@ArgoArgus Год назад
The argument on error handling is strange, with errors as values you have granular control for logging etc. but you can also handle the blanket case, you can literally do anything with errors as values. The main flaw with try catch in languages, are that error's can bubble up without making an explicit choice to do so. I have seen mutliple internal errors being exposed to the interface with other lanuages, with go exposing those are a choice and choices are powerful even when they are tedious.
@ArgoArgus
@ArgoArgus Год назад
The implicit interface implementation in go is also one of it's strongest suits. For example you could have a method that expects one interface and within that have control flow branches if that implements another specific interface (even if you don't know this at comp time, or if it can be statically checked), if you want to see the beauty of this in true action go have a look at the apiserver code for kubernetes, this also elegantly solves the struct key access in a very controlled fashion without having to use stringly typed code that is fragile and unpredictable, sure you have to define the accessor/mutation methods, you can access keys using reflection, however this is rarely done in golang as you typically would not code with that paradigm in mind. Another thing is that generics took forever to implement because they are really not necessary. The main issue I see in this whole article is that the OP see structs as classes. For the separation case just use composition properly. I agree with Melkey here, but would go further that you can not compare go to typescript at all in reality the paradigm and the mindshift needed for both are different, just because you understand the syntax and can use a keyboard doesn't mean you can code in a language. (Script kiddies be like : "I can code in every language because I can type.")
@nikitaproit
@nikitaproit Год назад
Node js has atomic operations. But you must implement mutexes and atomic types yourself. This is definitely a skill issue.
@rosehogenson1398
@rosehogenson1398 Год назад
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
@Nenad_bZmaj
@Nenad_bZmaj 7 месяцев назад
#3 - What is this, if not a "union type" : type Int interface { ~int | ~int32 | ~int64 | ~int16 } ? Like in (sorry, RU-vid sometimes doesn't allow links in comments): package main import "fmt" type ( // Type constraint Int interface { ~int | ~int32 | ~int64 | ~int16 } //generic type Slice[I Int] []I myType int16 myNewType int ) // method on generic type func (s Slice[I]) incrementBy(m I) { s[0] += m } func main() { var ( inc myType s Slice[myType] = make([]myType, 1, 1) a Slice[myNewType] ) s[0], inc = 5, 2 a = append(a, 10) s.incrementBy(inc) a.incrementBy(myNewType(inc)) fmt.Printf("s[0] = %d and is of type %T. ", s[0], s[0]) fmt.Printf("a[0] = %d and is of type %T. ", a[0], a[0]) } Output: s[0] = 7 and is of type main.myType. a[0] = 12 and is of type main.myNewType. #1 - I totally disagree with the nil pointer objection. Every pointer variable (e.g slice, map, function, interface, channel, pointer var to some other var) in Go gets a memory address. Only the value of that pointer var can be nil but the var itself can always be safely accessed. You cannot assign the memory address to a variable (&a = some pointer var is illegal), therefore you can never change it to nil. That is a big thing in Go. Executing a method on a slice or map that is empty is a matter of poor index (key) checking. You can run into that same problem in any language , when you try to access index 4 or larger in a 4 element slice. That's what checking for len is for. So, let's say you declared a slice or a map 'a' but forgot to initialize it, so it doesn't point to any memory. BTW you can initialize a slice either with make function or with append function (or with the literal). Before you try to access elements of the slice, check: if len(a) == 0 {return or whatever} or if len
@Warflay
@Warflay Год назад
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
@tesilab994
@tesilab994 3 месяца назад
Maybe programmers just need a little remedial training in how and where try catch is even needed. Either its bad because its excessively used, or its bad because it it isn't used. Simply put, layer the d--n code. If you provide an API, your implementations must catch all exceptions before they escape. If you to throw exceptions as part of your api--library api for example, rather than over the wire--then just ensure you are only throwing a limited set of documented exceptions that are part of YOUR API with well understood remedies.
@bobDotJS
@bobDotJS Год назад
Tldr; It's not typescript Typescript familiar Familiar good Go not typescript not familiar not good
@Nenad_bZmaj
@Nenad_bZmaj 7 месяцев назад
🤣
@lakelimbo
@lakelimbo Год назад
I went into that guy's profile, and pretty much all his arguments about everything are dramatic ad hominem, the only thing he replies is "you're a junior" and things like this, as if he wasn't, lol
@justsomerandomguyman
@justsomerandomguyman Год назад
I don't think either of you actually understand what sum types are. Your commentary on that point was pretty bad. Regular union types and sum types are 2 different things, and TypeScript has both. TypeScript calls sum types discriminated unions. Other languages call them tagged unions (Haskell), variants (OCaml), enums (Rust), etc.... In TypeScript, it's not quite as elegant as in a functional programming language with native support for Tagged Unions and pattern matching, but you have to remember TypeScript is bolted onto JavaScript. It can't just invent new language features from scratch. So, in order to support sum types, it requires you to introduce a discriminant property on the object, like `type` or `tag` which serves the same functionality as the type name (tag) itself in a language like Haskell, OCaml, or Rust. And, again, TS can't add real pattern matching to JS, but you can switch or if/else on the discriminant property to perform a poor man's version of pattern matching. In practice, it works out pretty well. Also, your comments about the regular union type no longer type checking don't really make sense. You declared the union is one type or the other and then you pushed one of the valid types into the array. There is nothing wrong with that. It would be the same with true sum types too. The whole point is that you aren't supposed to know what member of the union you have when you have a collection of a union/tagged union. This requires you to actually check to see what you have before doing anything important with the value. Honestly, this is pretty basic TypeScript. Anyone who has written TS for any reasonable amount of time should know this. Also, one more point. The non-tagged version of unions is indeed a controversial feature. It can be useful in moderation (particularly if you have a union of type-level string literals, for example), but languages like Haskell, OCaml, and F# don't support it, because not having tags makes type inference significantly harder. Still, people find it useful, and the Scala community found it useful enough to add it to Scala 3.
@keithjohnson6510
@keithjohnson6510 4 месяца назад
parseInt(0.00000005); I thought this was GO 'v' TS, not GO 'v' JS, so yes a bit of skill issue there, not knowing the difference.. :)
@ronniemagatti3342
@ronniemagatti3342 9 месяцев назад
23:48 this is just a feature of structural typing vs nominal typing. When you say "foo never implemented bar" that is not accurate; Foo has in fact implemented Bar as far as structural typing goes. If you change Foo's `bar` function to return a number instead of a string, you'll notice typescript then tells you `Argument of type 'Foo' is not assignable to parameter of type 'Bar'` because it's checking the _structure_, which in your example matches 1:1, not what you _nominally_ said it matches to. PS: this is not a diss at the other points in this video, really just hoping to clarify this particular point for viewers.
@gosnooky
@gosnooky Год назад
So basically this dude is trashing on Go because it's not TS and doesn't have the TS/Node ecosystem. This is a junior dev who's never written anything other than a NextJS app, and hasn't the ability to envision an application outside that space. His skill level is clearly lacking and has a one-dimensional view of software engineering, but talks like he understands certain concepts but doesn't really... not unlike those people you see commenting whom try to sound more intelligent by using "whom" instead of "who", but incorrectly.
Далее
The Truth About HTMX | Prime Reacts
49:56
Просмотров 372 тыс.
Does PHP Suck? | Prime React
29:56
Просмотров 153 тыс.
ТАРАКАН
00:38
Просмотров 531 тыс.
Golang is BAD for SMART PEOPLE
27:25
Просмотров 269 тыс.
Why I'm learning Go
21:35
Просмотров 66 тыс.
Rust vs Go : Hands On Comparison
50:40
Просмотров 226 тыс.
The Brutal Truth Behind Tech Layoffs | Prime Reacts
1:20:34
The Darkside of Software Engineering
30:43
Просмотров 172 тыс.
I'm Coming Around To Go...
21:33
Просмотров 115 тыс.