package main
import "os"
import "fmt"
func main() {
fmt.Println (len (os.Args[1:]), " Parameters...")
/*argsWithProg := os.Args*/
argsWithoutProg := os.Args[1:]
for i, arg := range argsWithoutProg {
fmt.Println ("Parameter ", i, ": ", arg)
}
if len(argsWithoutProg) != 1{
fmt.Println ("Just one Parameter Please")
os.Exit(-1)
}
fmt.Println ("Hello", argsWithoutProg[0])
}Go nos ofrece todos los parámetros en una matriz de la que podremos extraer fácilmente toda la información que necesitamos, como por ejemplo, el número de parámetros.
Go como otros lenguajes almacena en la primera entrada de la matriz
el nombre del programa que se ejecuta, sin embargo es muy sencillo
obtener una matriz solo con los parámetros utilizando un
slice del array.
Si bien, el valor de os.Args[0] contiene el nombre del
programa que se está ejecutando, no podemos modificar este valor
directamente para cambiar el nombre del proceso que aparece en
ps.
SOY NOVATO
Es posible modificar el valor de
os.Args[0]usando funciones no seguras del lenguaje, fundamentalmente obteniendo un puntero directamente al parámetro y modificándolo.. El siguiente código muestra un ejemplo de como hacerlo:var name String name = "Hello" a0str := (*reflect.StringHeader)(unsafe.Pointer(&os.Args[0])) argv0 := (*[1 << 30]byte)(unsafe.Pointer(a0str.Data))[:a0str.Len] n := copy(argv0, name) if n < len(argv0) { argv0[n] = 0 }En mi sistema he tenido que sustituir el último
ifpor un bucle que borra el resto de la cadena,for i:=n; i < argv0str.Len; i++ { argv0[i] =0 }De lo contrario, después de la cadena
Hellotodavía podemos ver los restos del nombre original (asumiendo que el nombre original era más largo queHello)En Go, las cadenas son inmutables, es decir, una vez creadas no se pueden modificar, por esa razón, cuando modificamos
os.Args[0], estamos asignando una nueva cadena a esa entrada del array, en lugar de sobreescribir elos.Args[0]original que contiene el nombre del programa conocido por el OS
Como sucede con la mayoría de los lenguajes más modernos, disponemos
de numerosos paquetes para poder hacer casi de todo. En el caso concreto
de procesar la línea de comandos, una de las opciones disponibles
replica el comportamiento de la librería getopt de GNU, y
es la opción recomendada cuando se quiera re-escribir alguna de las
utilidades GNU estándar en Go.
Veamos un ejemplo de como usarlo:
package main
import (
"os"
"fmt"
"github.com/pborman/getopt"
)
func main() {
opt1 := getopt.StringLong ("input", 'i', "input.txt", "Fichero Entrada")
opt2 := getopt.StringLong ("output", 'o', "output.txt", "Fichero Salida")
optAyuda := getopt.BoolLong("help", 0, "Help")
getopt.Parse()
if *optAyuda {
getopt.Usage()
os.Exit(0)
}
fmt.Println ("Op1 :" + *opt1 + " Op2: " + *opt2)
}El programa utiliza el módulo github.com/pborman/getopt.
Si, Go nos permite usar módulos directamente de github. Disponemos de
diferentes funciones para declarar distintos tipos de parámetros. En el
ejemplo estamos declarando dos cadenas de caracteres y un valor booleano
para el flag de ayuda. Las funciones de soporte nos permite indicar cual
será el flag largo (usando --) y el corto (con un único
-), además de un valor por defecto y lo que se mostrará al
ejecutar la función Usage.
SOY NOVATO
Para poder usar un módulo externo en go tenemos que crear un fichero `go.mod` en el que se almacena la lista de dependencias de nuestro programa, así como sus versiones. Para poder compilar el programa anterior, primero debemos crear un fichero `go.mod`, lo que podemos hacer de la siguiente forma:# go mod init solucionario/cmdline-getopt go: creating new go.mod: module solucionario/cmdline-getopt go: to add module requirements and sums: go mod tidy root@624154d820aa:/opt/code/cmdline# go mod tidyDonde le hemos dado el nombre `solucionario/cmdliune-getopt` a nuestro programa. Los comandos anteriores crearan un fichero `go.mod` como este:# cat go.mod module solucionario/cmdline-getopt go 1.19 require github.com/pborman/getopt v1.1.0
Existen otros paquetes con los que procesar la línea de comandos y os animamos a que exploréis las posibilidades.
Resumen
- Go recibe las opciones pasadas en la línea de comandos en la
variable
os.Args - La entrada 0 contiene el nombre del programa sin embargo, no puede ser modificada directamente
- El paquete
github.com/pborman/getoptofrece la misma funcionaldiad que la libreríagetopt.
■
