รับโฮมไดเร็กทอรีของผู้ใช้


94

วิธีต่อไปนี้เป็นวิธีที่ดีที่สุดในการรับโฮมไดเร็กทอรีของผู้ใช้ที่รันอยู่หรือไม่ หรือมีฟังก์ชันเฉพาะที่ฉันมองข้ามไปหรือไม่?

os.Getenv("HOME")

หากข้างต้นถูกต้องจะมีใครรู้บ้างหรือไม่ว่าแนวทางนี้รับประกันว่าจะทำงานบนแพลตฟอร์มที่ไม่ใช่ Linux เช่น Windows ได้หรือไม่?


2
$HOMEไม่จำเป็นต้องเป็นโฮมไดเร็กทอรีของผู้ใช้ ตัวอย่างเช่นฉันสามารถเขียนexport HOME=/something/elseก่อนเปิดโปรแกรมของคุณ โดยปกตินั่นหมายความว่าฉันต้องการให้โปรแกรมถือว่า/something/elseเป็นโฮมไดเร็กทอรีของฉันด้วยเหตุผลบางประการและโดยปกติโปรแกรมควรยอมรับสิ่งนั้น แต่ถ้าคุณต้องการโฮมไดเร็กทอรีจริงของผู้ใช้ตัวแปรสภาพแวดล้อมก็ไม่จำเป็นต้องมอบให้คุณ
Keith Thompson

1
@KeithThompson ขอบคุณ แต่สำหรับจุดประสงค์ของฉันมันดีพอแล้ว
Paul Ruane

คำตอบ:


176

ในการไป 1.0.3 (อาจก่อนหน้านี้ด้วย) การทำงานต่อไปนี้:

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

ถ้ามันเป็นสิ่งสำคัญที่จะข้ามรวบรวมพิจารณาห้องสมุดhomedir


1
ยอดเยี่ยมขอบคุณมาก ไม่ทราบถึงการเปลี่ยนแปลงนี้ นี่คือสิ่งที่ฉันกำลังมองหา
Paul Ruane

เป็นเพียงฉันหรือฉันคนเดียวที่ทำสิ่งนี้บน Windows ใช้เวลาหลายวินาที?
Htbaa

ดูเหมือนว่าทันทีบน Windows 7 64 บิต VM ของฉัน
Vlad Didenko

4
โปรดทราบว่าในขณะที่ 1.1 "usr, err: = user.Current ()" จะทำให้เกิดข้อผิดพลาด "ผู้ใช้: ปัจจุบันไม่ได้ใช้กับ darwin / amd64" บน osx
Oleiade

11
ใช้งานไม่ได้เมื่อคอมไพล์code.google.com/p/go/issues/detail?id=6376
วิษณุ

61

os.UserHomeDir ()

ใน go1.12 + คุณสามารถใช้ os.UserHomeDir ()

home, err := os.UserHomeDir()

ดูhttps://golang.org/pkg/os/#UserHomeDir

สิ่งนี้ควรใช้งานได้แม้ไม่ได้เปิดใช้ CGO (เช่นFROM scratch) และไม่ต้องแยกวิเคราะห์/etc/passwdหรือเรื่องไร้สาระอื่น ๆ


23

ตัวอย่างเช่น,

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
นี่เป็นแนวทางเดียวกับ Jeremy W Sherman ซึ่งดูเหมือนจะเป็นวิธีเดียวในปัจจุบัน ขอบคุณมาก.
Paul Ruane

2
นี่คือแนวทางตามใน viper util.go userHomeDir ()
RubenLaguna

ในเกือบทุกกรณีที่ฉันเห็นสิ่งนี้ใช้นี่ไม่ใช่สิ่งที่ถูกต้อง USERPROFILEเป็นรูทของพื้นที่เก็บข้อมูลของผู้ใช้ในระบบ แต่ไม่ใช่ที่ที่ควรเขียนแอปพลิเคชันไปที่นอกหน้าต่างโต้ตอบบันทึก หากคุณมีการกำหนดค่าแอปพลิเคชันควรเขียนAPPDATAและหากคุณมีแคชของแอปพลิเคชัน (หรือไฟล์ขนาดใหญ่ที่ไม่ควรซิงค์ผ่านเครือข่าย) ควรเขียนลงLOCALAPPDATAใน Windows
Micah Zoltu

4

นี่เป็นวิธีที่ดีและรัดกุมในการดำเนินการ (หากคุณใช้เฉพาะระบบที่ใช้ UNIX):

import (
  "os"
)

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

นั่นเป็นเพียงแค่ค้นหาตัวแปรสภาพแวดล้อม $ HOME

--- แก้ไข ---

ตอนนี้ฉันเห็นว่าวิธีการเดียวกันนี้ได้รับการแนะนำข้างต้น ผมจะปล่อยตัวอย่างนี้ไว้ที่นี่เป็นวิธีการกลั่น


2
1. ได้รับการแนะนำมาก่อน, 2. ไม่ใช่ข้ามแพลตฟอร์ม, 3. คำตอบที่ยอมรับได้ช่วยแก้ปัญหานี้ในทางที่ดีขึ้นแล้ว
Paul Ruane

3

คำตอบที่คล้ายกันกับ @peterSO แต่เคารพXDG_CONFIG_HOMEเส้นทางสำหรับ 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())
}

ชอบที่จะเห็นคำตอบนี้อัปเดตเพื่อเคารพ Windows ด้วย! APPDATAสำหรับการกำหนดค่าและLOCALAPPDATAสำหรับไฟล์ขนาดใหญ่ สำหรับวัตถุประสงค์ทั่วไป "บ้าน" ฉันขอแนะนำLOCALAPPDATAโดยค่าเริ่มต้นนักพัฒนาแอปพลิเคชันจะไม่ทำลายเครือข่ายขององค์กร 😊
Micah Zoltu

2

คุณควรใช้ตัวแปรสภาพแวดล้อมUSERPROFILEหรือHOMEPATHภายใต้ Windows ดูตัวแปรสภาพแวดล้อมที่รับรู้ (ยินดีต้อนรับลิงก์เอกสาร apropos เพิ่มเติม)


ขอบคุณ. คุณกำลังบอกว่า HOME ไม่ได้รับการเติมข้อมูลโดย Go สำหรับแต่ละแพลตฟอร์ม (ซึ่งมอบหมายโดยตรงใน O / S env vars) และฉันต้องตรวจสอบตัวแปรตามลำดับของแต่ละแพลตฟอร์มเพื่อระบุโฮมไดเร็กทอรี
Paul Ruane

ฉันได้ดูแหล่งที่มาและดูเหมือนว่า HOME จะไม่ได้รับการเติมโดยอัตโนมัติ ดูเหมือนว่า (ปัจจุบัน) ไม่มีสิ่งอำนวยความสะดวกที่ไม่เชื่อเรื่องพระเจ้าของแพลตฟอร์มสำหรับการรับโฮมไดเร็กทอรี
Paul Ruane

@PaulRuane เนื่องจากแพลตฟอร์มใช้ตัวแปรที่แตกต่างกันเพียงแค่เพิกเฉยต่อระบบปฏิบัติการตรวจสอบตัวแปรทั้งสองและเลือกตามที่ระบุไว้ หากมีการกำหนดทั้งสองอย่างฉันจะใช้HOMEเนื่องจากนั่นอาจหมายความว่าคุณกำลังทำงานภายใต้ cygwin
Jeremy W. Sherman

คุณไม่ควรใช้USERPROFILEหรือHOMEPATHบน Windows ในกรณีส่วนใหญ่ ในเกือบทุกกรณีที่ devs ใช้สิ่งเหล่านี้สิ่งที่ควรใช้คือAPPDATAหรือLOCALAPPDATA(ขึ้นอยู่กับว่าเหมาะสมหรือไม่ที่เนื้อหาจะซิงค์ผ่านเครือข่ายเมื่อเข้าสู่ระบบ / ออกจากระบบ)
Micah Zoltu

2

go1.8rc2 มีฟังก์ชัน go / build / defaultGOPATH ซึ่งรับโฮมไดเร็กทอรี https://github.com/golang/go/blob/go1.8rc2/src/go/build/build.go#L260-L277

รหัสต่อไปนี้ถูกดึงมาจากฟังก์ชัน 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)
}

ในขณะที่การใช้ฟังก์ชัน Go นี้น่าสนใจ แต่นี่เป็นวิธีแก้ปัญหาที่แย่กว่าการใช้ฟังก์ชันไลบรารีมาตรฐานที่อธิบายไว้ในคำตอบที่ยอมรับ (และเป็นแนวทางเดียวกับคำตอบของ peterSO เมื่อหกปีก่อน)
Paul Ruane

นี้ไม่ได้เป็นวิธีการแก้ปัญหาที่ถูกต้องในกรณีส่วนใหญ่ ดูความคิดเห็นเกี่ยวกับคำตอบอื่น ๆ แต่ TL; DR เป็นตัวเลือกที่ถูกต้องAPPDATAหรือLOCALAPPDATAเกือบตลอดเวลาไม่ใช่USERPROFILEบน Windows
Micah Zoltu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.