Closed adonovan closed 6 months ago
See also #45320, #63544.
Worth noting that in addition to the list of examples above, there are a number of constants especially in the compiler and runtime defined as both Booleans and integers for the purpose of feature detection in different contexts; see e.g.
Since converting a constant to a type that is not a type parameter type results in a constant, this change would allow the integer versions to go away. That's an important feature of a language change over e.g. #61915.
In the analysis the if
/if-else
and return
are two different species. if
/if-else
is the use of an int(bool)
conversion and return
is the definition of an int(bool)
converter which was, presumably defined so as to be used more than once. A second pass would be needed to find the invocations of these converters to compare with the if
/if-else
usages. Possibly not worth doing but important to consider when evaluating the results.
The proposal mentions that float64 and complex128 not supported, but what about other integer types? Are int32(x != 0)
and uintptr(x != 0)
considered, or is it sufficient to always convert through int
?
I don't know about uintptr
, but I think supporting other integers like uint32
would be beneficial. I have use for this in a CPU emulator:
https://github.com/fzipp/oberon/blob/ebf0a23b7c5422dda878336f07d5c4b31c1919d8/risc/risc.go#L245-L248
https://github.com/fzipp/oberon/blob/ebf0a23b7c5422dda878336f07d5c4b31c1919d8/risc/risc.go#L623
In response to https://github.com/golang/go/issues/64825#issuecomment-1865232867, I updated the proposal to clarify that it includes all integer types.
The proposal text mentions writing a "less" comparison func for bools, but does not mention the increasingly-common "cmp" comparison functions (used by slices.SortFunc
, slices.BinarySearchFunc
, and so on). That is where I most miss an int(bool)
conversion.
(Related to the declined proposal #61643.)
With this you could write
func Compare(x, y int) int {
return int(x > y) - int(x < y)
}
I don't know if that's good or bad. 😆
This proposal has been added to the active column of the proposals project and will now be reviewed at the weekly proposal review meetings. — rsc for the proposal review group
Would supporting the bool->int conversion mean the following is valid?
var a int = x > y || b
No, it's an explicit conversion. It would be either
var a int = int(x > y || b)
or
a := int(x > y || b)
Every language change carries significant constant costs to update everything - tools, books, docs, etc - and the data (2,700 potential non-machine-generated uses in 19,000 modules) seems to show that this would be used about 0.2 times per module, which doesn't seem worth it.
Assuming this gets declined, then in a separate issue, we may still want to make sure the compiler will handle code like this correctly:
func bool2int(b bool) int {
if b {
return 1
}
return 0
}
That way people can still write their own version and know it will be handled properly.
I think that particular form is not compiled today as efficiently as it could be, but if you write it instead as:
func bool2int(b bool) int {
x := 0
if b {
x = 1
}
return x
}
...then it compiles down to MOVBLZX
on amd64 (Godbolt link).
It is already basically handled properly.
At every callsite of bool2int
, it is inlined and uses the right instructions - a single sign-extend.
bool2int
by itself does not use the right instructions, but that's probably not a real issue. No one is going to be calling this indirectly.
As this proposal states, discussion of efficiency here is a distraction, just as it was a distraction in #9367.
This is purely about writing clear and concise code.
Right now, it's annoying to deal with bools when writing some kinds of expressions, particularly comparisons, in a way that dealing with other basic data types like integers and strings is not. This is particularly true for the func(X, X) int
("cmp") functions that are becoming common in the standard library as of the last few releases, and which are not yet broadly reflected in the existing corpus of code.
I'm sure that if we look, we can find plenty of language changes that will be used by less than 20% of modules. (Not to mention existing language features. What percentage of modules use complex types?)
As remarked in https://github.com/golang/go/issues/61915#issuecomment-1676512804 and this thread, one of the things that cannot be done now is use of bool→int in constants. That requires a language change.
I would also like to reiterate that the analysis undercounts in multiple ways so the numbers provided are a floor. I'm also not sure why we're not counting machine generated modules. Use in machine generated code should be weighted less, sure, but not discarded. It's still evidence of real-world use.
I'm also not sure use-per-module is the right proxy. I've written modules that don't use floating point numbers that doesn't make them less useful.
Based on the discussion above, this proposal seems like a likely decline. — rsc for the proposal review group
Personally I'd be sad if we punt on this addition once again. I very much relate to Alan's original points that it feels like an omission in the language that makes it somewhat inconsistent. I've had to write this function five times in the past handful of years, which is certainly not often, but each time I'm left with the impression that it's a silly situation to be in.
In that way, I see this proposal as being very similar to min
and max
- we could have declined that proposal using very similar arguments, but having the built-ins makes some Go code easier to write and maintain. I was lukewarm on the proposal when it was first opened, but now that I have the builtins, I definitely wouldn't give them up.
It's true that every language change carries its cost, but in this case, I honestly feel like the cost is tiny. We should weigh quality of life improvements for human developers in the long term over minimal tooling pain in the short term, I think.
I filed an alternative proposal: #66062.
One thought I had: if the solution being a language change is what is keeping this proposal from being a net positive, we could always consider a builtin function like func oneif(b bool) int
. That is the name I've personally chosen in the past for explicitness; bool2int
as a name would feel like a weird way to sidestep bool(int)
.
The fact that this has been requested so many times by different people seems to indicate that there is a need here. It's a simple and obvious feature request, I don't understand the resistance against it.
@zephyrtronium
Worth noting that in addition to the list of examples above, there are a number of constants especially in the compiler and runtime defined as both Booleans and integers for the purpose of feature detection in different contexts; see e.g.
Since converting a constant to a type that is not a type parameter type results in a constant, this change would allow the integer versions to go away. That's an important feature of a language change over e.g. #61915.
I agree with this 100%: currently it's possible to convert 0/1
to false/true
via x != 0
in a constant expression, but it has always bothered me that there is no way to convert false/true
to 0/1
in the same way. Often times I've had to resort to keeping all of my consts as ints to make them usable in constant expression calculations when it makes much more sense for them to be bools.
@gh2o
Often times I've had to resort to keeping all of my consts as ints to make them usable in constant expression calculations when it makes much more sense for them to be bools.
It may be helpful if you can share places you've done that. Examples of people actually needing int(bool) conversions in a capacity that a function cannot replace is probably the most important kind of information for the proposal process.
@zephyrtronium
One example I found in the go codebase itself: if these files were not auto-generated, I think it does make more sense for these values to be bools instead of ints from a type correctness standpoint.
Decline doesn't mean that it will never happen, just that it won't happen now. We have limited time, and as more and more things build on Go, every change becomes more difficult to make, because it requires updating everything above it in the stack.
I'm sure approximately nothing uses complex types. If Go didn't have them today, I think we would decline adding them pretty quickly. It was much easier to add things back then. The bar is always moving up, for better or worse.
Another example from the Go tree: https://github.com/golang/go/blob/go1.22.1/src/internal/goexperiment/exp_allocheaders_on.go Having written a fair amount of code using the GOOS and GOEXPERIMENT int constants, I agree it's very annoying. :)
Are there examples not from the Go tree itself? This pattern is unfortunately not captured by the ecosystem analysis (and I'm not sure how you'd do it reliably).
The analyzer I used is at https://go.dev/cl/550235, where it will remain in deep cryostorage until needed again.
Based on the discussion above, this proposal seems like a likely decline. — rsc for the proposal review group
No change in consensus, so declined. — rsc for the proposal review group
I'm surprised by these assessments by the proposal review group. The discussion here seems overwhelmingly in favor of adding these conversions. E.g., there are as many thumb-up "votes" on this issue already as there were on #59488, which added the min
and max
builtins.
Proposal #46505 to allow ArrayType(sliceValue)
conversions as shorthand for *(*ArrayType)(sliceValue)
(a much smaller and more niche convenience than this proposal) had fewer thumbs ups. I pointed out the same hesitation around tooling impacts (https://github.com/golang/go/issues/46505#issuecomment-852851640) and again (https://github.com/golang/go/issues/46505#issuecomment-897214942), yet the proposal group accepted that.
@ianlancetaylor argued:
That is true, of course, but the resulting code seems to me to be clearer and more straightforward. Why not take the minor win?
Doesn't this argument hold even more strongly for allowing users to write func() IntType { if boolExpr { return 1 }; return 0 }()
as IntType(boolExpr)
than it did for allowing *(*ArrayType)(sliceExpr)
as ArrayType(sliceExpr)
?
Worth mentioning there are many more examples under the b2i name out in the wild than those mentioned. This pattern is especially present in embedded systems programming. Here are more examples under the b2u8 name, mostly belonging to the embedded ecosystem of Go.
Worth mentioning there are many more examples under the b2i name out in the wild than those mentioned. This pattern is especially present in embedded systems programming. Here are more examples under the b2u8 name, mostly belonging to the embedded ecosystem of Go.
Don't forget to enable the "Exclude Go vendor" filter in the left pane.
BTW this is my favorite of all of them, which uses "unsafe" to make it faster. The difference is "almost unnoticeable", but every picosecond counts!
BTW this is my favorite of all of them, which uses "unsafe" to make it faster. The difference is "almost unnoticeable", but every picosecond counts!
I wish GitHub offered "☠️" as a reaction.
Based on the discussion above, this proposal seems like a likely decline.
Funny that happend after two encouraging comments by well-known gophers. Really sad the Go team played this as it is.
The discussion here seems overwhelmingly in favor of adding these conversions.
That's exactly how I read the discussion.
Now I'm stuck with being able to do string([]byte) but not int(bool). And much less bool(int).
We have limited time, and as more and more things build on Go, every change becomes more difficult to make, because it requires updating everything above it in the stack.
Given that it would be great if the community could weigh in in prioritising changes instead of just singular yes/no votes?
And much less bool(int).
That's trivially i != 0
. There's not a lot of point in adding it except symmetry.
There is no denying this would occasionally be useful. The problem is balancing overall churn against that utility. If someone is very excited about this change, the usual way to make the case (or not) would be to prepare a small stack of CLs showing (1) the spec changes, (2) the compiler and go/types changes, and (3) updating all the code in the main repo to use it as effectively as possible. (1) and (2) show that there is not too much involved (although there is always more to do in programs like staticcheck and gopls), and (3) demonstrates the benefits. I am still skeptical that the benefits will be large enough, but we definitely missed the ones @aclements pointed out in package runtime, of not having to maintain pairs of aligned constants. We can just emit the booleans and convert them in constant expressions as needed. Maybe there are others we missed too. The diffs for (3) are what matter most: demonstrate benefits justifying the cost in (1) and (2).
Composing int(bool)
with strings.Repeat
gives you optional strings, still in expression context, and without allocating:
fmt.Printf("%s.(%s).%s", // e.g. "bytes.(*Buffer).WriteString"
packageName,
strings.Repeat("*", int(isPtr)), // optional *
typeName,
methodName)
Too much talk... let's implement this feature already! I mean.. I do never get a technical reason for not doing this... you may peek at the summary I have made regarding the state of this, here.
You can use nstd.Btoi at the time, though it has not the type inference convenience.
I am in support of this. This missing feature is the one reason I would still use c.
This missing feature is the one reason I would still use c.
While I appreciate the vote of support for this late proposal, I question the wisdom of your choices. ;-)
Proposal Details
I propose, a second time, the following language change first proposed for go1.5 in #9367:
An explicit conversion
int(b)
, whereb
has a boolean type andint
stands for any integral type, would become legal and would yield 1 ifb
is true, 0 otherwise.Rationale: currently this function cannot be computed in a single expression, despite it being often useful, hard to misuse, present in nearly all other languages, and syntactically natural in Go. As a corollary, there is currently no simple way to derive an integer constant from a boolean constant.
While I appreciate the value of avoiding implicit int-to-bool conversions, forbidding explicit ones seems slightly obtuse, and as a result of its omission, one must write four extra lines of code:
Also, consider implementations of sort.Interface.Less that define a total order over tuples. They consist of a sequence of operations, one per column (x, etc) of the tuple, of this form:
For booleans, the
<
operator must be expressed as the opaque!a[i].x && a[j].x
. It would be easier to readint(a[i].x) < int(a[j].x)
.The motive here is brevity and clarity, not efficiency. I am confident that a good compiler can avoid the branch. The concern with efficiency in the previous proposal was a distraction, and it has been dealt with separately.
We do not propose to support the reverse operation,
bool(i)
, as one can already sayi != 0
in expression context (and it's shorter). Also,i != 0
makes the semantics explicit, wherebool(i)
could potentially be misinterpreted asi > 0
,i == 1
,i == max[u]int
,i == -1
, ori & 1 == 1
, all of which are representations of "true" used in other languages; and George Boole would have argued that the bool(int) function is simply not defined for values other than zero and one.We also do not propose to support
float64(b)
andcomplex128(b)
. Though consistent, there is little need for such conversions, and they can easily be implemented in two steps, still within expression context, for examplefloat64(int(b))
.In https://go.dev/cl/550235, I measured the occurrence of code snippets like the one above. Across about 19,000 modules, there are about 10K places where an if/else statement is used to simulate an int(bool) conversion. (I didn't attempt to find places where if/else was used to compute bool < bool, as is common in sort.Interface.Less implementations.) Of those, I ignored the ~5.5K in generated .pb.go files, and the ~2K in copies of github.com/wzzhu/tensor, leaving about 2700 more interesting cases. Here's a random sample of a few dozen:
https://go-mod-viewer.appspot.com/bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/ntp_unix.go#L76: [if]: current_source = int(fl == "") https://go-mod-viewer.appspot.com/cosmossdk.io/client/v2@v2.0.0-beta.1/internal/testpb/query.pulsar.go#L2731: [if-else]: dAtA[i] = int(x.Bools[iNdEx]) https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/randr/randr.go#L3797: [if-else]: buf[b] = int(Delete) https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L10065: [if-else]: buf[b] = int(Delete) https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L10719: [if-else]: buf[b] = int(OwnerEvents) https://go-mod-viewer.appspot.com/github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xproto/xproto.go#L3668: [if-else]: buf[b] = int(v.OverrideRedirect) https://go-mod-viewer.appspot.com/github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/sm4/sm4_gcm.go#L77: [return]: return int(temp&0x01 == 1) https://go-mod-viewer.appspot.com/github.com/XiaoMi/Gaea@v1.2.5/mysql/resultset_sort.go#L132: [return]: return int(v > s) https://go-mod-viewer.appspot.com/github.com/andybalholm/brotli@v1.0.6/brotli_bit_stream.go#L306: [if-else]: tmp = int(depths[symbols[0]] == 1) https://go-mod-viewer.appspot.com/github.com/andybalholm/brotli@v1.0.6/decode.go#L1282: [if-else]: s.should_wrap_ringbuffer = int(uint(s.pos) != 0) https://go-mod-viewer.appspot.com/github.com/apache/arrow/go/v13@v13.0.0/arrow/compute/internal/exec/span.go#L280: [if-else]: a.Nulls = int(val.IsValid()) https://go-mod-viewer.appspot.com/github.com/apache/arrow/go/v14@v14.0.1/internal/bitutils/bitmap_generate.go#L85: [if-else]: outResults[i] = int(g()) https://go-mod-viewer.appspot.com/github.com/aviddiviner/docopt-go@v0.0.0-20170807220726-d8a1d67efc6a/docopt.go#L433: [if]: argcount = int(eq == "=") https://go-mod-viewer.appspot.com/github.com/blevesearch/geo@v0.1.18/s2/edge_clipping.go#L148: [if]: ai = int(a.X > b.X) https://go-mod-viewer.appspot.com/github.com/btccom/go-micro/v2@v2.9.3/api/router/static/static.go#L232: [if]: idx = int(len(req.URL.Path) > 0 && req.URL.Path != "/") https://go-mod-viewer.appspot.com/github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/sstable/writer_test.go#L923: [if]: expectedLength = int(expectedIntersects) https://go-mod-viewer.appspot.com/github.com/consensys/gnark-crypto@v0.12.1/ecc/bw6-761/fr/fri/fri.go#L309: [if-else]: fullMerkleProof = int(len(pp.Rounds[0].Interactions[0][0].ProofSet) > len(pp.Rounds[0].Interactions[0][1].ProofSet)) https://go-mod-viewer.appspot.com/github.com/coreservice-io/utils@v0.3.0/version_util/version.go#L81: [return]: return int(a.tail > b.tail) https://go-mod-viewer.appspot.com/github.com/cosmos/cosmos-proto@v1.0.0-beta.3/internal/testprotos/test3/test.pulsar.go#L6416: [if-else]: dAtA[i] = int(x.RepeatedBool[iNdEx]) https://go-mod-viewer.appspot.com/github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/boolean.go#L187: [if-else]: d = int(wasNull || !val) https://go-mod-viewer.appspot.com/github.com/dop251/goja@v0.0.0-20231027120936-b396bb4c349d/ftoa/ftoa.go#L614: [if]: stop = int(len(buf) > 0 && buf[0] == '-') https://go-mod-viewer.appspot.com/github.com/dotcloud/go-redis-server@v0.0.0-20130830204822-e4d48d56d178/auto.go#L174: [if]: start = int(mtype.NumIn() > 0 && mtype.In(0).AssignableTo(reflect.TypeOf(autoHandler))) https://go-mod-viewer.appspot.com/github.com/dubbogo/gost@v1.14.0/time/timer.go#L118: [if-else]: ret = int(first.trig > second.trig) https://go-mod-viewer.appspot.com/github.com/fraugster/parquet-go@v0.12.0/type_boolean.go#L91: [if]: v = int(values[i].(bool)) https://go-mod-viewer.appspot.com/github.com/gagliardetto/binary@v0.7.9/encoder.go#L189: [if]: num = int(b) https://go-mod-viewer.appspot.com/github.com/golang-commonmark/markdown@v0.0.0-20180910011815-a8f139058164/blockquote.go#L160: [if]: d = int(spaceAfterMarker) https://go-mod-viewer.appspot.com/github.com/hyperledger/fabric-amcl@v0.0.0-20230602173724-9e02669dceb2/core/FP256BN/FP4.go#L214: [if-else]: u = int(F.a.iszilch()) https://go-mod-viewer.appspot.com/github.com/intel/goresctrl@v0.5.0/pkg/blockio/oci_test.go#L95: [if]: expectedErrorCount = int(len(tc.expectedErrorSubstrings) > 0) https://go-mod-viewer.appspot.com/github.com/intel/goresctrl@v0.5.0/pkg/sst/sst_if.go#L109: [if]: ReadWrite = int(doWrite) https://go-mod-viewer.appspot.com/github.com/jezek/xgb@v1.1.1/xprint/xprint.go#L639: [if-else]: buf[b] = int(Cancel) https://go-mod-viewer.appspot.com/github.com/jezek/xgb@v1.1.1/xproto/xproto.go#L7364: [if-else]: buf[b] = int(DoAcceleration) https://go-mod-viewer.appspot.com/github.com/la5nta/wl2k-go@v0.11.8/rigcontrol/hamlib/rigctld.go#L168: [if]: bInt = int(on == true) https://go-mod-viewer.appspot.com/github.com/m3db/m3@v1.5.0/src/dbnode/persist/fs/msgpack/stream.go#L170: [if]: unreadBytes = int(s.unreadByte != -1) https://go-mod-viewer.appspot.com/github.com/m3db/m3@v1.5.0/src/dbnode/storage/bootstrap_instrumentation.go#L180: [if]: status = int(isBootstrapped) https://go-mod-viewer.appspot.com/github.com/mitchellh/go-vnc@v0.0.0-20150629162542-723ed9867aed/pixel_format.go#L111: [if-else]: boolByte = int(format.TrueColor) https://go-mod-viewer.appspot.com/github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/atomicbitops/bool.go#L34: [if]: u = int(val) https://go-mod-viewer.appspot.com/github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/state/wire/wire.go#L88: [if-else]: v = int(b) https://go-mod-viewer.appspot.com/github.com/oasisprotocol/ed25519@v0.0.0-20210505154701-76d8c688d86e/internal/modm/modm_64bit.go#L736: [if]: cmp = int(i == 0) https://go-mod-viewer.appspot.com/github.com/onosproject/onos-api/go@v0.10.32/onos/config/v3/typedvalue.go#L877: [if]: intval = int(b) https://go-mod-viewer.appspot.com/github.com/parquet-go/parquet-go@v0.20.0/row_buffer_test.go#L146: [if]: definitionLevel = int(!node.Required()) https://go-mod-viewer.appspot.com/github.com/peske/x-tools@v0.0.0-20221212040959-717b025fabf0/cmd/goyacc/yacc.go#L2126: [if]: nolook = int(tystate[i] != MUSTLOOKAHEAD) https://go-mod-viewer.appspot.com/github.com/pion/webrtc/v3@v3.2.24/atomicbool.go#L27: [if]: i = int(value) https://go-mod-viewer.appspot.com/github.com/pocketbase/pocketbase@v0.20.0/forms/admin_upsert_test.go#L160: [if]: expectInterceptorCall = int(s.expectError) https://go-mod-viewer.appspot.com/github.com/polarismesh/polaris@v1.17.8/store/mysql/strategy.go#L80: [if]: isDefault = int(strategy.Default) https://go-mod-viewer.appspot.com/github.com/regen-network/regen-ledger/api/v2@v2.3.0/regen/ecocredit/marketplace/v1/state.pulsar.go#L515: [if-else]: dAtA[i] = int(x.Maker) https://go-mod-viewer.appspot.com/github.com/regen-network/regen-ledger/api@v1.1.0/regen/ecocredit/marketplace/v1/tx.pulsar.go#L2785: [if-else]: dAtA[i] = int(x.DisableAutoRetire) https://go-mod-viewer.appspot.com/github.com/regen-network/regen-ledger/api@v1.1.0/regen/ecocredit/v1alpha1/types.pulsar.go#L2460: [if-else]: dAtA[i] = int(x.AllowlistEnabled) https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/glx/glx.go#L1494: [if-else]: buf[b] = int(IsDirect) https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/randr/randr.go#L3804: [if-else]: buf[b] = int(Pending) https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/shape/shape.go#L130: [if-else]: buf[b] = int(v.Shaped) https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xproto/xproto.go#L10719: [if-else]: buf[b] = int(OwnerEvents) https://go-mod-viewer.appspot.com/github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xproto/xproto.go#L7614: [if-else]: buf[b] = int(Exposures) https://go-mod-viewer.appspot.com/github.com/sajari/fuzzy@v1.0.0/fuzzy.go#L255: [if-else]: temp = int((a)[j-1] == (*b)[i-1]) https://go-mod-viewer.appspot.com/github.com/segmentio/parquet-go@v0.0.0-20230712180008-5d42db8f0d47/file.go#L692: [if]: f.index = int(f.dictOffset > 0) https://go-mod-viewer.appspot.com/github.com/shakinm/xlsReader@v0.9.12/xls/workbook.go#L107: [if-else]: grbitOffset = int(len(wb.sst.RgbSrc) == 0) https://go-mod-viewer.appspot.com/github.com/thanos-io/thanos@v0.32.5/pkg/store/cache/caching_bucket_test.go#L442: [if]: expectedHitsDiff = int(expectedCache) https://go-mod-viewer.appspot.com/github.com/u2takey/go-utils@v0.3.1/strings/string.go#L225: [if]: i = int(strings.Index(str, \u) > 0) https://go-mod-viewer.appspot.com/github.com/uadmin/uadmin@v0.10.1/setting.go#L522: [if]: n = int(v) https://go-mod-viewer.appspot.com/github.com/zhangzhaojian/go-mongodb@v1.1.0/mongo/collection.go#L388: [if]: limit = int(deleteOne) https://go-mod-viewer.appspot.com/go.etcd.io/raft/v3@v3.0.0-20231213110755-8757de38ed2c/rawnode_test.go#L325: [if]: maybePlusOne = int(ok && autoLeave) https://go-mod-viewer.appspot.com/go.flow.arcalot.io/pluginsdk@v0.7.0/schema/function.go#L322: [if]: expectedReturnVals = int(f.StaticOutputValue != nil || f.DynamicTypeHandler != nil) https://go-mod-viewer.appspot.com/go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/internal/compile/serial.go#L207: [return]: return int(b) https://go-mod-viewer.appspot.com/gopkg.in/olebedev/go-duktape.v1@v1.0.0-20151008052556-e2ae92f01e4a/api.go#L947: [if]: val = int(val)
And here are all occurrences in the standard library:
src/runtime/proc.go:5422:2: [if]: run0 = int(!iscgo && cgoHasExtraM && extraMLength.Load() > 0) src/runtime/symtab.go:1062:2: [if]: mask = int(off == ^uint32(0)) src/reflect/abi.go:380:3: [if]: x = int(b.Get(i)) src/time/format.go:417:2: [if]: n = int(u == 0) src/compress/flate/huffman_bit_writer.go:405:2: [if]: flag = int(isEof) src/encoding/binary/binary.go:348:4: [if-else]: bs[0] = int(*v) src/encoding/binary/binary.go:354:4: [if-else]: bs[0] = int(v) src/encoding/binary/binary.go:361:5: [if-else]: bs[i] = int(x) src/encoding/binary/binary.go:546:2: [if-else]: e.buf[e.offset] = int(x) src/math/big/float.go:1377:2: [if]: sbit = int(len(r) > 0) src/math/big/nat.go:235:3: [if-else]: c = int(cx < c2 || cy < c3) src/crypto/x509/pkcs1.go:108:2: [if]: version = int(len(key.Primes) > 2) src/internal/zstd/zstd.go:210:2: [if-else]: windowDescriptorSize = int(singleSegment) src/go/printer/nodes.go:619:5: [if]: min = int(prev != nil && name == prev) src/go/types/mono.go:198:3: [if]: weight = int(typ == targ) src/internal/pkgbits/encoder.go:275:2: [if]: x = int(b) src/compress/flate/deflate_test.go:180:3: [if-else]: b[i] = int(r.cur+int64(i) >= r.l-1<<16) src/go/scanner/scanner_test.go:735:2: [if]: cnt = int(err != "") src/go/types/hilbert_test.go:153:4: [if]: v = int(i == j) src/strings/builder_test.go:105:3: [if]: wantAllocs = int(growLen == 0) src/unicode/utf8/utf8_test.go:168:3: [if]: wantsize = int(wantsize >= len(b))