golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.31k stars 17.7k forks source link

proposal: cmd/vet: add check for common error mishandling pattern #20148

Open robpike opened 7 years ago

robpike commented 7 years ago

People have proposed adding a test to vet to catch certain unused errors. This can be very noisy, and there are many cases where the error is genuinely known to be nil and can be ignored, such as in a call to bufio.Writer.Write. Therefore a general "unused error" check will be too noisy and fail the precision criterion described in cmd/vet/README.

However, my project has been badly bitten twice recently by a particular problem of unused errors that should be caught. The two looked schematically like these snippets:

func e() error { ... }
var err error

# Error value not caught in if init:
if e(); err != nil {...}

# Error value not caught before if:
e()
if err != nil { ... }

I did some experiments to catch calls to functions with the type of e that did not catch the error, and found too may false positives for things like os.Setenv.

However, since the real problem isn't that the error is discarded, but that it is discarded immediately before a check, I think it's worth trying a more targeted approach, one that would catch both of the problems in the snippets above.

The -unusedresult flag, on by default, already checks for things like calls to fmt.Sprintf where the value is not used, which is clearly a bug - there is no other reason to call fmt.Sprintf. That check works with a whitelist, but the problems in the examples above involved local functions that would never appear on a whitelist unless explicitly added when vet is called, which is error-prone (and not done in general).

I therefore propose to add to the -unusedresult check a test for the specific case with these three properties:

  1. a call to a function that returns an error as one of its possibly several arguments;
  2. return values from the function are dropped (no explicit _);
  3. the next statement reads a variable of type error.

It's point 3 that makes this work, I think, eliminating almost all the noise from calls to things like os.Setenv while catching the real bugs. If you just called an error function and then ask about the error, if there's no flow from the call to the check, you almost certainly made a mistake.

Regarding the criteria:

Correctness: This is a real bug, and it's bitten our project twice with severe security problems as a result. This is a problem that needs fixing.

Frequency: It's hit our project twice, and our project isn't big. I believe the severity is high enough that even a modest frequency of hits justifies the fix. If I implement this, I predict it will find more.

Precision: I believe that rule 3 in this proposal should make it precise enough.

griesemer commented 7 years ago

This seems worthwhile doing. I think the proof is in the pudding - let's implement it and see if it can be made to work as advertised.

dlsniper commented 7 years ago

Hi,

I'm not sure about the full context of those issues, but both these tools would catch the error, with this code https://play.golang.org/p/pkaWAqDUY0 as an example:

Both of them are included in this other tool: https://github.com/alecthomas/gometalinter

I wonder if rather than having the effort duplicate, more gophers should be made aware by these tools via the https://golang.org website by adding a (third-party) tooling section (cc @rakyll). Or do you think having this check in the vet tool would bring any advantage over the existing tools in the ecosystem?

Thank you.

ianlancetaylor commented 7 years ago

This is a refinement of #19727.

dominikh commented 7 years ago

It's worth pointing out that neither staticcheck nor errcheck fulfill Rob's requirements. Staticcheck doesn't actually catch this problem at all (yet), its output for https://play.golang.org/p/pkaWAqDUY0 is complaining about something unrelated. Errcheck does catch the issue – being the canonical tool for finding unchecked errors – but it's also a tool that's too noisy for a lot of people, see Rob's original message that mentions bufio.Writer.Write.

kevinburke commented 7 years ago

On a slightly related note: I sometimes try to make it impossible to have this problem by trying to never reuse an error; specifically to never assign to an error value with =.

Sometimes I get caught up though with code like this:

val, err := doSomething()
if err != nil {
    return err
}

val2, err2 := doSomethingElse()
if err2 != nil {
    return err
}

And then get confused why I'm returning nil from the function.

cznic commented 7 years ago

I sometimes try to make it impossible to have this problem by trying to never reuse an error; specifically to never assign to an error value with =.

I would go the opposite way. It's the := which causes the trouble. (While being undeniably handy in almost every other situation.)

rsc commented 7 years ago

Leaving on hold until @robpike has time to further explore a prototype.

velovix commented 7 years ago

I'm not especially comfortable with the idea of ignoring errors when they are generally expected not to happen. It doesn't sound like a good idea, but perhaps I don't understand just how unlikely these errors are. It seems like the best case scenario is that you save three lines of code to panic on the error, and the worse case is that your program silently fails in a potentially subtle way.

Is this something a lot of Gophers do in practice? Has anyone run errcheck against as sizeable amount of Go code to make sure this is the case?

velovix commented 7 years ago

I have since found out that fmt.Println returns an error, which is itself reason enough for me to be convinced that some errors should be ignored in practice.

leighmcculloch commented 7 years ago

One downside to introducing this into go get, is that while it would introduce less noise than if go vet mimicked errcheck, it would require us to write code that is not consistent. In some cases we may need to explicitly discard an error, in others we won't. Inconsistencies degrade readability because each inconsistency adds noise or calls attention to something that's different for a real reason. In this case the inconsistency would not aid the reader and may raise questions for the reader.

Example: If we need to call a function that returns an unimportant error, in between calling a function with an error and handling that error, we'll be required to insert _ = to signal an intent to discard the error.

fmt.Println("Welcome") // not required to signal intent to discard
n, err := doThing()
_ = metrics.Track("action", n, err) // required to signal intent to discard
if err != nil {
    handleError(err)
    return
}

But this is one downside and it seems like the benefits would out way it.

networkimprov commented 5 years ago

A solution via Go 2 Error Handling: https://github.com/golang/go/issues/20803#issuecomment-443411043

dgryski commented 4 years ago

I've found that nilness and ineffassign end up catching these cases.

timothy-king commented 3 years ago

I think these two cases are fairly distinct.

if e(); err != nil {...}

It seems like the checker Rob described should have a low false positive rate already for this case. I would be curious to see a prototype explore this.

e() if err != nil { ... }

Due to things like fmt.Println, more evidence seems needed here to infer intent. Knowing that err != nil is always false seems sufficiently precise. One can pick this back up from the control flow and conditions. I am not 100% on how the nilness pass works, but I am not surprised this would also report these. Example:

val, err := doSomething()
if err != nil {
    return err
}
e(val) // where e has an error return value.
if err != nil {...} // err must be nil due to the previous if

Weaker ways of inferring intent I can think of include:

dgryski commented 3 years ago

nilness does indeed catch the second case in your example. The data flow analysis notices that err must be nil (otherwise the function would have returned) and so warns the second err != nil check is redundant. Note that simply checking err != nil twice without the control flow change is not enough to trigger the check, unless the two checks are nested (again, causing the second check to be reundant).

yawaramin commented 3 years ago

Unless I'm misunderstanding something, this proposal wouldn't catch an issue I had recently:

func (c Client) Close() {
  c.Close() // returns type error
}

Not realizing that Close() returns an error, newcomers like myself may easily drop it without checking at all.

DeedleFake commented 3 years ago

Your problem there @yawaramin is that your outer function should be returning an error if you want to implement io.Closer. If it had, the compiler would have complained about a missing return, which would probably tip you off that you'd missed it.

adonovan commented 5 months ago

Some data from the module mirror corpus: running the proposed analyzer across 24000 modules, it reported 6800 diagnostics in 1200 modules. A random 50 are shown at the bottom. The majority seem to be false positives involving Close, of the following form:

err := f.Read()
f.Close()
if err != nil { ... }

or fmt.Println, which is bad form for errors, but not quite a bug:

res, err := f()
fmt.Println(res, err)
if err != nil { ... }

The analyzer could easily be taught to ignore both of these cases. The remainder, though a small fraction, include a number of obviously real bugs, such as these three:

The random 50:

https://go-mod-viewer.appspot.com/go.etcd.io/etcd@v3.3.27+incompatible/pkg/transport/timeout_transport_test.go#L67: call to resp.Body.Close discards error https://go-mod-viewer.appspot.com/gitee.com/openeuler/go-gitee@v0.0.0-20220530104019-3af895bc380c/gitee/api_gists.go#L1716: call to localVarHttpResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/Tanibox/tania-core@v0.0.0-20220210213334-ae75a069a958/src/growth/repository/sqlite/crop_read_repository.go#L110: call to f.DB.Exec discards error https://go-mod-viewer.appspot.com/github.com/spinnaker/spin@v1.30.0/gateapi/api_v2_pipeline_templates_controller.go#L779: call to localVarHttpResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/honeycombio/honeytail@v1.9.0/leash_test.go#L68: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/dnephin/dobi@v0.15.0/tasks/image/image.go#L79: call to wpipe.Close discards error https://go-mod-viewer.appspot.com/github.com/fastwego/offiaccount@v1.0.1/util/aes_crypto_test.go#L98: call to fmt.Println discards error https://go-mod-viewer.appspot.com/github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/cmd/root.go#L82: call to fmt.Fprintln discards error https://go-mod-viewer.appspot.com/github.com/Kong/go-pdk@v0.11.0/server/pbserver.go#L35: call to conn.Close discards error https://go-mod-viewer.appspot.com/github.com/EngineerKamesh/gofullstack@v0.0.0-20180609171605-d41341d7d4ee/volume3/section4/gopherface/middleware/gated.go#L30: call to fmt.Printf discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/beta/ActionService.go#L923: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/beta/ActionEducation.go#L1470: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/volatiletech/authboss@v2.4.1+incompatible/defaults/values.go#L218: call to r.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/free5gc/openapi@v1.0.8/Npcf_AMPolicy/api_default.go#L348: call to localVarHTTPResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/git-lfs/git-lfs@v2.5.2+incompatible/commands/command_fsck.go#L108: call to f.Close discards error https://go-mod-viewer.appspot.com/github.com/hashicorp/vault/sdk@v0.13.0/physical/inmem/cache_test.go#L50: call to inm.Delete discards error https://go-mod-viewer.appspot.com/github.com/antihax/goesi@v0.0.0-20240126031043-6c54d0cb7f95/esi/api_contacts.go#L1252: call to localVarHttpResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/ooni/oohttp@v0.7.2/fs_test.go#L1504: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/beta/ActionOffice.go#L394: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/nektos/act@v0.2.63/pkg/container/docker_pull.go#L62: call to logDockerResponse discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/beta/ActionCalendar.go#L499: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/beta/ActionManaged.go#L1833: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/bndr/gojenkins@v1.1.0/artifact.go#L66: call to a.validateDownload discards error https://go-mod-viewer.appspot.com/github.com/antihax/goesi@v0.0.0-20240126031043-6c54d0cb7f95/esi/api_market.go#L1218: call to localVarHttpResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/beta/ActionService.go#L820: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/free5gc/openapi@v1.0.8/Nudr_DataRepository/api_smsf3_gpp_registration_document.go#L167: call to localVarHTTPResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/btcsuite/btcwallet/walletdb@v1.4.2/walletdbtest/interface.go#L545: call to walletdb.View discards error https://go-mod-viewer.appspot.com/github.com/golangci/gofmt@v0.0.0-20231018234816-f50ced29576e/gofmt/long_test.go#L58: call to f.Close discards error https://go-mod-viewer.appspot.com/github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/middleware/auth.go#L240: call to c.Request.Body.Close discards error https://go-mod-viewer.appspot.com/golang.org/x/tools@v0.21.0/internal/imports/fix.go#L1363: call to d.Close discards error https://go-mod-viewer.appspot.com/github.com/optim-corp/cios-golang-sdk@v0.5.1/cios/api_device_asset.go#L586: call to localVarHTTPResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/free5gc/openapi@v1.0.8/Nudr_DataRepository/api_smsf_non3_gpp_registration_document.go#L256: call to localVarHTTPResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/minio/minio-go/v6@v6.0.57/core_test.go#L201: call to reader.Close discards error https://go-mod-viewer.appspot.com/github.com/palcoin-project/palcd@v1.0.0/rpcclient/infrastructure.go#L779: call to httpResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/v1.0/ActionDevice.go#L1759: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/free5gc/openapi@v1.0.8/Namf_Communication/api_individual_ue_context_document.go#L246: call to localVarHttpResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/evanw/esbuild@v0.21.4/internal/fs/fs_mock_test.go#L99: call to fs.ReadFile discards error https://go-mod-viewer.appspot.com/github.com/Finnhub-Stock-API/finnhub-go@v1.2.1/api_default.go#L3227: call to localVarHTTPResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/free5gc/openapi@v1.0.8/Nnef_PFDmanagement/api_notification.go#L70: call to localVarHTTPResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/xmidt-org/webpa-common@v1.11.9/bookkeeping/requestResponse.go#L21: call to request.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/beta/ActionData.go#L188: call to res.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/zmap/zcrypto@v0.0.0-20240512203510-0fef58d9a9db/x509/revocation/mozilla/mozilla.go#L213: call to resp.Body.Close discards error https://go-mod-viewer.appspot.com/git.prognetwork.ru/x0r/utls@v1.3.3/handshake_server_test.go#L331: call to c.Close discards error https://go-mod-viewer.appspot.com/github.com/juju/charm/v11@v11.2.0/charmdir.go#L523: call to file.Close discards error https://go-mod-viewer.appspot.com/gopkg.in/juju/charm.v6-unstable@v6.0.0-20171026192109-50d0c219b496/charmdir.go#L48: call to file.Close discards error https://go-mod-viewer.appspot.com/github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/archive.go#L148: call to tw.Close discards error https://go-mod-viewer.appspot.com/github.com/Bio-core/jtree@v0.0.0-20190705165106-1d7a7e7d6272/repos/experiment_repo.go#L89: call to stmt.Close discards error https://go-mod-viewer.appspot.com/gopkg.in/simversity/gottp.v3@v3.0.0-20160401065405-576cf030ca0e/tests/mock_server.go#L78: call to resp.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/launchdarkly/api-client-go@v5.3.0+incompatible/api_projects.go#L178: call to localVarHttpResponse.Body.Close discards error https://go-mod-viewer.appspot.com/github.com/yaegashi/msgraph.go@v0.1.4/v1.0/ActionContact.go#L387: call to res.Body.Close discards error

