► Join my Discord community for free education 👉 discord.com/invite/bDy8t4b3Rz ► Learn how to become a Golang master 👉 fulltimegodev.com Thanks for watching
@joseburgosguntin Жыл бұрын
The length of the byte slice ( []byte ) does not contribute to the size of the User struct due to it's size, it will always be a 3 word data structure (in 64 bit systems, that means a total of 24 bytes). It will always be 3 words because golang has unified the types that rust would call the vector (Vec, as we know dynamically sized array stored in the heap) and the slice (&[T] a view). Meaning that it'll need to acomadate for the larger one of these, a vector needs 3 words (ptr, len, cap) and the slice only 2 (ptr, len). TL;DR a large array like [10000]byte would contribute to the size of the structure since it's stored right there in the struct, while a []byte only do 3 words (in 64 bit system usually 24 bytes), not matter what size it has.
@kruczek1986 Жыл бұрын
User will have the same size always, you have right. but i have question about this slice still... when you pass User (no pointer) this slice will be copied? but at the end this is reference so not should be a "problem", correct?
@joseburgosguntin Жыл бұрын
@@kruczek1986 No, it wouldn't be a "problem" in the sense that the bytes of the big file won't be copied (only the slice (ptr and len), like u said); but since this slice still points to the underlying file, be carful to not mutate it accidentally cuz it will change the contents of the file of the original User instance (and this could be bad because it could confuse most of the devs that'll use the function since mutations to a variable after passing it by value (a copy) into another function is pretty uncommon) Sidenote: if you do these five things in order you might get even more confused (this wouldn't happen in rust btw because you can't have a mutable borrow while having an imutable one at the same) 1. create a slice (a dynamically sized array) `slice_1 := []byte{1, 2, 3}` 2. create a slice (a view into the array) `slice_2 := slice_1[:]` or `slice_2 := slice_1 3. append to slice_1 `append(slice_1, 4)` 4. change the first element `slice_1[0] = 9` 5. print slice_1 and slice_2 and you'll get (sometimes) slice_1: [5, 2, 3, 4], slice_2: [1, 2, 3] this is happening because the the new element didn't fit in the original underlying array so a new one was created somewhere else, leaving the slice pointing to old one, and this only happens sometimes because if the original slice has enough capsity it'll just put it where you would expect it to
@3266711732665514 Жыл бұрын
Sure, he was wrong in this specific scenario, but if it was a large data structure the explanation still makes sense, I think that this was only him trying to come up with an example on the fly
@ricardor8044 Жыл бұрын
I love that you code stuff from zero to explain your concepts. It shows how good you understand of that subject
@lokthar6314 Жыл бұрын
You forgot to mention one big point about pointers: Escape Analysis. The moment you reference a pointer to something and move it beyond the function scope (e.g passing a reference to another function or having a pointer receiver) the Go Compiler is moving the data to the heap. Accessing data from the heap rather than from the stack can be around 100x - 1000x slower. func Foo(bar *string) {} // bar is moved to the heap, when accessing bar.ANYTHING, then the runtime has to follow the pointer address and do couple of memory operations func Foo(bar string){} // bar is in the function stack, runtime can access bar with o(1) operation You could avoid accessing the heap by making use of Golangs CPU inline caching, which requires you to make decisions about locality and temporality of your data and how you access it.
@anthonygg_ Жыл бұрын
Im learning each day. 🤝
@gearboxworks Жыл бұрын
@@anthonygg_ - yes, and also potential thrashing for garbage collection if a lot of heap is used and released, constantly.
@Davidlavieri Жыл бұрын
sharing pointers down typically remains on the stack, depending on what you do with the pointer, it may go on the heap, IIRC from this talk kzbin.info/www/bejne/kH69oXtqrrlqg5I
@lokthar6314 Жыл бұрын
@@Davidlavieri this is only the case if the compiler decides to inline though, on which you can't rely
@lokthar6314 Жыл бұрын
thanks for the great share@@Davidlavieri
@hamm8934 Жыл бұрын
Love the level of depth you explain at. You provide the “why”, not just the how. The use case is always the most important part and you make sure to always drill this home. Keep up the great content!
@shadyabhi9 ай бұрын
This video didn't answer the most basic question, "how big is big when the overhead of copying the whole struct is larger than garbage collection"? Also, garbage collection overhead is one of the biggest reasons when discussing this topic.
@ilambuduri4 ай бұрын
the size of a pointer is same for all data types, passing values into a function takes longer as data gets larger, so if structs for example are small size, use pass by value, otherwise use pointers, just dont do it all over the place, i have seen pointers used in IO, json marshall with interface, before we had generics. and ye pointers are not good for garbage collection, u make the job harder for GC with pointers.
@a0umАй бұрын
Also he gave the wrong idea mentioning string and byte slices as potentially “large objects”, when they’re actually just a pointer and an int under the hood.
@nas337 Жыл бұрын
Pretty simple explanation. Another possible reason to not use pointers is to reduce memory allocation in the heap. Allocation is not free operation and less memory allocation leads to less GC cycles. Coping the structure usually is not a problem because this memory will be allocated on stack frame and will be unloaded after function execution which not involve GC at all. Anthony thanks for the video. Now I am willing to watch a guide of zero allocation programs🙂
@ДмитрийКарпич6 ай бұрын
Hm, golang use two different strategy for heap/pointers with GC and stack/values cases with somthing different? Not get it why. I`m novice from JS-land, where all cleaned with one GC.
@akionka Жыл бұрын
8:55 string size is 16 (ptr+len) bytes, slice size is 24 (ptr+len+cap) byte so only these 16/24 bytes get copied, the actual underlying data is stored on the heap and is not copied
@anthonygg_ Жыл бұрын
Thanks you for this in depth explanation.
@ekadet Жыл бұрын
The presenter simply doesn't understand how the String type works
@demyk214 Жыл бұрын
Finally a youtube channel that gets to the point, u’d make a killer teacher btw.
@CodyDostal10 ай бұрын
Thank you! As someone who has used Python for many years, I’m finally leaning a new language and chose Go. So having to learn when to use pointers and get a better understanding of them has been hard. Your video really helped!
@SeanSmithPit Жыл бұрын
Great video! I appreciate how you were candid about your nil return, while not being strictly idiomatic is still a personal preference. Always nice to hear how other programmers think and what they find intuitive.
@freivincampbell11 ай бұрын
I am starting into this journey and I am very happy to found out your channel 🎉 thanks a lot … blessings from Costa Rica 🇨🇷
@anthonygg_11 ай бұрын
Thanks and the best of luck!
@silakanveli11 ай бұрын
One of the best explanation of why!
@goldilockszone4389 Жыл бұрын
I am starting on my Go journey and I so of the topic you are covering are no covered by anyone. I am glad you are doing a great job ! _Subed_
@siddhantkashyap5934 Жыл бұрын
No one can explain any better!!! Thank you!
@theedgardev10 ай бұрын
As always, what a great explanation Anthony. Keep posting valuable content!
@TheQxY Жыл бұрын
A few pointers (pun intended) for new users summarized: - Do not use getters if you don't need to obfuscate the field. Just make the field public. - Do not mix value and pointer receivers. - As a rule of thumb, start by writing your methods as value receivers. If you really need to be able to mutate the receiver, rewrite all methods to use pointer receivers. This will generally give you the best performance and clearest behaviour. - When in doubt, benchmark and test.
@ForeverZer0 Жыл бұрын
Genuine question: how does passing structs around by value offer better performance than pointers to them? I am somewhat new to Go (coming from C background), but this seems fundamentally incorrect for any struct that is larger than the machine's word size. I don't discount there might be some knowledge gap specific to how the Go compiler works, and perhaps there some automagic voodoo going on in this regard, but I don't understand how that would be the case, even in theory.
@TheQxY Жыл бұрын
@@ForeverZer0 Because the data pointers point to is stored on the heap. Small types (including small structs) are stored on the stack, making it potentially a good bit faster. You can verify this yourself with some simple benchmarks. I learned this from Jonathan Amsterdam, one of the leads of the Go team at Gophercon this year.
@TobiasSample Жыл бұрын
Are there drawbacks to mixing value and pointer receivers?
@DonFeedtehTroll Жыл бұрын
@@TobiasSample It creates problems with interfaces. An interface expects all receivers for the implemented methods to be of the same type. If you have an interface that has 2 or more methods, mixing pointers and value gives you errors.
@ja31ya Жыл бұрын
@@TheQxYI wish this kind of information was more readily available.
@christopherchalcraft1134 Жыл бұрын
Really love your style and pace of video. Great job.
@tpotjj2979 Жыл бұрын
Once again a valuable lesson!🙏
@yavener19 күн бұрын
Mb I'm a bit wrong, but I would start an explanation from the following point: when we call a function in Go all arguments are copied. So, if we pass user struct without pointer - we just send a copy of original user and modify this copy in function body without any impact to original one. But pointers will be just copied to function (8-byte numbers), so reference to original user's data will be available in functions body to manipulate it.
@future-jim Жыл бұрын
thanks for the pointers!
@nekoill Жыл бұрын
What a great channel, so happy I got it in my recommendations
@neufaldahouli2352 Жыл бұрын
You are great dude! Keep it up!
@mlemImlem4 ай бұрын
Very informative video, well explained.
@lorenzochukwuebukaobi8898 Жыл бұрын
Thank you so much for the explanation
@guidow961610 ай бұрын
Simple PassByReference vs PassByValue stuff. If you have an extension function on something without a pointer (u User) the user you use in that function is a copy of that original, and it's lifetime ends when the function ends. If you use that it would be better to return that user.
@dougsaylor6442 Жыл бұрын
This definitely trips up Go newbies. Good video! 😀
@dawnrazor Жыл бұрын
There are a couple of other issues when not using pointer receivers. 1) I read somewhere (i forget where) that for a particular type of object do not mix pointer and non pointer receivers, stick to either one or the other. The problem is most objects need to be able have some methods mutate state which means non pointer receivers are not appropriate. The other issue is lint errors. Even if it is valid to use a non pointer receiver but that object has many members, the linter will emit an error saying that what you’re doing is inefficient. For these reasons I rarely use non pointer receivers. But there is something else that troubles me about over using pointers and that is to do with escape analysis. Sometimes it is paradoxically more efficient to not use pointers because escape analysis is quicker. This is still an area I’m a bit hazy in so I need to do more research
@juicerAware7 ай бұрын
Great, Thanks for the informative video sir
@Drag0n_Master_6 ай бұрын
TL;DR: in GoLang function parameters passed by value by default
@Jimmy20011227 ай бұрын
great example of pointers, simplified with the state example
@kruczek1986 Жыл бұрын
nice! i have a question about struct if it is a service with some repository, validators etc, you know "classic" service layer. When i have constructor for it (func New) should i return pointer or not, and method for this service should be a pointer or not?
@NandhaKumar-c3e4 ай бұрын
this is the perfect video to understand pointers in my pov
@anyDimka Жыл бұрын
Thanks for the video! Also, I use pointers when struct uses locks or other structures that holds their own state and are stored as values.
@SergeyKhaylov Жыл бұрын
Thank for the video.
@edocdrah Жыл бұрын
loved the video.
@robsonandradev Жыл бұрын
Great vídeo man thanks! I like to think about it as I think about passing parameters by value or by reference, when I need just the value I will probably not need a pointer, in another hand when I need the reference I will for sure need to use a pointer. Of course we shouldn't ignore the memory optimization.
@Maniac-007 Жыл бұрын
9:55 “Can I type, please?” Bro you hade lost there 😂 +1 sub
@sergeliatko5 ай бұрын
Thanks, now I see the pointers are the same as reference in PHP except that you need to specify each time you want to use them (in PHP objects are passed by reference by default)
@XxMissingDataxX Жыл бұрын
Man please can you do a series on subjects like that “ when and how to use them” in the golang language? Example maps
@Alexedtion Жыл бұрын
Cool video. It will be amazing a video about AI with Golang (not directly). Vector databases is trending recently bc LLMs, the most popular ones are built with Go and use some ML algorithm, some with C++ interop but is hard to find content about this topic and even if is a great idea to boast AI models consumption with GO
@OhDevBeard7 ай бұрын
Dude thank you for this.
@matthew78uk Жыл бұрын
Amazing content!
@sujaelee2191 Жыл бұрын
another use case - When field can be optional and null value should be differentiated from empty value. For example, let's say a student struct can have score field, but the score can be null when the score is not yet announced. In this case 0 score should be differentiated from null.
@anakinkylo.thepomenerianan908410 ай бұрын
It makes sense to return a pointer because of the default which will be applied to an empty struct of User. So easier to check a nil reference. Prefer using pointers also
@MartinBenesh Жыл бұрын
You are making assumptions regarding go's memory management that are unfortunately wrong. Passing by value doesn't necessarily mean copying the whole struct. For instance your example with 'func(u User) Email() string' would most likely be inlined. In fact the compiler goes extra length, to try and keep structs on the stack and making it a pointer pretty much forces it to escape to heap. It would be interesting to test, when size of struct passed on stack would actually become slower than heap. My guess would be, that only for structs with impractical number of attributes, or a massive array (not a slice - that one is internally a pointer). I would suggest sticking to: use value types by default, only use pointers when you actually need the pointer. that is, when you need to share the data. And please, test your assumptions before you claim them as facts.
@b3owu1f Жыл бұрын
Two thoughts/questions. First, IDE's (and maybe linters) like to complain if you use * and no * on same struct.. not sure why this is? Seems to me for readability reasons as well as your points here, mixing * and no * should be perfectly fine. Second thought.. regardless of size of struct.. it seems to me that you almost always benefit using pointers. That only 8 bytes are copied every time, means faster execution. I argue that this is better because it is not horrible difficult to read code with or without * in this case. The argument that without * tells us that the code is read only.. e.g. not updating anything is really up to the developer of the receiver function to ensure they don't change anything. Anyone else calling it will benefit from the faster execution knowing that the function is not changing anything. So really the one time this is a concern is IF some rogue/dummy developer changes something but doesnt indicate they are doing so in comments.. like if you were using a 3rd party library calling a receiver function and it was assumed nothing would change, but it does.. then that's a bug on the developer of that library. So I guess in that sense, removing the concern that a developer doesn't know that they could be modifying the provided receiver object may be good, but if the receiver function is one called a LOT, and every invocation copies 9+ bytes to it, then the pointer would execute faster. I know.. I KNOW.. some will argue that execution speed is not always important and could be considered early optimizing and not necessary. I say as long as you know when writing the functions that you could arbitrarily change things.. you either make a copy locally for local use, or you just.. uh.. be a better developer and not change anything to pick up that extra speed AND less memory usage on the stack per call.
@anthonygg_ Жыл бұрын
True should be fine. Unless you you are setting members without using *. Thats an ineffective operation
@psycodreamcx7739 Жыл бұрын
Thanks for the video! I'd love a video that covers edge cases (and of course, if you want and have the time haha) to understand better different scenarios
@adambright5416 Жыл бұрын
Value receivers make copy of a struct, however, it is not a deep copy, so beware. If your struct has pointers in it (slice is a pointer to an array, so it counts as well as maps), than you will still be able to update the values... so calling method like below, will still alter user in this scenario func (u User) editFile() { u.file[0] = '0' }
@smjure Жыл бұрын
Another great video Anthony. Could you please make some good video on profiling (with goroutines)?
@RA-xx4mz Жыл бұрын
I just fixed a MASSIVE edge case bug because someone was using a pointer when they should have been using a copy of a value. Pointers are dangerous!
@carriagereturned3974 Жыл бұрын
pointer is an address. When to use it? Use if: want to change value of variable stored at that address. Typically you pass variable's value to function, func cannot change its value, because func doesn't know address. So if you want to change var's value - pass pointer (a.k.a. address). Pointer's value is literally (actually) an address, only it is called a pointer (so it is a type, and a word you can refer in your speech).
@LarryStone-q6r Жыл бұрын
Off topic I know, but I love your terminal color scheme. What is it?
@anthonygg_ Жыл бұрын
Gruvbox
@LarryStone-q6r Жыл бұрын
Thanks! @@anthonygg_
@maciejkrasuski7 күн бұрын
Wrong. On calling "By value" receivers only shallow copy is put on stack. 'file' is slice which in go is value referential to memory allocated elsewhere. In fact slice is tuple (ptr, off, len) and actual memory is separate, and only referenced by ptr. On "by val" pass only this tuple is being copied
@vitiok78 Жыл бұрын
I use the rule that never lets me down. If one method of a type uses a pointer receiver then in general you should use a pointer receiver in all of the methods. It is just safer.
@dulanjala8 ай бұрын
thanks!
@awesomedavid2012 Жыл бұрын
Would it be premature optimization to use a pointer in a getter to avoid making a copy? It may actually be faster to copy a small struct than perform the pointer indirection... But I am correct that without a pointer, go will simply copy the struct right?
@CR33D404 Жыл бұрын
What a syntax!,I was just scrolling and suddenly decided to take a look on the go lang, I’m now curious about that first parentheses witch is placed before the func name does it mean that the function you define like that is going to be added to that struct or class as a member class or smth? Doesn’t go support defining methods inside the struct/class?
@tomassarmiento2199 Жыл бұрын
What if in the database you want some attributes to be null. In the model when working with an ORM, would you set that same variable with a pointer?
@Markus-qf6qi Жыл бұрын
Would a 3rd reason to use pointers to have properties which are nil/nullable (e.g. when working with json/rest api) or would you prefer converting the values later for representation only?
@dj-yv7oi Жыл бұрын
quick question, anthony, why do you hate getters and setters ? 🙃
@anthonygg_ Жыл бұрын
No clue, need to rewatch. I never use getters and setters. So it might be some educational case
@dj-yv7oi Жыл бұрын
@@anthonygg_ i been thru comments and some possibility is that you can just make struct fields public and modify/get them that way 😅
@blessedpigeon6304 Жыл бұрын
i looove how in go the so called syntactic sugar makes things more confusing but i guess it's always the case
@wMwPlay Жыл бұрын
I prefer named return values, so I don't have to type User{}. But I also avoid naked return.
@tobiasprimatjahja38110 ай бұрын
The “Can I type please” makes me laugh
@abysscritical28458 күн бұрын
1:08, does anyone know the motion to move text over like this?
@piyushacharya76966 күн бұрын
That's because of his auto-format on save
@phoehtaung Жыл бұрын
Would you be able to share the theme you are using?
@anthonygg_ Жыл бұрын
Gruvbox
@annguyen6166 Жыл бұрын
Love your video, but are there any rule for attribute, when the attribute should be pointer ?
@anthonygg_ Жыл бұрын
Good question. Lets dive deeper in another video.
@bramvanneerven Жыл бұрын
@@anthonygg_ Would be nice if you could cover shallow vs deep cloning in this case as well. I sometimes need a freezed/cloned representation of the struct to e.g. send it into a gRPC stream (because editing the sent struct after sending it is not safe). What do you do in this case when the struct contains pointers?
@elisio.developer Жыл бұрын
Anyone knows what theme and font is Anthony using?
@anthonygg_ Жыл бұрын
Font: consolas theme: Gruvbox
@brickshick Жыл бұрын
How can you be in great shape and at the same time learn coding? Please teach us some time management my lord
@JohanStrandOne Жыл бұрын
*Commenting for engagement*
@anthonygg_ Жыл бұрын
🤣
@AmirGolmoradi Жыл бұрын
Which Vscode Theme are you using ?
@TMANandMAISON9917 ай бұрын
Thanks for the explanation Love the accent though, you pronounce 'object' exactly like we do in Russian
@avi7278 Жыл бұрын
coming from a Typescript background and also dart/flutter. I'm exploring Go and find your videos quite helpful. But I donno is if it's just me but Go makes me ask what and why tf a lot. Also, you messed up your first example right? whether it's updateEmail or UpdateEmail is irrelevant in respect to your example, correct? Maybe on your first example you didn't mean to create a method but rather just a function that you pass the user to?
@oktay978410 ай бұрын
Go is a case sensitive language. So anthony created two functions called updateEmail and UpdateEmail. Probably (but not for sure) if they were both exactly the same name, linter would throw an error and show the line in red. Also, you can access the updateEmail function from any object you create from the User struct, but the same is not true for UpdateEmail.
@AHN144411 ай бұрын
When the parameter is an slice ? don't need to pass as pointer because the slice is already a pointer?
@anthonygg_11 ай бұрын
Correct
@AchwaqKhalid Жыл бұрын
Please use a bigger font for your future videos 💡 Edit: fixed ✅
@anthonygg_ Жыл бұрын
BOGGER 💪
@AchwaqKhalid Жыл бұрын
@@anthonygg_ bigger 😅
@achmaddhanytomara72272 ай бұрын
GREATTTTTTTT
@pablo1gustavo Жыл бұрын
what is this vscode theme?
@anthonygg_ Жыл бұрын
Gruvbox
@rockandrolldevil66511 ай бұрын
awesome
@professorgoodwin Жыл бұрын
1. Slice always 24 bytes, because it's a pointer to underlay array, lengrh and capacity. 2 . When you use pointer you get Escape to Heap and GC. You should keep it in mind. 3. What Go will do if you call non-pointer receiver from pointer or vice versa. It's an interesting stuff, that you did not explain in this video. In two words if you have pointer receiver and call it from non-pointer object it will work fine - Go create reference under the hood and vice versa. So, this is NOT just a syntax sugar. In your example , if I wtire something like: u := &User{email:"email"} s := u.Email() it will work correctly. Resume : probably, you should better learn Go before teaching other people
@timhilt1185 Жыл бұрын
Exactly. Receivers allow access to private struct members. If he would have run the „non receiver implementations“, it wouldn‘t have compiled.
@masterchief1520 Жыл бұрын
@@timhilt1185could you please explain a bit better I got confused reading the above explanation
@minciNashu Жыл бұрын
So copies are actual copies of objects, instead of copies of references, as expected in most GC languages.
@Luix Жыл бұрын
interesting. As much as I like Go I think Java does the setters better.
@JugaadTech Жыл бұрын
I have seen you somewhere, are you a doctor or plumber as well by any chance
@anthonygg_ Жыл бұрын
Dont forget the fireman and the astronaut.
@dixztube11 ай бұрын
How come e-mail isn’t e
@axMf3qTI Жыл бұрын
Is it good practice in Go to make getter/setter methods for structs? ..Oh haha 2 secs after posting he says he hates getters and setters so I guess not.
@mhe8ehdb38bbbbhh3 ай бұрын
I want your theme color name😂
@deepakparasjain9991Ай бұрын
4:24 why?? 😂
@sunilanthony17 Жыл бұрын
Thank you, love it but your typing raises my OCD to a different level. 🙂
@choleralul Жыл бұрын
How Long is a Chinese
@anthonygg_ Жыл бұрын
He certainly is
@Zmey56563 ай бұрын
If I want nil value - use a pointer ;-)
@Dozer456123 Жыл бұрын
lol "I hate setters and getters", proceeds to make a setter with a different name. Immutability is really the only way to write go code that is tolerable
@vyacheslavgorbov6652 Жыл бұрын
9:50 , 1 gay bee.
@jimbo0o3 ай бұрын
I hate your keyboard's noise! please filter it
@user-qc7rz3nq2b18 күн бұрын
you are clear but too fast
@anthonygg_18 күн бұрын
I really wish I could be slower. Problem is that if my videos take longer than 20 min, the algo will punish me.