Skip to content

src/encoding/csv/writer.go: Triplicated quoting when writing a quoted string #73034

@oGabrielArruda

Description

@oGabrielArruda

Go version

go version go1.23.3 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/gabriel.alvesdearruda/Library/Caches/go-build'
GOENV='/Users/gabriel.alvesdearruda/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/gabriel.alvesdearruda/go/pkg/mod'
GONOPROXY=''
GONOSUMDB='gitlab.thunes.com/*,gitlab.thunes.com/*/*'
GOOS='darwin'
GOPATH='/Users/gabriel.alvesdearruda/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.23.3/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.23.3/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.3'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/gabriel.alvesdearruda/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/gabriel.alvesdearruda/thunes/bootstrap/go-sftp-transfer/go.mod'
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/pk/_2923cl114q1vn9h63xgr3gc0000gr/T/go-build3215592430=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

The problem

When writing to a CSV file, I want to wrap certain strings in quotes, especially when the text contains spaces. However, this appears to be impossible.

The issue occurs because when calling the csv.Write function with an array containing manually escaped quotes (e.g., fmt.Sprintf("\"example\"")), the CSV writer inserts quotes at three different points:

  1. When the condition !w.fieldNeedsQuotes(field) is met, the function immediately writes an opening quote (w.w.WriteByte('"');). This happens in encoding/csv/writer.go#L71.

  2. When encoding special characters, the function escapes existing quotes (""), which occurs in encoding/csv/writer.go#L92.

  3. Finally, the function writes a closing quote in encoding/csv/writer.go#L110.

As a result, the output in the CSV file ends up with triple quotes, like this:
"""example""", with three quotes.

Steps to reproduce

To reproduce the problem, I wrote this code:

package main

import (
	"encoding/csv"
	"fmt"
	"os"
	"strings"
)

func main() {
	records := []string{"myfield1", "my nice field", "myfield3"}
	quoted := quotedFields(records)

	file, err := os.Create("./output.csv")
	if err != nil {
		panic(err)
	}

	writer := csv.NewWriter(file)
	writer.Write(quoted)
	writer.Flush()
}

func quotedFields(fields []string) []string {
	result := make([]string, len(fields))

	for i, v := range fields {
		if strings.Contains(v, " ") {
			result[i] = fmt.Sprintf("\"%s\"", v)
			continue
		}

		result[i] = v
	}
	return result
}

Output file:

myfield1,"""my nice field""",myfield3

Expected Output:

myfield1,"my nice field",myfield3

What did you see happen?

Output file:

myfield1,"""my nice field""",myfield3

What did you expect to see?

Expected Output:

myfield1,"my nice field",myfield3

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.FrozenDueToAge

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions