Skip to content
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

Interleaved append() calls when defining a struct value #69849

Closed
nicula-stripe opened this issue Oct 11, 2024 · 2 comments
Closed

Interleaved append() calls when defining a struct value #69849

nicula-stripe opened this issue Oct 11, 2024 · 2 comments

Comments

@nicula-stripe
Copy link

nicula-stripe commented Oct 11, 2024

Go version

go version go1.23.2 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/nicula/Library/Caches/go-build'
GOENV='/Users/nicula/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/nicula/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/nicula/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.23.2/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.23.2/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.2'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/nicula/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/_6/fr_zgkg90fn_963wxpdlx34r0000gn/T/go-build4004302717=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

I ran https://go.dev/play/p/oj2ayYHklaY.

What did you see happen?

The two append() calls inside with_struct() happen before the first call to string(), but only if string() is used directly, not with a wrapper.

What did you expect to see?

In with_struct(), I expected string(append(arr1, 'c')) and string(append(arr2, 'd')) to be executed separately, not be interleaved.

It's also weird how adding a wrapper around string() makes the append() calls not interleaved. Is this actually due to intentional, undefined behavior? (due to go's relaxed order of evaluation rules)

Thanks @adesjardins-stripe, who originally brought this up in a Slack channel.

@randall77
Copy link
Contributor

randall77 commented Oct 11, 2024

This is a consequence of Go's somewhat lax rules about order of evaluation.

In particular, the only two function calls in your struct literal expression are the two append calls. Those must appear to be evaluated in text order (first the 'c' append, then the d append). But []byte->string conversions are not one of the expression types that must be ordered. Both string conversions can happen after both appends.

So this isn't a bug. If you need to enforce ordering like this, you can use statement boundaries to do that (like your other examples).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants