Skip to content

slices: Clone keeps source array alive when source slice is zero length #68488

Closed
@diegommm

Description

@diegommm

Go version

go version go1.22.5 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/gopher/.cache/go-build'
GOENV='/home/gopher/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/gopher/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/gopher/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/snap/go/10660'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/snap/go/10660/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.5'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
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 -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3287061668=/tmp/go-build -gno-record-gcc-switches'

What did you do?

See this playground.

package main

import (
	"fmt"
	"runtime"
	"slices"
)

func main() {
	fmt.Println("running for standard library")
	cloneWithFunc(slices.Clone[[]*int, *int])
	fmt.Println()
	fmt.Println("running for local func")
	cloneWithFunc(clone[[]*int, *int])
}

func cloneWithFunc(f func([]*int) []*int) {
	x := []*int{newInt(), newInt(), newInt()}
	x = f(x[:0])
	forceGC()
	fmt.Println("did the finalizer for this slice items run before this printed line?", x)
	forceGC()
}

func clone[S ~[]E, E any](s S) S {
	return append(S(nil), s...)
}

func forceGC() {
	runtime.GC()
	runtime.GC()
}

var count int

func newInt() *int {
	count++
	id := count
	x := new(int)
	runtime.SetFinalizer(x, func(*int) {
		fmt.Println("finalizer run for item:", id)
	})
	return x
}

What did you see happen?

running for standard library
did the finalizer for this slice items run before this printed line? []
finalizer run for item: 3
finalizer run for item: 2
finalizer run for item: 1

running for local func
finalizer run for item: 5
finalizer run for item: 4
finalizer run for item: 6
did the finalizer for this slice items run before this printed line? []

What did you expect to see?

running for standard library
finalizer run for item: 3
finalizer run for item: 2
finalizer run for item: 1
did the finalizer for this slice items run before this printed line? []

running for local func
finalizer run for item: 5
finalizer run for item: 4
finalizer run for item: 6
did the finalizer for this slice items run before this printed line? []

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixPendingIssues that have a fix which has not yet been reviewed or submitted.NeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions