► Join my Discord community for free education 👉 discord.com/invite/bDy8t4b3Rz ► Become a Patreon for exclusive tutorials👉 www.patreon.com/anthonygg_ ► Buy me a coffee 👉 donate.stripe.com/aEU2a6ayH2uCa3u4gg Thanks for watching
Very interesting, I was expecting something like player.Position.Move(), but all clear about struct embedding. Cool! Cheers from Central America, Guatemala
Great tutorial, I am learning Go and this is really helpfull. I have one question though. For the type SecialPosition, you added Position (and not *Position) unlike what you did for Player or Ennemi. What is the difference?
@@yaminokaze4475 I found out, that if we use pointer, we should somewhere allocate a memory for the pointer like &Position{}. So, we will have to write a contructor for a SpecialPosition struct, if we embbed Poisition in it like a pointer, it will be like this: func NewSpecialPosition() *SpecialPosition { return &SpecialPosition{ Position: &Position{}, } }
Shouldn't be the case that the pointer version stores a pointer to the Position struct and the other ones stores a full copy by value of the struct? It's not the same.
Nice! The word you’re looking for is ‘promotion’. Embedding a type within a struct ‘promotes’ fields and method declared on the type to the containing struct. You can even embed an interface within another interface - you can even embed an interface within a struct
God dammit :). For some reason when copy-pasting from another video that link gets truncated somehow. Anyway, normally should be fixed now. Thanks for letting me know, and thanks upfront for the coffee
The ONE thing you didnt cover that's important is what happens if Position and SpecialPosition have the same method names. No overloading capability, so which one is called?
Quite a lot of nuance between them! The default value of a reference type is NIL, so if you forget to use the factory method and just build a Player raw with p := Player{} (or forget to init your embedded types in the constructor), it'll have a nil Position. And as you might guess, in this case if you try invoking Player.Move you'll get a runtime error. - so why would I ever want to use a by-reference embed? To keep working with the videogame example, you'll eventually add a Sprite struct to the project. Your Sprite will have some graphics, a physical size, a count of the available frames of animation, maybe it has a draw method or a non-member function handles that, whatever. A lot of enemies will share the same sprite asset, so embedding the Sprite struct by-reference makes sense here. A lot of unique enemy structs can point to the same single instance of Sprite. We can just have it as a reference passed in to the constructor. We'll let each enemy track which frame of animation they are on independently, not within the Sprite struct. Another idea is this opens the door to data-oriented design. let's say you declare all your positions in a big slice. enemies:=make([]Position, 1000) now in your enemy constructor, you point each enemy's Position to its own &enemies[i]. now when you write a function that iterates over "the position of the enemies" it has the advantage of cpu cache coherency. You'll also need to track which positions in the slice are actually 'real', too, fortunately this is a trivial to do, define a new type with by-value Position embedding and an extra bool. by-value has the advantage of keeping things simple. no nil pointer to trip over, no extra malloc or reference for the gc. Should probably be your default go-to, then when you see an embedded pointer you'll think "okay, maybe this is a many-to-few relationship, or there's a special purpose for this."
I noticed that you always make every function public by default, starting with a capitilized letter. Can you please explain that habbit ? Wouldn't it more secure to make all functions private by default ?
@@anthonygg_ Cool! Is the struct by default a pointer in that case? Wondering why in Player has a pointer to Position - can we drop it here too? I mean, i get the difference between pointer/not pointer, but wondering that is the proper way to do it in GoLang
You put out great content... But man... Your typing style and the clack of your keyboard is distracting. Somehow you stuff a whole bunch of useless extra keystrokes in an effort to go fast. Relax! Fast is smooth and smooth is fast.
@@anthonygg_ I think, I have already stopped watching and googled the topic on a few of your videos as a result. To my knowledge, I don't have misophonia and generally tolerate things that those with it don't. I mean this as constructive feedback. A simple and low background beat track that doesn't overpower or conflict with your voice but creates something more like a white-noise mask is a simple thing to do that doesn't require you "work on it"; it let's you use the keyboard you like, avoids needing excessive filters and work on the audio track, and helps feature your content without drawing attention away.
► Join my Discord community for free education 👉 discord.com/invite/bDy8t4b3Rz
► Become a Patreon for exclusive tutorials👉 www.patreon.com/anthonygg_
► Buy me a coffee 👉 donate.stripe.com/aEU2a6ayH2uCa3u4gg
Thanks for watching
Yo, why are you like the only person doing content like this on Go? There needs to be more of this
Send everyone here 🎉
This man look's like a person who can get things done .
Sometimes 😂
Time well spent. Thanks Anthony
I'm an old dog, but I still love learning. Your great videos inspire me.
Best movie for Friday night)
Very interesting, I was expecting something like player.Position.Move(), but all clear about struct embedding. Cool! Cheers from Central America, Guatemala
You will definitely become "Elite GO" with Anthony 👍
Thank you !! I have ADHD and your content is dopamina producer.
Great tutorial, I am learning Go and this is really helpfull.
I have one question though.
For the type SecialPosition, you added Position (and not *Position) unlike what you did for Player or Ennemi.
What is the difference?
I had this exact question too
Same here
Thank you really clear explanation
Great one ❤
You are a god. thank you for your content 🙏🏼
Great as usual
Sweet thanks for this great lesson of Golang
Very informative. Great work 👍
GG very nice tutorial. First time i can follow all through and understand all haha
Thanks!
best of the best
Why do you use pointer to Position inside Player but non-pointer in the SpecialPosition?
Same Question, If you found an answer plz let me know.
@@yaminokaze4475 i also want to know this, but i think, he just made a mistake, because there is no reason to make it non pointer.
@@yaminokaze4475 I found out, that if we use pointer, we should somewhere allocate a memory for the pointer like &Position{}. So, we will have to write a contructor for a SpecialPosition struct, if we embbed Poisition in it like a pointer, it will be like this: func NewSpecialPosition() *SpecialPosition { return &SpecialPosition{ Position: &Position{}, } }
@@alexobzorThanks, this really helped!
great content as always
so many points of view: inheritance or embedding)
Great video, thank you again!
Yo man this is so DOPE! I like this approach so much. By the way what is this VScode theme? Looks so warm :)
Gruvbox
@@anthonygg_ ahh yes, exactly! Thank you. :)
Love your videos.Could you please make a video on how to implement port forwarding in golang.
Noted that on the list
I find go a bit inconsistent. You can embed with and without the * (position is embedded into SpecialPosition NOT as a pointer) and works the same.
Shouldn't be the case that the pointer version stores a pointer to the Position struct and the other ones stores a full copy by value of the struct? It's not the same.
I noticed that you always make a constructor function to instanciate structures. Would you say that's a good habit to take on ?
Yes
Every time I think "I'm gonna learn Rust" I am reminded how beautiful and elegant Go is, and I stay put.
Big fan!
My man! How are you?
I am doing amazing! Great to see the channel grow like this❤️
we need problem solving vids on Friday or any day of the week if u have time
Keep the dopamine coming!
Nice!
The word you’re looking for is ‘promotion’.
Embedding a type within a struct ‘promotes’ fields and method declared on the type to the containing struct.
You can even embed an interface within another interface - you can even embed an interface within a struct
Why in the enemy and player struct you embed it as *Position and in the SpecialPostion without the “*”? What’s the difference? 🤔
Not sure, no particular reason I guess 🥲
@@anthonygg_ 😅
Great work! Wanna buy you a coffee but the link provided(stripe?) is not working for me(get 404).
God dammit :). For some reason when copy-pasting from another video that link gets truncated somehow. Anyway, normally should be fixed now. Thanks for letting me know, and thanks upfront for the coffee
@@anthonygg_ Think I had the same problem in some other videos of you. Anyway, above link works now :)
The ONE thing you didnt cover that's important is what happens if Position and SpecialPosition have the same method names. No overloading capability, so which one is called?
the containing type's method is given preference, else you can do "Outer.Inner.field" to select the embedded field or method
hi, why are you embedding the pointers instead of values ?
No real reason better not use them in that case
What vscode theme is?
Pronunciation: "struct" (with u), not "strict" (with i).
Ok buddy.
What's the difference between embedding with a dereferencing '*' and embedding without it?
Quite a lot of nuance between them!
The default value of a reference type is NIL, so if you forget to use the factory method and just build a Player raw with p := Player{} (or forget to init your embedded types in the constructor), it'll have a nil Position. And as you might guess, in this case if you try invoking Player.Move you'll get a runtime error.
- so why would I ever want to use a by-reference embed?
To keep working with the videogame example, you'll eventually add a Sprite struct to the project. Your Sprite will have some graphics, a physical size, a count of the available frames of animation, maybe it has a draw method or a non-member function handles that, whatever. A lot of enemies will share the same sprite asset, so embedding the Sprite struct by-reference makes sense here. A lot of unique enemy structs can point to the same single instance of Sprite. We can just have it as a reference passed in to the constructor. We'll let each enemy track which frame of animation they are on independently, not within the Sprite struct.
Another idea is this opens the door to data-oriented design. let's say you declare all your positions in a big slice. enemies:=make([]Position, 1000)
now in your enemy constructor, you point each enemy's Position to its own &enemies[i].
now when you write a function that iterates over "the position of the enemies" it has the advantage of cpu cache coherency. You'll also need to track which positions in the slice are actually 'real', too, fortunately this is a trivial to do, define a new type with by-value Position embedding and an extra bool.
by-value has the advantage of keeping things simple. no nil pointer to trip over, no extra malloc or reference for the gc. Should probably be your default go-to, then when you see an embedded pointer you'll think "okay, maybe this is a many-to-few relationship, or there's a special purpose for this."
Thank you, makes a lot of sense!
I noticed that you always make every function public by default, starting with a capitilized letter. Can you please explain that habbit ? Wouldn't it more secure to make all functions private by default ?
Is there any special reason, why Position that is embedded in SpecialPosition is not a pointer?
No special reason. You can drop the pointer
@@anthonygg_ Cool! Is the struct by default a pointer in that case?
Wondering why in Player has a pointer to Position - can we drop it here too?
I mean, i get the difference between pointer/not pointer, but wondering that is the proper way to do it in GoLang
top gg
That's weird. The "Position" is basically polluting namespace of the "Player".
it this Irish or Scottsih accent? I need to know this
How old are u bro ?
Is that inheritance ? I would think of it more as Composition, it doesn't inherit anything
Cool workaround, but it't not inheritance
Correct but it was such a good keyword for the title
That is more ECS than OOP
Brother, you're providing great content, but please, slow down when typing it gets very hard to follow when you're mistyping every other word.
You have a point
Bcoz we only know to copy ... 😂
That's not inheritance. That's composition and it blows
Its has its purpose sometimes. But most of the time its not the best fit. So I agree here with you. Inheritance is a click bait.
@@anthonygg_ I meant GO's struct embedding. It blows
why your cursor and your typing is weird?
Cause Im a weirdo.
It is Vim
You put out great content... But man... Your typing style and the clack of your keyboard is distracting. Somehow you stuff a whole bunch of useless extra keystrokes in an effort to go fast.
Relax! Fast is smooth and smooth is fast.
Its more of a tick I do when thinking. Im working on it.
@@anthonygg_ have you considered adding some low level background music to obscure the keyboard?
@@Combatwhombat Im considering adding more keyboard noise in the future. What do you think?
@@anthonygg_ I think, I have already stopped watching and googled the topic on a few of your videos as a result. To my knowledge, I don't have misophonia and generally tolerate things that those with it don't. I mean this as constructive feedback.
A simple and low background beat track that doesn't overpower or conflict with your voice but creates something more like a white-noise mask is a simple thing to do that doesn't require you "work on it"; it let's you use the keyboard you like, avoids needing excessive filters and work on the audio track, and helps feature your content without drawing attention away.
*Slow is smooth and smooth is fast :)