-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
zap.String with ~string generic #1275
Comments
Thanks for the issue, @bcspragu. s := zap.String
log.Info("foo", s("k", "v")) The above will fail to compile with the suggested change. However, I still think this functionality is valuable. func Str[T ~string](k string, v T) Field {
return String(k, string(v))
} If desirable, we can even expand that type constraint in the future to WDYT @prashantv @mway @sywhang? |
+1 on adding this functionality as a new function. I think this would be even more helpful for the slice functions like |
Agreed. One minor adjustment: let's parameterize both arguments. So: package fields // go.uber.org/zap/exp/fields
func Str[T ~string](key T, value T) zap.Field {
return zap.String(string(key), string(value))
} for package fields // go.uber.org/zap/exp/fields
func Strs[T ~string](key T, values []T) zap.Field {
return zap.Array(string(key), stringArray(values))
}
type stringArray[T ~string] []T
func (a stringArray[T]) MarshalLogArray(enc zapcore.ArrayEncoder) error {
for i := range a {
enc.AppendString(string(a[i]))
}
return nil
} In |
One minor adjustment to the minor adjustment. If you go this route for keys, you'll want to use two different generic args, otherwise they'll need to have the same underlying type. For example: type (
A string
B string
)
func main() {
a := A("key")
b := B("value")
test(a, b)
}
func test[T ~string](k T, v T) {
fmt.Println(k, v)
} will give you an error like func test[T ~string, U ~string](k T, v U) {
fmt.Println(k, v)
} For the use cases I have, I've never run into something where I'd need/want a non-string key, but I could imagine doing something like: package logkey
type Key string
const (
UserID LogKey = "user_id"
// ... more keys ...
) to have consistent keys throughout a codebase. All the other details here, like using |
Agreed. If we parameterize the key as well, it should be its own type parameter. So just to confirm, are we going for: func Str[K ~string, V ~string](k K, v V) Field
func Strs[K ~string, V ~[]S, S ~string](k K, v V) Field |
Thanks for catching. That'll teach me to write comments before caffeine. |
Yeah, IMO there's also no reason to not parameterize it for flexibility.
I had originally collapsed |
This all sounds good to me! As for next steps, I'm happy to pull together a PR, seems like the main open question is to put it in |
Given the low-risk nature of the change, I think putting this in |
We just need to be willing to commit to the API if we elect for a non- |
Thanks, @bcspragu for volunteering. I discussed this with @sywhang and @mway and we agree that it makes sense to prove it out in exp before upgrading to top-level. Would you mind placing it in |
Implements uber-go#1275 by adding new `zapfield.Str` and `zapfield.Strs` types, which operate on generic string-like types and use the underlying `zap.String` and `zap.Strings` codepaths. In uber-go#1275, the decision was to put these in a separate `zap/exp/zapfield` package and I didn't see an existing one, so I made a new `zapfield` package.
Sounds like a plan to me, I've kicked this off in #1281 |
Since this is now available in the zap/exp/zapfield package, will close this issue. We can evaluate promoting it to a top-level field in some time. |
Is your feature request related to a problem? Please describe.
Frequently, we'll want to log something defined as:
And to log it presently, we'll have to do something like:
Which includes a lot of
string(...)
conversions, that are mostly unnecessary now that generics exist.Describe the solution you'd like
The solution I'm proposing is to change the type of
zap.String
from:to
This is purely a convenience thing, but it removes a lot of casting that clutters up our logging code. AFAICT, this should be backwards compatible, and generics are already in use in the latest release. The same strategy could be applied to all the other primitive-type
zap.Field
helpers to simplify end-user code a bit.Describe alternatives you've considered
The
zap.Stringer
helper is closely related, but doesn't help thetype X string
use case, which is a pretty common idiom in Go.Is this a breaking change?
Nope! Should totally be backwards compatible. Existing
string(x)
casts will work fine, but future ones can be reduced to justx
.Additional context
This change would take about 37 seconds to implement, happy to contribute that if folks are interested. Also, apologies if this has come up before, I tried searching issues for it, but came up empty handed. Searching for
"~string"
didn't give me anything relevant AFAICT.The text was updated successfully, but these errors were encountered: