io.WriteString to a file panics

218 views
Skip to first unread message

Rory Campbell-Lange

unread,
Apr 12, 2022, 3:54:05 AM4/12/22
to golang-nuts
I have a command line programme that can output to either stdout or a named file. Output to stdout, as commented out in the small example below, works fine, but not to a named file.

Attempting to write to a named file panics on go 1.17 on Linux with:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x46123d]

I'm confused since both os.Stdout and os.Create are *os.File types, which implement the Write(b []byte) (n int, err error) method which fulfils the io.Writer interface. I pass around io.Writer types in my programme to facilitate testing.

I've chosen io.WriteString because it will use StringWriter on the writer if the writer supports this method, which may perform better than a simple Write.

Clearly I am missing something fundamental, or I have a stupid error in my programme. Help very much appreciated.

Thanks
Rory

package main

import (
"io"
"log"
"os"
)

func main() {

// o := "-" // use stdin
o := "/tmp/output.txt" // or a file

var output io.Writer
if o == "-" {
output = os.Stdout
} else {
output, err := os.Create(o)
if err != nil {
log.Fatalf("Could not create file %s, %s", output, err)
}
defer output.Close()
}

_, err := io.WriteString(output, "hello")
if err != nil {
log.Fatal(err)
}
}

Sean Liao

unread,
Apr 12, 2022, 4:04:04 AM4/12/22
to golang-nuts
> output, err := os.Create(o)
The short variable declaration you used to create `err` also shadows `output`.

var err error
output, err = os.Create(o)


--
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/YlUv/%2BH%2BHYguq4Nn%40campbell-lange.net.

Jan Mercl

unread,
Apr 12, 2022, 4:05:14 AM4/12/22
to Rory Campbell-Lange, golang-nuts
On Tue, Apr 12, 2022 at 9:53 AM Rory Campbell-Lange
<ro...@campbell-lange.net> wrote:

> Attempting to write to a named file panics on go 1.17 on Linux with:
>
> panic: runtime error: invalid memory address or nil pointer dereference
> [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x46123d]

Not providing the backtrace means other have to guess where the
program actually failed.

The 'output` variable is nil in the 'io.WriteString' statement, the
panic is legitimate. The variable 'output', declared within the block
after 'else' is a different variable because it is not assigned, using
'=', but declared, using ':='. Go has blocks scope very much like C
and most other languages.

-j

Rory Campbell-Lange

unread,
Apr 12, 2022, 4:44:15 AM4/12/22
to Sean Liao, golang-nuts
On 12/04/22, 'Sean Liao' via golang-nuts (golan...@googlegroups.com) wrote:
> > output, err := os.Create(o)
> The short variable declaration you used to create `err` also shadows
> `output`.

Thanks very much for pointing out this shadowing problem.

>
> var err error
> output, err = os.Create(o)
>
> > func main() {
> >
> > // o := "-" // use stdin
> > o := "/tmp/output.txt" // or a file
> >
> > var output io.Writer
> > if o == "-" {
> > output = os.Stdout
> > } else {
> > output, err := os.Create(o)
...
Reply all
Reply to author
Forward
0 new messages