gopherbot commented 5 months ago

Change https://go.dev/cl/590376 mentions this issue: go/analysis/passes/unusedresult: evaluate issue 20148 heuristic

adonovan commented 5 months ago

Discarding Close and [Pp]rint, we get 1100 findings, of which a random 50 are shown here. Inspecting the first 10, four appear to be real bugs.

https://go-mod-viewer.appspot.com/github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/services/mux/mux_client.go#L173: call to conn.SetDeadline discards error https://go-mod-viewer.appspot.com/github.com/CanonicalLtd/go-sqlite3@v1.6.0/sqlite3_test.go#L257: call to res.RowsAffected discards error https://go-mod-viewer.appspot.com/github.com/Mrs4s/go-cqhttp@v1.2.0/internal/selfupdate/update_others.go#L43: call to fromStream discards error https://go-mod-viewer.appspot.com/github.com/NaverCloudPlatform/ncloud-sdk-go-v2@v1.6.13/services/clouddb/api_client.go#L320: call to bodyBuf.WriteString discards error https://go-mod-viewer.appspot.com/github.com/SupenBysz/gf-admin-community@v0.7.4/internal/logic/sys_user/sys_user.go#L659: call to g.Try discards error https://go-mod-viewer.appspot.com/github.com/WindomZ/go-commander@v1.2.2/exec.go#L49: call to os.Stderr.WriteString discards error https://go-mod-viewer.appspot.com/github.com/amitbet/vnc2video@v0.0.0-20190616012314-9d50b9dab1d9/fbs-reader.go#L99: call to binary.Read discards error https://go-mod-viewer.appspot.com/github.com/apache/arrow/go/v16@v16.1.0/arrow/flight/flight_middleware_test.go#L51: call to grpc.SetTrailer discards error https://go-mod-viewer.appspot.com/github.com/apache/arrow/go/v7@v7.0.1/arrow/flight/flight_middleware_test.go#L49: call to grpc.SetTrailer discards error https://go-mod-viewer.appspot.com/github.com/artyom/thrift@v0.0.0-20130902103359-388840a05deb/protocol_test.go#L172: call to p.WriteListEnd discards error https://go-mod-viewer.appspot.com/github.com/dtm-labs/rockscache@v0.1.1/batch.go#L99: call to c.rdb.Del(ctx, keys[idx]).Err discards error https://go-mod-viewer.appspot.com/github.com/ethereum/go-ethereum@v1.14.3/metrics/registry_test.go#L203: call to Register discards error https://go-mod-viewer.appspot.com/github.com/futurehomeno/fimpgo@v1.14.0/mqtt_transport_test.go#L256: call to mqtt.Subscribe discards error https://go-mod-viewer.appspot.com/github.com/git-lfs/git-lfs@v2.5.2+incompatible/commands/run.go#L78: call to closeAPIClient discards error https://go-mod-viewer.appspot.com/github.com/google/martian/v3@v3.3.3/header/forwarded_modifier_test.go#L72: call to m.ModifyRequest discards error https://go-mod-viewer.appspot.com/github.com/hanwen/go-fuse@v1.0.0/unionfs/autounion_test.go#L256: call to os.Symlink discards error https://go-mod-viewer.appspot.com/github.com/hanwen/go-fuse@v1.0.0/unionfs/autounion_test.go#L57: call to os.Mkdir discards error https://go-mod-viewer.appspot.com/github.com/infraboard/keyauth@v0.8.1/apps/tag/impl/tag.go#L30: call to s.value.InsertMany discards error https://go-mod-viewer.appspot.com/github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/api/datastore/mysql/mysql.go#L212: call to json.Unmarshal discards error https://go-mod-viewer.appspot.com/github.com/jordwest/imap-server@v0.0.0-20200627020849-1cf758ba359f/conn/command_store.go#L54: call to msg.Save discards error https://go-mod-viewer.appspot.com/github.com/kjk/siser@v0.0.0-20220410204903-1b1e84ea1397/pak/writer.go#L148: call to os.Remove discards error https://go-mod-viewer.appspot.com/github.com/kubernetes-incubator/kube-aws@v0.16.4/pkg/api/deployment.go#L159: call to subnet.Validate discards error https://go-mod-viewer.appspot.com/github.com/kubewharf/katalyst-core@v0.5.3/pkg/metaserver/agent/pod/pod.go#L249: call to general.UpdateHealthzStateByError discards error https://go-mod-viewer.appspot.com/github.com/lbryio/lbcd@v0.22.119/txscript/standard_test.go#L609: call to btcutil.NewAddressScriptHashFromHash discards error https://go-mod-viewer.appspot.com/github.com/mailgun/mailgun-go/v3@v3.6.4/tags.go#L172: call to url.ParseQuery discards error https://go-mod-viewer.appspot.com/github.com/minio/console@v1.4.1/replication/admin_api_int_replication_test.go#L110: call to json.NewDecoder(response.Body).Decode discards error https://go-mod-viewer.appspot.com/github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/recovery/recovery.go#L204: call to msg.Annotate discards error https://go-mod-viewer.appspot.com/github.com/moov-io/imagecashletter@v0.10.1/cmd/readImageCashLetter/main.go#L55: call to ICLFile.Create discards error https://go-mod-viewer.appspot.com/github.com/nakagami/firebirdsql@v0.9.10/driver_test.go#L387: call to conn1.Exec discards error https://go-mod-viewer.appspot.com/github.com/nakagami/firebirdsql@v0.9.10/transaction_test.go#L211: call to conn.Exec discards error https://go-mod-viewer.appspot.com/github.com/nutsdb/nutsdb@v1.0.4/examples/k-v/increments/main.go#L29: call to nutsdb.Open discards error https://go-mod-viewer.appspot.com/github.com/opencontainers/runtime-tools@v0.9.0/validation/kill/kill.go#L72: call to util.WaitingForStatus discards error https://go-mod-viewer.appspot.com/github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchtransport/logger.go#L397: call to b.WriteRune discards error https://go-mod-viewer.appspot.com/github.com/philippseith/signalr@v0.6.3/jsonhubprotocol.go#L76: call to j.dbg.Log discards error https://go-mod-viewer.appspot.com/github.com/pusher/oauth2_proxy@v3.2.0+incompatible/oauthproxy_test.go#L90: call to websocket.Message.Receive discards error https://go-mod-viewer.appspot.com/github.com/rcrowley/go-metrics@v0.0.0-20201227073835-cf1acfcdf475/registry_test.go#L276: call to Register discards error https://go-mod-viewer.appspot.com/github.com/readium/readium-lcp-server@v0.0.0-20240509124024-799e77a0bbd6/storage/fs.go#L64: call to io.Copy discards error https://go-mod-viewer.appspot.com/github.com/s7techlab/cckit@v0.10.5/examples/insurance/app/invoke_insurance.go#L346: call to stub.PutState discards error https://go-mod-viewer.appspot.com/github.com/sdboyer/gps@v0.16.3/pkgtree/pkgtree_test.go#L1368: call to os.Chmod discards error https://go-mod-viewer.appspot.com/github.com/signintech/pdft@v0.5.0/pdf_data.go#L343: call to p.getPageCrawl discards error https://go-mod-viewer.appspot.com/github.com/stakater/IngressMonitorController@v1.0.103/pkg/monitors/uptimerobot/uptime-status-page_test.go#L104: call to service.AddMonitorToStatusPage discards error https://go-mod-viewer.appspot.com/github.com/tendermint/tmlibs@v0.9.0/autofile/cmd/logjack.go#L62: call to group.Flush discards error https://go-mod-viewer.appspot.com/github.com/therealbill/libredis@v0.0.0-20161227004305-7d50abda5ccf/client/transactions_test.go#L67: call to transaction.Discard discards error https://go-mod-viewer.appspot.com/github.com/vmware/govmomi@v0.37.2/vsan/client_test.go#L84: call to finder.HostSystemList discards error https://go-mod-viewer.appspot.com/github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/webapp/dynamic_components_handler.go#L44: call to componentTemplates.ExecuteTemplate discards error https://go-mod-viewer.appspot.com/github.com/wormhole-foundation/wormhole-explorer/common@v0.0.0-20240604151348-09585b5b97c5/client/cache/notional/cache.go#L108: call to json.Unmarshal discards error https://go-mod-viewer.appspot.com/github.com/yaricom/goNEAT@v0.0.0-20210507221059-e2110b885482/neat/genetics/organism.go#L107: call to o.Genotype.Write discards error https://go-mod-viewer.appspot.com/github.com/yggdrasil-network/yggdrasil-go@v0.5.6/src/core/link_tcp_linux.go#L24: call to c.Control discards error https://go-mod-viewer.appspot.com/github.com/zaquestion/lab@v0.25.1/cmd/mr_show.go#L50: call to cmd.Flags().GetBool discards error https://go-mod-viewer.appspot.com/gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/renter/repair_test.go#L98: call to build.Retry discards error

yawaramin commented 5 months ago

Are these necessarily false positives?

f.Close()

Could we not explicitly assign and ignore the result?

_ := f.Close()

Or

Ignore(f.Close()) // or: ignore f.Close()
ianlancetaylor commented 5 months ago

@yawaramin It's often fine to call the Close method of a file opened for reading. We don't want people to have to write unnecessary syntax merely to silence a program analyzer.