► Join my Discord community for free education 👉 discord.com/invite/bDy8t4b3Rz ► Pre order (get 30% off) my Golang course 👉 fulltimegodev.com Thanks for watching
@kafran Жыл бұрын
This pattern is commonly known as the "Functional Options" pattern. The Functional Options pattern is a design pattern in Go where you pass in functions that alter the state of a type. These functions are often called "option functions". They provide a way to cleanly design APIs and offer a more flexible and readable way to interact with a function or type. Nice demonstration on how to implement them. Thanks.
@jeezusjr Жыл бұрын
Perfect timing! I am doing something right now that can use this pattern. Thanks!
@necroowl3953 Жыл бұрын
1. Make the config elements private 2. Make the options type a public interface, with a single private method (apply(config) config) 3. Expose public functions returning this interface 4. Add a function type that complies with the option interface, make that type implement the apply method by calling itself. 5. Add a no-op type for validation when needed. 6. Validate input before returning a config type. Boom, functional options with a restrictive builder pattern, for your constructors. You can make it generic too.
@macot7911 ай бұрын
Hey! Those suggestions are really great, I'm new at Golang and have tried to adapt Anthonygg's example with your suggestions, but I'm a bit stuck at step 5. Could you clarify what you mean? Thanks
@hugorojasmonzon14879 ай бұрын
Could you create a github example of these ideas ?
@abiiranathan Жыл бұрын
Functional Options Pattern... popularized by Dave Cheney
@wuilliam321 Жыл бұрын
Any book/reference? Thanks
@jamesprendergast7158 Жыл бұрын
Surprised gg didn't know the name TBH
@Cruzylife Жыл бұрын
@@jamesprendergast7158 because Ant creates his own meta
@TehKarmalizer Жыл бұрын
Looks like functional riff on the builder pattern.
@Kiran_C_NayakАй бұрын
Dave Cheney's Talk: kzbin.info/www/bejne/aGXPd6d9fbyrd7M Link to Rob Pike's Blog mentioned in Dave's talk: commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
@jex8885 Жыл бұрын
This channel is amazing, you're making my Go code better and better for every video!
@banatibor8310 ай бұрын
It looks fancy but a bit of a hassle. A simple builder pattern is much more readable I think. The default values are nice. Then just put methods onto the ServerOpts type which return *ServerOpts. type ServerOpts struct {...}, func NewServerOpts() *ServerOpts {...set defaults...} , func (s *ServerOpts) Id(id string) *ServerOpts {... set id ..}, func (s *ServerOpts) MaxConn(maxconn int) *ServerOpts {...set maxcon..} Then you can use it like this: s := NewServer(NewServerOpts().Id("my-server").MaxConn(100))
@Ascentyon8 ай бұрын
Exactly. This is much better for discoverability, instead of having a bunch of standalone functions.
@matthewwagner5396Ай бұрын
Feels like you don’t even need the opts struct here. Just use the server struct itself
@jaiswalrohan26 күн бұрын
@@matthewwagner5396 yep
@arieheinrich3457 Жыл бұрын
Thanks for diving into design patterns Anthony ! This is what separate starting devs to more advanced ones, that we all aspire to be, and that is understanding design patterns. Looks more like the Builder pattern than the Visitor one.
@anthonygg_ Жыл бұрын
Apperantly is the “functional options” pattern 🤷♀️
I also know this as a builder pattern, it's very common and good use for building test fixtures
@yogeshdharya3857 Жыл бұрын
3:50 to 3:53 Witch Craft and Woo Doo ! . My man's a part-time wizard
@vitiok78 Жыл бұрын
Reinventing the wheel of named function parameters with default values))
@susiebaka338811 ай бұрын
you're free to use a map or whatever my guy
@bigtymer4862 Жыл бұрын
Love these pattern videos man!!
@adriancmiranda2 ай бұрын
It's a very good pattern, thx for sharing. Your didatic is very good!
@kylestubblefield3404 Жыл бұрын
This is a great video. I stumbled onto using this pattern by accident, it was very useful for a previous project I was working on
@skyline7349 Жыл бұрын
Thank you for posting this Anthony, very nice pattern and will be trying to incorporate it with my starter projects
@Programscape Жыл бұрын
Watch this video for some time ago, remember. And return now to implement this in my project)) Antony is gigachad, thx for the video
@lokthar6314 Жыл бұрын
Quality Content
@anthonygg_ Жыл бұрын
🙏
@lotfikamel5947 Жыл бұрын
As always very advanced content
@bjugdbjk Жыл бұрын
Just love this man !! More like this brother, these r the stuff which really play with the Dopamine !!
@rajdama205 Жыл бұрын
The way you make any concept understand is just amazing !!
@kajfehlhaber Жыл бұрын
Awesome video as always! ❤
@whatwhat2573 Жыл бұрын
Nice clean pattern to understand too
@vitaliik8315 Жыл бұрын
Thanks for yours lessons. One of the best video lessons for go.
@JT-mr3db9 ай бұрын
Does feel like a take on the builder pattern. Incredibly handy pattern a lot of Elm libs use as well.
@joshuatye1027Күн бұрын
Builder pattern returns this though. This accepts an unknown number of functions that may or not even return valid struct keys.
@codewithluke Жыл бұрын
Nice one. Really enjoy this pattern.
@kanfit Жыл бұрын
Thanks, I think you also talked about a bit of functional programming in Golang in this video, which is very nice.
@grim.reaper Жыл бұрын
This is amazing and used in a lot of places tbh. This is very true that it's used in gRPC, also ssh package if I am not wrong because ssh connection has a lot of options. While putting this in a library the "withXYZ" functions can also be a method where it can have the server receiver methods. This is so so so amazing!!!
@Rohinthas9 ай бұрын
Aah functional stuff is just so pleasing to think about
@Crazyfulization Жыл бұрын
Really helpful, you can see the benefit right away! Awesome stuff
@matthewbridges31479 ай бұрын
Thanks for the explainer, I'd have been searching docs for a standard way to do this without realising it requires a pattern. In JS I'd just use a default arg param and a spread operator to override
@hugorojasmonzon14879 ай бұрын
Amazing video, thanks for sharing your knowledge!
@victorkochkarev25769 ай бұрын
This is a beautiful pattern!
@michael_loc009 Жыл бұрын
I wish you would upload this amazing tutorial when I first learnt Go.
@henrisetiawan75478 ай бұрын
Gem....amazing explanation..and going sub ..
@sibonelongobese8639 Жыл бұрын
Top notch stuff 👌🏽
@grise123 Жыл бұрын
nice pattern, seems very helful
@howesteve7 ай бұрын
Congrats, you just converted your one liner function into a 50 lines api, introducing lot of nested function calls and even loop overhead, by using the old builder pattern.
@anthonygg_7 ай бұрын
Well, you are not wrong.
@burionyt Жыл бұрын
only real world shit in the channel 💪🏼 love your content as always ❤
@fluctura Жыл бұрын
Meanwhile in TypeScript: mergedOpts = { ...defaultOpts, ...opts } as Opts But its a cool pattern. Go doesn't have "map spread operator" and thats a good thing probably. But sometimes it would be so handy to have more syntactic sugar
@fluctura Жыл бұрын
btw it is a mix of Higher order Functions you write and you use them to compose a struct using Inversion of Control. So basically Higher order compositional Inversion of Control based state management (as your config acts as a state) 😂😅
@pserra94 Жыл бұрын
Hi Antonio, how are you? I'm migrating from nodejs to Golang thanks to you and your videos, always amazing! I don't know if it's asking too much, but could you make a video/tutorial for developing web crawlers with golang, please? I was googling about it but I didn't find any good content about it. Thank you so much my friend, you are amazing!
@fauzi5848 Жыл бұрын
This is so useful, thank you so much!
@miguelborges7913 Жыл бұрын
This is great!
@TuvaluHODL Жыл бұрын
Opts (Opts, opts), opts Opts Opts opts😅 Thank you Op for the video ; I appreciate your talent and time
@quantenlicht Жыл бұрын
Start: 1:03
@johnb765711 ай бұрын
Thank you, perfect
@orterves9 ай бұрын
That's a beautiful pattern
@vanshajdhar9223 Жыл бұрын
Beautiful ❤️
@mihaiii6720 Жыл бұрын
This pattern is so good !!! I guess you can use it in TS/JS too
@fringefringe7282 Жыл бұрын
This is pretty cool.
@ShadwTrooper9 ай бұрын
Clever. I like it.
@Epistemer Жыл бұрын
This is honestly really cool, I always hated how there is no way to do kwargs in go
@GustavoFSx7 ай бұрын
Beautiful
@jf3518 Жыл бұрын
Great work around. Though I would not use it, as I cannot use an existing config to initialize the state. Instead I would just use merge function to join default config with provided config.
@inaccessiblecardinal9352 Жыл бұрын
Good stuff. Aws' sdk has this pattern in every client (that I've used).
@kevinkkirimii Жыл бұрын
I have misused this pattern. Quite useful
@seanknowles9985 Жыл бұрын
Hey big boss, two questions: 1. How to make an efficient cron job scheduler from scratch? 2. How to make realtime subscriptions to database values - for example we have key value store but then we build realtime subs that can subscribe to changes of a key and its data? Another quality video for the fans homie, love this channel. Bests, Super fan.
@reikooters Жыл бұрын
Isn't this kind of a limitation on the language? If you could specify default values when you declare structs, then this would go from 50 lines down to 10? You mentioned doing this function approach if you were building a library. How would you do this in a way that's easy for consumers of the library to use and know which functions are available to be used for configuration? Would you put them together into a "configuration" package? (I'm not a Go user, just interested)
@sunofabeach9424 Жыл бұрын
this language is limited is so many ways that eventually you give up on it and probably on life as well. GO, while being a higher level than C, looks and feels as clunky as C. but what in C is honestly called a hack, in GO called a pattern. C was designed to be as easy to parse and compile as possible and that's why it lacks so much. GO has no such excuse
@klamberext Жыл бұрын
The example here is for overriding defaults. Imagine instead a environment specific factory configuration or just a variety of options: Lets say your server/thingy supports different storage services - S3, ftp, local. Now you want to say: withStorageDriverFromEnv, or withFtpStorage or withS3 storage. All of them require different kinds of paths, credentials etc.. Now do that with default values on struct. The limit is in the example given.
@klamberext Жыл бұрын
For consumers you provide docs. Or you instead implement the OptFunc as an interface . Then it would be possible to view the list of implementations for given interface(if you have good IDE) .
@botyironcastle2 ай бұрын
with golang you always have to reinvent the wheel, this is called required and optional params with default values, and a good language has it out of the box without defining 200 functions and polluting the code space and destroying readability.
@jaiswalrohan26 күн бұрын
yep, as someone coming from python i am like \(〇_o)/
@adyanto4043Ай бұрын
can we use builder design pattern for the same?
@Md.MitunRahman Жыл бұрын
this is unbelievable
@PouriyaJamshidi Жыл бұрын
This was really informative. A side question. Any particular reason for using int instead of uint in maxConn? I noticed most people use int where a uint makes more sense. In this case, we cannot have negative maxConn.
@anthonygg_ Жыл бұрын
Just for demonstration purposes. Uint is better.
@PouriyaJamshidi Жыл бұрын
@@anthonygg_ Thanks. I think somewhere I heard something along the lines of integer underflow and was wondering if this has something to do with that
@helmchen1239 Жыл бұрын
-1 meaning unlimited could be an option in that case though :)
@myrachanto Жыл бұрын
that was really cool trick i like it
@ChristopheHa Жыл бұрын
I guess this could also be combined with builder pattern, and then you can just can chain those withX on the builder and build will return the instance
@MrXperx Жыл бұрын
Looks to be a variation of the builder pattern. (I come from OOPS)
@matiasbpg Жыл бұрын
What is the advantage of this pattern over a builder pattern?
@sfsdeniso5941 Жыл бұрын
Error handling In go you cannot chain builder calls as each must return error (and not this)
@matiasbpg Жыл бұрын
@@sfsdeniso5941 thanks for the answer! However I think a builder for the opts struct shouldnt have this problem, but now I can see the inconvenience. Maybe a walk around could be that the builder struct could itself carry through the error as a property and the build method could return the value error tuple
@CaffeineForCode Жыл бұрын
The only problem with this pattern is that you lose info from the LSP. Working with the AWS SDK, I often have no idea what is possible or what the opt functions do without reading the documentation. It’s a trade off, especially when you have a lot of config options
@tigranrostomyan9231 Жыл бұрын
I think it is possible to solve by putting all 'OptFunc's into another (child) package, e.g. "server/opts". Maybe it's a bit of overkill but if you then type 'opts.' and call autocompletion it will list all 'OptFunc's
@jub0bs Жыл бұрын
You write: "I often have no idea what is possible or what the opt functions do without reading the documentation." But is a classic config struct any better, in this respect?
@jurijskobecs2803 Жыл бұрын
@@jub0bs of course its better, you got one place/struct to check all the possible options
@jub0bs Жыл бұрын
@@jurijskobecs2803 The fields of a struct type tell you close to nothing about how they're going to be used by the rest of the program. Their names give you clues at best, and their documentation is meant to give you accurate information. But you'll need to dig into the implementation to definitely find out. In this respect, a struct isn't superior or inferior to functional options.
@HiperCode10100 Жыл бұрын
very good thx bro
@plashless3406 Жыл бұрын
amazing.
@luizfernandopereira5120 Жыл бұрын
This pattern is just an adptation from the Fluent Interface Pattern existing in OOP languages, is nice to see it in go though.
@MesheeKnight Жыл бұрын
We use to call this the Option pattern. Would you have a nice one for Mandatory config where you cannot provide a reasonable default, like a sql.Conn?
@anthonygg_ Жыл бұрын
Thats an amazing question! You could force an interface as option and implement a noop for that interface as default to prevent nil pointers. What do you think?
@MesheeKnight Жыл бұрын
@@anthonygg_ i see the Idea, but i am looking for a way for large amount of mandatories, noop wont do the trick i think
@sfsdeniso5941 Жыл бұрын
It is called 'Functional options pattern' should look like this: func NewServer(addr string, opts ...Option) error () {.....} so here addr is mandatory. Usage example: server, err := NewServer("localhost", withPort(8080), withTimeout(time.Second))
@MENTOKz Жыл бұрын
oh snap cool man
@heartly4u Жыл бұрын
why not create a builder pattern, which will do the same as what you are doing, with more readability.
@JohnDoe-ji1zv Жыл бұрын
Can you share example how your pattern is more clear than the one shown in a video ?
@heartly4u Жыл бұрын
@@JohnDoe-ji1zv wouldnt it be more readable this way newServer().withTls().withId().withMaxConnections().build()
@tgraupne Жыл бұрын
I was thinking about the same thing. 🤔 Maybe the authors or some other people would like to chime in.
@TheSurvivor196310 ай бұрын
This is a good pattern, I've been using it for years, but why not make an option function that returns the same option function with the previous value? That way you can change and reset options on the fly. An example could be to elevate debug logging temporarily for some very complex code segment. Rob Pike wrote an article about this for some years ago. type Option func(*Some) Option type Some struct{ ... dLevel int } func Debug(d int) Option { return func(s *Some) Option { t := s.dLevel s.dLevel = d return SetOption(t) } }
@startengine8838 Жыл бұрын
how inner function (the one that you retuen in options functions) gets the pointer which it has as input when higher lexical scope doesnt provide it
@infastin3795 Жыл бұрын
I hate functional options pattern. It just so much worse compared to just passing a pointer to a structure with options.
@pyronb Жыл бұрын
Can somone please rephrase what's happening at 6:15 with fn(&o) ? It's not clear to me how everything works together
@ja31ya Жыл бұрын
He's using the spread operator to allow as many OptFunc's as you want. He then uses the range operator to loop through each OptFunc and executes them with a reference to the options struct (that's the **fn(&o)**), so that the OptFunc can modify the options directly, overwriting the default options.
@folium5725 Жыл бұрын
Hi Anthony, what theme do you use?
@anthonygg_ Жыл бұрын
Gruvbox
@suikast42011 ай бұрын
Cool fancy< stuff. What about toi make a fluent api with that style?
@ivanrachev9409 Жыл бұрын
Cool approach! Just wondering, why did you go back to VS Code?
@timurgirfanov531 Жыл бұрын
It's like Visitor pattern, but in a functional way
@sfsdeniso5941 Жыл бұрын
It is called 'Functional options pattern'
@1_PieceOfCode5 ай бұрын
why not just set default conf at first and then use factory pattern so user can just change config as he wants?
@yawneed10 ай бұрын
Hello. Where does download your vscode config?
@maninalift Жыл бұрын
Is there an advantage over the builder pattern? It seems to be equivalent in usage but I'd guess harder to optimise.
@x0z59 Жыл бұрын
will this thing not make established Go features convoluted? aren't you not reinventing the wheel here?
@mozhago8280 Жыл бұрын
Is this pattern used in go starndard lib?
@dmitriyobidin604911 ай бұрын
The only problem i have with this pattern is that it is not obvious which methods/func you can use as options.
@metaltyphoon Жыл бұрын
AWS SDK uses this pattern too.
@vasiliyaristov714811 ай бұрын
Interesting
@igor-glagola Жыл бұрын
Looks like some sort of builder pattern
@robinlioret7998 Жыл бұрын
I think it's a Go version of the Builder pattern, but not sure.
@jungervin87654 ай бұрын
Why not just create a default struct every time you want to use this. Create a default func, and the user can change the options. How is all that "with" functions not polluting the function names?
@polnio8 ай бұрын
This pattern looks a lot like the builder pattern. Am I wrong?
@chaitany.a Жыл бұрын
This is like a functional builder pattern...?
@faiz_00004 ай бұрын
damn, so much work for just an optional config parameters can't you just make every args optional and assign default value to it if its nil?
@AmedMoore8 ай бұрын
This pattern is called “over engineering”
@henryconner7808 ай бұрын
You do be the that guy
@caiocesarmelolopes2156 Жыл бұрын
That looks like function as parameter that was introduced in java 8 with lambdas xD
@TimurSevimli Жыл бұрын
Why not just take configuration data from a JSON file, like config.json?
@5packsabs Жыл бұрын
How to code??
@anthonygg_ Жыл бұрын
Press buttons
@TheMereth4 ай бұрын
damn so much work just to have required/optional parameters