Correct on input but panic on output in golang

1.3k views Asked by At

Trying to write a bit of go, I would like to create a sort of cat function in Golang:

package main

import (
        "fmt"
        "os"
        "io/ioutil"
        "log"
)

func main() {
        // part to ask the question and get the input
        fmt.Print("Which file would you like to read?: ")
        var input string
        fmt.Scanln(&input)
        fmt.Print(input)

        // part to give the output
        f, err := os.Open(os.Args[1]) // Open the file                                       
        if err != nil {
                log.Fatalln("my program broken")
        }

        defer f.Close() // Always close things open                                          

        bs, err := ioutil.ReadAll(f)
        if err != nil {
                log.Fatalln("my program broken")
        }

        // part to print the output
        fmt.Printf("input", bs) // %s convert directly in string the result                  

}

But I get a go panic on execution and do not find more explicit information.

What I have done wrong?

How can I get more information about that error from the terminal?

$ go run gocat.go Which file would you like to read?: gocat.go gocat.gopanic: runtime error: index out of range

goroutine 1 [running]: panic(0x4b1840, 0xc42000a0e0) /usr/lib/go/src/runtime/panic.go:500 +0x1a1 main.main() /home/user/git/go-experimentations/gocat/gocat.go:23 +0x4ba exit status 2

3

There are 3 answers

0
Uncle Bob On BEST ANSWER

You use = rather than := So here is from where your error comes from.

8
jfly On

not os.Open(os.Args[1]), Args[1] is out of range. you should open the file you input like this:

f, err := os.Open(input)
5
jmaloney On

I imagine you found some examples online and don't quite understand what is going on.

From the os package's documentation.

Args hold the command-line arguments, starting with the program name.

Since you started your program without any arguments and os.Args is a slice, the program panics when you access out of the slice's bounds. (Like trying to access an element of any array that does not exist)

It looks like you are trying to prompt for the input here

var input string
fmt.Scanln(&input)
fmt.Print(input)

All you need to do is replace

f, err := os.Open(os.Args[1])

With:

f, err := os.Open(input)

Your last print statement is also incorrect.

It should be:

// part to print the output
fmt.Printf("input \n %s", string(bs))

You need to cast bs which is currently []byte to a string and you need to add %s to indicate to fmt.Printf where string(bs) should be placed in the format string