Go Pointers: When & How To Use Them Efficiently

Go Pointers: When & How To Use Them Efficiently

Anthony GG

1 год назад

66,412 Просмотров

Ссылки и html тэги не поддерживаются


Комментарии:

@edocdrah
@edocdrah - 02.12.2023 09:18

loved the video.

Ответить
@user-cb3le9oh9p
@user-cb3le9oh9p - 30.11.2023 06:51

Off topic I know, but I love your terminal color scheme. What is it?

Ответить
@MartinBenesh
@MartinBenesh - 19.11.2023 15:31

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.

Ответить
@SeanSmithPit
@SeanSmithPit - 17.11.2023 21:36

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.

Ответить
@carriagereturned3974
@carriagereturned3974 - 14.11.2023 18:10

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).

Ответить
@AmirGolmoradi
@AmirGolmoradi - 23.10.2023 22:00

Which Vscode Theme are you using ?

Ответить
@adambright5416
@adambright5416 - 30.09.2023 23:19

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'
}

Ответить
@awesomedavid2012
@awesomedavid2012 - 27.09.2023 14:03

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?

Ответить
@b3owu1f
@b3owu1f - 27.08.2023 22:21

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.

Ответить
@AchwaqKhalid
@AchwaqKhalid - 26.08.2023 18:40

Please use a bigger font for your future videos 💡

Edit: fixed ✅

Ответить
@CR33D404
@CR33D404 - 22.08.2023 15:19

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?

Ответить
@JugaadTech
@JugaadTech - 17.08.2023 18:34

I have seen you somewhere, are you a doctor or plumber as well by any chance

Ответить
@sunilanthony17
@sunilanthony17 - 17.08.2023 13:55

Thank you, love it but your typing raises my OCD to a different level. 🙂

Ответить
@professorgoodwin
@professorgoodwin - 16.08.2023 10:36

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

Ответить
@tomassarmiento2199
@tomassarmiento2199 - 05.08.2023 06:17

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?

Ответить
@TheQxY
@TheQxY - 30.07.2023 14:25

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.

Ответить
@dougsaylor6442
@dougsaylor6442 - 25.07.2023 23:45

This definitely trips up Go newbies. Good video! 😀

Ответить
@robsonandradev
@robsonandradev - 18.07.2023 04:03

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.

Ответить
@elisiosa3111
@elisiosa3111 - 10.07.2023 19:37

Anyone knows what theme and font is Anthony using?

Ответить
@minciNashu
@minciNashu - 09.07.2023 08:05

So copies are actual copies of objects, instead of copies of references, as expected in most GC languages.

Ответить
@christopherchalcraft1134
@christopherchalcraft1134 - 06.07.2023 10:11

Really love your style and pace of video. Great job.

Ответить
@vitiok78
@vitiok78 - 06.07.2023 00:57

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.

Ответить
@pablo1gustavo
@pablo1gustavo - 27.06.2023 19:54

what is this vscode theme?

Ответить
@tumz8970
@tumz8970 - 25.06.2023 19:47

How can you be in great shape and at the same time learn coding? Please teach us some time management my lord

Ответить
@sujaelee2191
@sujaelee2191 - 25.06.2023 15:55

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.

Ответить
@goldilockszone4389
@goldilockszone4389 - 22.06.2023 07:43

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

Ответить
@Markus-qf6qi
@Markus-qf6qi - 20.06.2023 11:12

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?

Ответить
@lokthar6314
@lokthar6314 - 19.06.2023 07:46

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.

Ответить
@psycodreamcx7739
@psycodreamcx7739 - 16.06.2023 05:51

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

Ответить
@kruczek1986
@kruczek1986 - 15.06.2023 08:53

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?

Ответить
@smjure
@smjure - 15.06.2023 07:10

Another great video Anthony. Could you please make some good video on profiling (with goroutines)?

Ответить
@choleralul
@choleralul - 14.06.2023 18:24

How Long is a Chinese

Ответить
@phoehtaung
@phoehtaung - 14.06.2023 14:46

Would you be able to share the theme you are using?

Ответить
@wMwPlay
@wMwPlay - 14.06.2023 13:41

I prefer named return values, so I don't have to type User{}. But I also avoid naked return.

Ответить
@RA-xx4mz
@RA-xx4mz - 14.06.2023 05:22

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!

Ответить
@Alexedtion
@Alexedtion - 14.06.2023 03:50

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

Ответить
@joseburgosguntin
@joseburgosguntin - 14.06.2023 03:28

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<T>, 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.

Ответить
@hamm8934
@hamm8934 - 14.06.2023 02:28

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!

Ответить
@nas337
@nas337 - 13.06.2023 23:04

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🙂

Ответить
@JohanStrandOne
@JohanStrandOne - 13.06.2023 22:35

Commenting for engagement

Ответить
@SergeyKhaylov
@SergeyKhaylov - 13.06.2023 22:31

Thank for the video.

Ответить
@XxMissingDataxX
@XxMissingDataxX - 13.06.2023 20:26

Man please can you do a series on subjects like that “ when and how to use them” in the golang language? Example maps

Ответить
@annguyen6166
@annguyen6166 - 13.06.2023 20:21

Love your video, but are there any rule for attribute, when the attribute should be pointer ?

Ответить
@jamesarias2363
@jamesarias2363 - 13.06.2023 19:28

thanks for the pointers!

Ответить
@siddhantkashyap5934
@siddhantkashyap5934 - 13.06.2023 19:20

No one can explain any better!!! Thank you!

Ответить