-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: strconv: add generic integer variants #67110
Comments
See also #57975 which proposed |
Thx, I've updated the proposal to only include I don't see rational behind the useless generics argument here. Finally implementing it can be do with foldable types checking tricks thx there can only be integers, no need for reflect. |
What are "foldable" types and what are their tricks? I have never heard this term in the context of Go. |
@gophun for example see |
I still feel like I did on #57975: parsing any type is too much, but a narrowly tailored integer parser would be useful. I prefer a pointer-based API because you can omit // if new parse / format functions for new integers types are added, they would also be added there.
type integers interface{ uint | uint8 | uint16 | uint32 | uint64 | uintptr | int | int8 | int16 | int32 | int64 }
// Integer is like calling the matching Parse${T} with bitSize being the type's size.
func Integer[T ~integers](ptr *T, v string, base int) error
// FormatInteger is like calling the matching Format${T}, it accept 2 <= base <= 36.
func FormatInteger[T ~integers](v T, base int) string
// Usage
n := defaultValue
strconv.Integer(&n, s, 10) // Can ignore the return value if your usecase just falls back to defaultValue |
@earthboundkid maybe, looks subjective to me, FWIW it's more tokens. But as long it's not a runtime |
Change https://go.dev/cl/582575 mentions this issue: |
I implemented this in https://go-review.googlesource.com/c/go/+/582575 to prove this completely dodge questions about import cycles and |
The version without a pointer comes out significantly longer for the not uncommon case of not caring about the error: n := defaultValue // let's say this is an int32
if v, err := strconv.Integer[int32](s, 10); err == nil {
n = v
} |
Another way to do it would be to get the unsafe.Sizeof, no? Edit: Playground |
You can use |
#60274 would be useful here. The pointer version of n := defaultValue // let's say this is an int32
if v, err := strconv.Integer[int32](s, 10); err == nil {
n = v
} is n := defaultValue
var v int32
if strconv.Integer(&v, s, 10) == nil {
n = v
} so you're not saving a great deal unless The first looks clearer to me and the second makes it easier to write strconv.Integer(&v, "oops, always zero!", 10) |
If it’s using a pointer and there’s an error, it shouldn’t write a zero into the pointer. It should just leave it alone. So then you can drop the whole if statement and assignment. |
See #29982 which would move Sizeof out of unsafe. |
Proposal Details
I had an argument with @ldemailly on what is the least ugly to stringify a
~uint8
(typediota
enum) to a base ten number.strconv.FormatUint(uint64(i), 10)
is verbose so it seems people would enjoy usingstrconv.Itoa
more, howeverItoa
is easy to use incorrectly, it may truncate on 32 bits platforms and is signed which might or might not be what you want to do. (search 13k results, this is popular)I propose theses new functions:
The idea is you don't bother thinking about what the best function is, what type conversion you need to do or what
bitsize
should be set to.You just call
ParseInteger
orFormatInteger
with the type you want, and let the type checker handles the tricky bits for you.The text was updated successfully, but these errors were encountered: