Obtener el directorio de inicio del usuario


94

¿Es la siguiente la mejor manera de obtener el directorio de inicio del usuario en ejecución? ¿O hay una función específica que he desarrollado?

os.Getenv("HOME")

Si lo anterior es correcto, ¿alguien sabe si se garantiza que este enfoque funcione en plataformas que no sean Linux, por ejemplo, Windows?


2
$HOMEno es necesariamente el directorio de inicio del usuario. Por ejemplo, puedo escribir export HOME=/something/elseantes de lanzar su programa. Por lo general, eso significa que quiero que el programa lo trate /something/elsecomo mi directorio de inicio por alguna razón, y generalmente el programa debería aceptarlo. Pero si realmente necesita el directorio de inicio real del usuario , una variable de entorno no necesariamente se lo proporcionará.
Keith Thompson

1
@KeithThompson Gracias, pero para mis propósitos es lo suficientemente bueno.
Paul Ruane

Respuestas:


175

En go 1.0.3 (probablemente antes también) funciona lo siguiente:

package main
import (
    "os/user"
    "fmt"
    "log"
)
func main() {
    usr, err := user.Current()
    if err != nil {
        log.Fatal( err )
    }
    fmt.Println( usr.HomeDir )
}

Si es importante realizar una compilación cruzada, considere la homedirbiblioteca


1
Impresionante, muchas gracias. No estaba al tanto de este cambio. Esto es exactamente lo que estaba buscando.
Paul Ruane

¿Soy solo yo o soy el único en el que hacer esto en Windows lleva varios segundos?
Htbaa

Definitivamente parece instantáneo en mi máquina virtual con Windows 7 de 64 bits.
Vlad Didenko

4
Tenga en cuenta que a partir de la versión 1.1, "usr, err: = user.Current ()" arrojará un error "user: Current no implementado en darwin / amd64" en osx.
Oleiade

11
no funciona cuando se compila en forma cruzada code.google.com/p/go/issues/detail?id=6376
Vishnu

61

os.UserHomeDir ()

En go1.12 + puede usar os.UserHomeDir ()

home, err := os.UserHomeDir()

Ver https://golang.org/pkg/os/#UserHomeDir

Eso debería funcionar incluso sin CGO habilitado (es decir FROM scratch) y sin tener que analizar /etc/passwdu otras tonterías similares.


23

Por ejemplo,

package main

import (
    "fmt"
    "os"
    "runtime"
)

func UserHomeDir() string {
    if runtime.GOOS == "windows" {
        home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
        if home == "" {
            home = os.Getenv("USERPROFILE")
        }
        return home
    }
    return os.Getenv("HOME")
}

func main() {
    dir := UserHomeDir()
    fmt.Println(dir)
}

1
Este es el mismo enfoque que Jeremy W Sherman, que parece ser el único camino en la actualidad. Muchas gracias.
Paul Ruane

2
Este es el enfoque seguido en viper util.go userHomeDir ()
RubenLaguna

En casi todos los casos en los que veo que se usa, esto NO es lo correcto. USERPROFILEes la raíz del espacio de almacenamiento del usuario en el sistema, pero NO es el lugar donde las aplicaciones deben escribir fuera de un cuadro de diálogo para guardar. Si tiene una configuración de la aplicación, debe escribirse en ella APPDATAy si tiene un caché de la aplicación (o archivos grandes que no deben sincronizarse a través de una red) debe escribirse LOCALAPPDATAen Windows.
Micah Zoltu

4

Aquí hay una forma agradable y concisa de hacerlo (si solo está ejecutando en un sistema basado en UNIX):

import (
  "os"
)

var home string = os.Getenv("HOME")

Eso solo consulta la variable de entorno $ HOME.

--- Editar ---

Ahora veo que este mismo método se sugirió anteriormente. Dejaré este ejemplo aquí como una solución destilada.


2
1. se ha sugerido antes, 2. no es multiplataforma, 3. la respuesta aceptada ya resuelve este problema de una mejor manera.
Paul Ruane

3

Respuesta similar a @peterSO pero respeta la XDG_CONFIG_HOMEruta para linux.

package main

import (
    "fmt"
    "os"
    "runtime"
)

func userHomeDir() string {
    if runtime.GOOS == "windows" {
        home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
        if home == "" {
            home = os.Getenv("USERPROFILE")
        }
        return home
    } else if runtime.GOOS == "linux" {
        home := os.Getenv("XDG_CONFIG_HOME")
        if home != "" {
            return home
        }
    }
    return os.Getenv("HOME")
}

func main() {
    fmt.Println(userHomeDir())
}

¡Me encantaría ver esta respuesta actualizada para respetar Windows también! APPDATApara configuración y LOCALAPPDATApara archivos grandes. Para un "hogar" de propósito general, recomiendo LOCALAPPDATAque, por defecto, los desarrolladores de aplicaciones no destruyan las redes corporativas. 😊
Micah Zoltu

2

Debe utilizar la variable de entorno USERPROFILEo HOMEPATHen Windows. Consulte Variables de entorno reconocidas (se agradecería un enlace de documentación más apropiado).


Gracias. ¿Está diciendo, entonces, que HOME no está poblado por Go para cada plataforma (que delega directamente en las vars env O / S) y que debo verificar la variable respectiva de cada plataforma para identificar el directorio de inicio?
Paul Ruane

He echado un vistazo a la fuente y parece que HOME no se completa automáticamente. Parece que (actualmente) no existe una función independiente de la plataforma para obtener el directorio de inicio.
Paul Ruane

@PaulRuane Dado que las plataformas usan diferentes variables, simplemente ignore el sistema operativo, verifique ambas variables y elija la que esté poblada. Si ambos están definidos, lo usaría HOME, ya que eso probablemente significa que está ejecutando cygwin.
Jeremy W. Sherman

NO debe usar USERPROFILEo HOMEPATHen Windows en la gran mayoría de los casos. En casi todos los casos en los que los desarrolladores los usan, lo que deberían usar es APPDATAo LOCALAPPDATA(dependiendo de si es razonable que el contenido se sincronice a través de la red al iniciar / cerrar sesión).
Micah Zoltu

2

go1.8rc2 tiene la función go / build / defaultGOPATH que obtiene el directorio de inicio. https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

El siguiente código se extrae de la función defaultGOPATH.

package main

import (
    "fmt"
    "os"
    "runtime"
)

func UserHomeDir() string {
    env := "HOME"
    if runtime.GOOS == "windows" {
        env = "USERPROFILE"
    } else if runtime.GOOS == "plan9" {
        env = "home"
    }
    return os.Getenv(env)
}

func main() {
    dir := UserHomeDir()
    fmt.Println(dir)
}

Si bien la implementación de esta función Go es interesante, esta es una solución peor que usar la función de biblioteca estándar descrita en la respuesta aceptada. (Y es el mismo enfoque que la respuesta de peterSO de hace seis años.)
Paul Ruane

Esta no es la solución adecuada en la mayoría de los casos . Vea los comentarios sobre otras respuestas, pero el TL; DR es eso APPDATAo LOCALAPPDATAcasi siempre es la opción correcta, no USERPROFILE, en Windows.
Micah Zoltu
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.