7

I am writing a CLI interface program in Go.my program requires a user to enter a filename as an argument . following is the code I wrote to handle the situations in which user doesn't enter any argument . but it panics and gives an error "index out of range".how do I handle this?

  package main

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

func main() {
    if len(os.Args) == 0 {
        fmt.Println("usage: gohex  <filename>")

        os.Exit(1)
    } else {
        filename := os.Args[1]

        data, err := ioutil.ReadFile(filename)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(hex.Dump(data))
    }

}
  • Please show us the complete code. The current snippet cannot panic. – Roland Illig May 12 '16 at 18:56
  • I can't reproduce this problem. Are you sure you get this error on exactly this code? – Rob Napier May 12 '16 at 18:56
  • 2
    In Go as in C, the executable path is passed as first parameter of the arguments list. So you have to check that len == 1 – Warrior May 12 '16 at 18:57
  • @Warrior can you elaborate please? – Prithviraj Sukale May 12 '16 at 19:04
  • When you run your program the minimum length of `os.Args` is 1 because by default the first position is occupied by the executable (your program) path. If the user inserts one or more parameters you have `len(os.Args)` > 1 so use that as condition to see if there are additional commandline arguments (or `len(os.Args) == 1` in your case). – Warrior May 12 '16 at 19:09
  • Args will always be at least 1 long, because Args[0] will be the executable's name. So your first if check for len == 0 is failing. – BlueSpaceCanary May 12 '16 at 19:09
  • oh ok .i got that .thank you @Warrior – Prithviraj Sukale May 12 '16 at 19:19

2 Answers2

12

Your problem relies in this line:

if len(os.Args) == 0

You are checking for the first argument which as you supposed should be the filename, but in fact is the go / executable filename. So if you wish to check if an argument has been provided you need to check that the argument length is greater than 1. Change the code to:

if len(os.Args) <= 1 {
    log.Fatal("usage: gohex  <filename>")
}
030
  • 10,842
  • 12
  • 78
  • 123
Endre Simo
  • 11,330
  • 2
  • 40
  • 49
2

The other answer has a couple of issues. It has this check:

len(os.Args) <= 1

but len(os.Args) must always be at least 1, so using <= is pointless. Further, in this specific case, len of anything other than 2 is invalid as well. So just check that:

package main
import "os"

func main() {
   if len(os.Args) != 2 {
      println("gohex <filename>")
      return
   }
   filename := os.Args[1]
   println(filename)
}

Side note, personally I also think using os.Exit(1) is invalid in this context as well. I think "printing the help text" is a valid use case, and not an error.

Zombo
  • 1
  • 62
  • 391
  • 407