golang / go

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

cmd/gofmt: gofmt breaks examples with multline comments as output #43548

Open acanalis opened 3 years ago

acanalis commented 3 years ago

What version of Go are you using (go version)?

$ go version
go1.15.6 linux/amd64

Does this issue reproduce with the latest release?

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/agus/.cache/go-build"
GOENV="/home/agus/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/agus/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/agus/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build854558968=/tmp/go-build -gno-record-gcc-switches"

What did you do?

As per the guide "Testable examples in Go", I wrote a test file example_test.go inside an empty directory as the following:

package test1_test

import "fmt"

func Example() {
    fmt.Println(1)
    fmt.Println("\t\tA")

    // Output:
/*1
        A*/
}

Run go fmt and then go test:

What did you expect to see?

$ go test
PASS
ok      _/home/agus/code/bugreproduce/gorunnableexample 0.002s

What did you see instead?

After running go fmt (see on playground) , the program becomes:

package test1_test

import "fmt"

func Example() {
    fmt.Println(1)
    fmt.Println("\t\tA")

    // Output:
    /* 1
    A*/
}

The change of indentation of the line A* seems to make the test fail:

$ go test
--- FAIL: Example (0.00s)
got:
1
                A
want:
1
        A
FAIL
exit status 1
FAIL    _/home/agus/code/bugreproduce/gorunnableexample 0.002s

Relevant issues & workarounds:

https://github.com/golang/go/issues/41980 https://github.com/golang/go/issues/5128#issuecomment-708940093 https://github.com/golang/go/issues/6416

The problem can be worked around by using inline comments (//), which don't depend on formatting. This runs ok before and after gofmt:

package test1_test

import "fmt"

func Example() {
    fmt.Println(1)
    fmt.Println("\t\tA")

    // Output:
    // 1
//      A
}

However, this isn't satisfactory because it would make very difficult to check output longer that a couple of lines.

agnivade commented 3 years ago

As you have correctly pointed out, https://github.com/golang/go/issues/5128 is the overall issue that tracks this. It is a problem that we've had for quite a while, and unfortunately, using inline comments are the only available workaround as of now.

acanalis commented 3 years ago

As you have correctly pointed out, #5128 is the overall issue that tracks this. It is a problem that we've had for quite a while, and unfortunately, using inline comments are the only available workaround as of now.

That issue is about whether or not block comments should be formatted. The topic shifted during the years and it's now 8 years old. Some code examples don't apply any more. In general I'm not against formatting block comments because the use is almost always within documentation headers.

This issue in turn is about allowing go fmt and go test to work together in a way that allows writing longer examples.

I'd rather keep them separate from each other, if possible.

agnivade commented 3 years ago

I'll defer to @griesemer on whether to track this separately or merge with the parent.

griesemer commented 3 years ago

Fine to leave as a separate issue. At some point (maybe when doing whatever is needed to fine-tune generics gofmt output) we need to look at all these gofmt issues.