Suppress GoFmt-generated error with/tools.go?

268 views
Skip to first unread message

Mike Schinkel

unread,
Aug 29, 2024, 9:54:43 PMAug 29
to GoLang Nuts Mailing List
Hi all,

I think I already know the answer, but hoping there is a way I am missing to get gofmt to stop generating the "import in a program, not an importable package" error when parsing a `tools.go` file with the `tools` build tag.

If you are not familiar, there is an approach several people have written about to store references to your project's required Go-based CLI tools in a `tools.go` file:

https://play-with-go.dev/tools-as-dependencies_go119_en/
https://www.jvt.me/posts/2022/06/15/go-tools-dependency-management/

I am using it because oapi-codegen recommends it for maintaining enabling others who may clone your repo to easily get the proper tools then need installed:

https://github.com/oapi-codegen/oapi-codegen/?tab=readme-ov-file#install

And grpc-gateway evidently recommends it too:

https://github.com/grpc-ecosystem/grpc-gateway#installation

When I run gofmt — which GoLand does prior to a commit — it generates that as an error. People have said just to ignore it:

https://github.com/grpc-ecosystem/grpc-gateway/issues/3515
https://stackoverflow.com/questions/77664121/import-is-a-program-not-an-importable-package

However — call me anal —I really want to ensure no errors are generated unless they are errors I really need to fix. Otherwise I will likely get complacent and accidentally commit a real error.

Is there any way to get gofmt to ignore code based on build tags, e.g. `tools` in this case?

-Mike

Axel Wagner

unread,
Aug 30, 2024, 2:44:03 AMAug 30
to Mike Schinkel, GoLang Nuts Mailing List
Hi,

I don't think that error message comes from gofmt. As far as I am aware, gofmt only parses source code, it does not even do type-checking.
That is intentional - in general, Go tools tend to avoid relying on stronger assumptions than they need. So I would assume that this error message is produced by the editor running `go build` or something similar, which does need to check imports for correctness. And because it requires that, it seems unlikely that the error would be able to go away. Of course, the editor could stop running that command in that context or suppress that error message itself.

FWIW you might be interested in https://github.com/golang/go/issues/48429, which gives a less hacky way to track tool dependencies and which (as far as I know) has been accepted and is being implemented, with some delays due to team changes. So, for the concrete issue, a solution is already being worked on.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/31160B8D-8DBC-43C7-8396-F74B2B8AFD92%40newclarity.net.

peterGo

unread,
Aug 30, 2024, 9:14:38 AMAug 30
to golang-nuts
Mike,

Let's use official Go sources.

go/src/cmd/tools/tools.go:

$ go version
go version devel go1.24-0f003f9d15 Thu Aug 29 09:15:06 2024 +0000 linux/amd64
$


$ cat tools.go
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build tools

package tools

// Arrange to vendor the bisect command for use
// by the internal/godebug package test.
import _ "golang.org/x/tools/cmd/bisect"
$


Indent the tools.go import statement by a tab to force a reformat.

$ go fmt
tools.go
$


Attempt to build package tools.

$ go build
package cmd/tools: build constraints exclude all Go files in /home/peter/go/src/cmd/tools
$ go build -tags=tools
tools.go:11:8: import "golang.org/x/tools/cmd/bisect" is a program, not an importable package
$


Looks like a go build generated error.

A related Go issue.

https://github.com/golang/go/issues/48429

peter

Mike Schinkel

unread,
Aug 31, 2024, 8:22:32 AMAug 31
to Axel Wagner, peterGo, GoLang Nuts Mailing List
Hi Alex & Peter,

Thank you both for your replies.

On Aug 30, 2024, at 2:43 AM, Axel Wagner <axel.wa...@googlemail.com> wrote:
I don't think that error message comes from gofmt. As far as I am aware, gofmt only parses source code, it does not even do type-checking.

As you sure about that?  Running this:

go fmt ./tools.go

Generates this error for me using go1.23.0 (vs. go1.22.x):

tools.go:9:2: import "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen" is a program, not an importable package

FWIW you might be interested in https://github.com/golang/go/issues/48429, which gives a less hacky way to track tool dependencies and which (as far as I know) has been accepted and is being implemented, with some delays due to team changes. So, for the concrete issue, a solution is already being worked on.

Thank you for that link. I will look into that for longer term.  

Shorter term, though it would be nice to find a way to resolve this.

On Aug 30, 2024, at 9:14 AM, peterGo <go.pe...@gmail.com> wrote:
Let's use official Go sources.

go/src/cmd/tools/tools.go:

Indent the tools.go import statement by a tab to force a reformat.

$ go fmt 
tools.go


Attempt to build package tools.

$ go build
package cmd/tools: build constraints exclude all Go files in /home/peter/go/src/cmd/tools
$ go build -tags=tools 
tools.go:11:8: import "golang.org/x/tools/cmd/bisect" is a program, not an importable package


Looks like a go build generated error.

Have you tried `go fmt` on `tools.go` with go1.23?  

I tried with go1.22.6 just now and it did not generate an error, but it does with go1.23.0.

-Mke

Jan Mercl

unread,
Aug 31, 2024, 8:30:40 AMAug 31
to Mike Schinkel, GoLang Nuts Mailing List
On Sat, Aug 31, 2024 at 2:22 PM Mike Schinkel <mi...@newclarity.net> wrote:

> go fmt ./tools.go

'go fmt' is not gofmt. The OP talks about gofmt. I haven't tried
anything but you may try if using gofmt instead of 'go fmt' makes a
difference.

Mike Schinkel

unread,
Aug 31, 2024, 9:02:26 AMAug 31
to Jan Mercl, GoLang Nuts Mailing List
> On Aug 31, 2024, at 8:29 AM, Jan Mercl <0xj...@gmail.com> wrote:
>
> On Sat, Aug 31, 2024 at 2:22 PM Mike Schinkel <mi...@newclarity.net> wrote:
>
>> go fmt ./tools.go
>
> 'go fmt' is not gofmt.

They are different? Well that is positively confusing.

Thank you for pointing that out, though.

> The OP talks about gofmt.

Well, as I am the OP and I meant to talk about `go fmt, not `gofmt` so I had an inadvertent typo in my post because I did not realize there was a difference.

So, can I start over by asking the same questions about `go fmt` instead of `gofmt?`

-Mike

Axel Wagner

unread,
Aug 31, 2024, 9:46:20 AMAug 31
to Mike Schinkel, peterGo, GoLang Nuts Mailing List
On Sat, 31 Aug 2024 at 14:22, Mike Schinkel <mi...@newclarity.net> wrote:
Hi Alex & Peter,

Thank you both for your replies.

On Aug 30, 2024, at 2:43 AM, Axel Wagner <axel.wa...@googlemail.com> wrote:
I don't think that error message comes from gofmt. As far as I am aware, gofmt only parses source code, it does not even do type-checking.

As you sure about that?  Running this:

go fmt ./tools.go

Generates this error for me using go1.23.0 (vs. go1.22.x):

tools.go:9:2: import "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen" is a program, not an importable package

You are right, I can reproduce that. As Jan, I was using `gofmt`, not `go fmt`. That's interesting.
It seems the main difference is that `go fmt` accepts packages (and so it actually does have to look at import paths to a degree at least) while `gofmt` accepts files.
Good to know. I think it probably shouldn't actually check the imports beyond finding the package you want to format. Perhaps that can be fixed.
 

FWIW you might be interested in https://github.com/golang/go/issues/48429, which gives a less hacky way to track tool dependencies and which (as far as I know) has been accepted and is being implemented, with some delays due to team changes. So, for the concrete issue, a solution is already being worked on.

Thank you for that link. I will look into that for longer term.  

Shorter term, though it would be nice to find a way to resolve this.

Perhaps you can get your editor to run `gofmt` instead of `go fmt`?

I'm sceptical that there will be a shorter-term way to change anything on the Go side - if this ends up being considered an issue to fix, it would only get fixed in Go 1.24 at the earliest. And I would kind of hope that, until then, #48429 is merged.

peterGo

unread,
Aug 31, 2024, 12:30:21 PMAug 31
to golang-nuts
Mike,

I get the same results for go1.22 and go1.23 as I got for go (devel go1.24).

I indented the src/cmd/tools/tools.go file import statement by a tab to force a reformat.

~/go1.22/src/cmd/tools$ go1.22 version
go version go1.22.6 linux/amd64

~/go1.22/src/cmd/tools$ go1.22 fmt
tools.go

~/go1.22/src/cmd/tools$ go1.22 build
package cmd/tools: build constraints exclude all Go files in /home/peter/go1.22/src/cmd/tools
~/go1.22/src/cmd/tools$ go1.22 build -tags=tools

tools.go:11:8: import "golang.org/x/tools/cmd/bisect" is a program, not an importable package
~/go1.22/src/cmd/tools$

and

~/go1.23/src/cmd/tools$ go1.23 version
go version go1.23.0 linux/amd64

~/go1.23/src/cmd/tools$ go1.23 fmt
tools.go

~/go1.23/src/cmd/tools$ go1.23 build
package cmd/tools: build constraints exclude all Go files in /home/peter/go1.23/src/cmd/tools
~/go1.23/src/cmd/tools$ go1.23 build -tags=tools

tools.go:11:8: import "golang.org/x/tools/cmd/bisect" is a program, not an importable package
~/go1.23/src/cmd/tools$

peter

Mike Schinkel

unread,
Sep 1, 2024, 4:08:44 AMSep 1
to Axel Wagner, peterGo, GoLang Nuts Mailing List
On Aug 31, 2024, at 9:45 AM, Axel Wagner <axel.wa...@googlemail.com> wrote:

On Sat, 31 Aug 2024 at 14:22, Mike Schinkel <mi...@newclarity.net> wrote:
Hi Alex & Peter,

Thank you both for your replies.

On Aug 30, 2024, at 2:43 AM, Axel Wagner <axel.wa...@googlemail.com> wrote:
I don't think that error message comes from gofmt. As far as I am aware, gofmt only parses source code, it does not even do type-checking.

As you sure about that?  Running this:

go fmt ./tools.go

Generates this error for me using go1.23.0 (vs. go1.22.x):

tools.go:9:2: import "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen" is a program, not an importable package

You are right, I can reproduce that. As Jan, I was using `gofmt`, not `go fmt`. That's interesting.
It seems the main difference is that `go fmt` accepts packages (and so it actually does have to look at import paths to a degree at least) while `gofmt` accepts files.
Good to know. I think it probably shouldn't actually check the imports beyond finding the package you want to format. Perhaps that can be fixed.

Thank you for checking it.  

Sometimes an error in understand can reveal undiscovered bugs. Happy accidents.

 Perhaps you can get your editor to run `gofmt` instead of `go fmt`?

Yeah, unfortunately GoLand does not have an option for that, AFAICT.  At least not in the "on commit" workflow.

This is the "on commit" settings dialog so you can see the options it offers: 


I can certainly reach out to JetBrains and submit a feature request for them to address this from their end — which I will do — but as you mention `go fmt` probably should not fail on this, so fixing from both ends would be ideal.

I'm sceptical that there will be a shorter-term way to change anything on the Go side - if this ends up being considered an issue to fix, it would only get fixed in Go 1.24 at the earliest. And I would kind of hope that, until then, #48429 is merged.

Yeah, you are probably correct on the timeframe.  Thank you for engaging on this.

On Aug 31, 2024, at 12:30 PM, peterGo <go.pe...@gmail.com> wrote:

Mike,

I get the same results for go1.22 and go1.23 as I got for go (devel go1.24).

I indented the src/cmd/tools/tools.go file import statement by a tab to force a reformat.

I probably did something wrong when testing with go1.22.6 then.

But either way, we confirmed that the problematic behavior does in-fact occur with `go fmt`.

Ian — if you are reading this — does this rise enough to the level of a bug — checking imports on a `go fmt` — that I should submit as an issue on GitHub?

-Mike

Ian Lance Taylor

unread,
Sep 2, 2024, 8:41:23 PMSep 2
to Mike Schinkel, Axel Wagner, peterGo, GoLang Nuts Mailing List
On Sun, Sep 1, 2024 at 1:08 AM Mike Schinkel <mi...@newclarity.net> wrote:
>
> Ian — if you are reading this — does this rise enough to the level of a bug — checking imports on a `go fmt` — that I should submit as an issue on GitHub?

This is, perhaps unfortunately, expected behavior.

The "go fmt" command is the "fmt" subcommand of the "go" command. It
takes a list of packages. If no package is listed, it applies to the
current directory. Because it is part of the "go" command, it looks
at imports, finds packages, and does other things that the "go"
command does. The docs are at
https://pkg.go.dev/cmd/go#hdr-Gofmt__reformat__package_sources.

The "gofmt" command is a simpler command that formats one or more
source files. If no source files are listed, it reads a Go file on
standard input and emits the formatted version on standard output.
The "gofmt" command is invoked by "go fmt". The "gofmt" command has
more options than the "go fmt" command, but on the other hand it won't
find packages for you. The docs are at https://pkg.go.dev/cmd/gofmt.

This has been discussed before, for example
https://groups.google.com/g/golang-nuts/c/t-tSHt8RG-4,
https://go.dev/issue/33263, https://go.dev/issue/35258.

Ian

Mike Schinkel

unread,
Sep 2, 2024, 8:56:00 PMSep 2
to Ian Lance Taylor, GoLang Nuts Mailing List
Thank you for providing all those details. Looks like it is what it is.

Looking forward to hopefully seeing this then: https://github.com/golang/go/issues/48429

-Mike
Reply all
Reply to author
Forward
0 new messages