Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

config: Use reflection #1480

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jonjohnsonjr
Copy link
Contributor

Our previous approach of playing whack-a-mole did not seem to work very well. This just replaces everything via reflection, with two notable exceptions:

  1. Some top-level fields in Configuration are meta-fields and not meant to be replaced by anything.
  2. Since subpackages support Range, we need to expand them before calling replace() on them.

This approach won't scale very well if we add sub-fields to structs that shouldn't support string replacement or if we add top-level fields to Configuration that need replacement (we will need to update this code).

One approach for dealing with both of these things would be to use struct tags to explicitly mark fields as non-replaceable and handle these exceptions in the reflection code by just skipping over them. That's more complicated than I intend for this change, so I'm going to punt on that for now, but we should consider it if this new code doesn't hold up to the test of time.

Our previous approach of playing whack-a-mole did not seem to work very
well. This just replaces everything via reflection, with two notable
exceptions:

1. Some top-level fields in Configuration are meta-fields and not
   meant to be replaced by anything.
2. Since subpackages support Range, we need to expand them before
   calling replace() on them.

This approach won't scale very well if we add sub-fields to structs that
shouldn't support string replacement or if we add top-level fields to
Configuration that need replacement (we will need to update this code).

One approach for dealing with both of these things would be to use
struct tags to explicitly mark fields as non-replaceable and handle
these exceptions in the reflection code by just skipping over them.
That's more complicated than I intend for this change, so I'm going to
punt on that for now, but we should consider it if this new code doesn't
hold up to the test of time.

Signed-off-by: Jon Johnson <[email protected]>
@luhring
Copy link
Contributor

luhring commented Sep 6, 2024

One approach for dealing with both of these things would be to use struct tags to explicitly mark fields as non-replaceable and handle these exceptions in the reflection code by just skipping over them. That's more complicated than I intend for this change, so I'm going to punt on that for now, but we should consider it if this new code doesn't hold up to the test of time.

Yeah, I think if we want to go the recursive reflection route, we'll need the struct tag piece sooner or later.

)

// replace takes the given T and recursively walks it, replacing any strings it encounters inside structs, maps, slices, etc with the given replacer.
func replace[T any](r *strings.Replacer, in T) T {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A test focused on this function would be nifty

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants