Skip to content

proposal: os: add UserConfigDir #29960

Closed
Closed
@mvdan

Description

@mvdan

Go 1.11 added os.UserCacheDir in #22536, and 1.12 is adding os.UserHomeDir in #26463. This is great, and it covers plenty of common use cases.

UserCacheDir is particularly interesting, as its behavior changes greatly between platforms. For example, on Unix-y systems it tries $XDG_CACHE_HOME and falls back to $HOME/.cache, and on Windows it uses %LocalAppData%.

With those two functions, I believe there's only one piece missing; a configuration directory. Too many applications write "dot files" under the user's home directory, and that's bad practice. Some others hard-code $HOME/.config, which is only marginally better as it doesn't do the right thing on Windows/Mac.

Relying on XDG base directory vars like $XDG_CONFIG_HOME is no good either, as those don't exist on most systems.

We're only left with third-party libraries like https://github.com/shibukawa/configdir, which are moderately popular. In practice, popular software tends to write their own implementations. Below are some examples:

I propose adding func UserConfigDir() (string, error), which would return:

  • $XDG_CONFIG_HOME or $HOME/.config on Unix-y systems
  • %APPDATA% on Windows, which is described as "Contains the full path to the Application Data directory of the logged-in user" (unlike %LOCALAPPDATA%, it's not for temporary files)
  • $HOME/Library/Preferences on Mac

I don't know about plan9, but given that the cache dir is $home/lib/cache, perhaps $home/lib/config would work.

Please note that I'm not suggesting adding support for XDG base directories into the os package. Most notably, adding UserConfigDir might lead to some users requesting UserDataDir. However, I can think of multiple reasons why they're not equally important:

  • Mac and Windows don't obey XDG, so they only have one persistent per-user directory
  • Even on Linux, most apps store all their data in their config dir. For example: Chromium, Libreoffice, GIMP, and gcloud all seem to ignore XDG_DATA_HOME
  • Most programs only need one persistent per-user directory, and it's often for config files; see the links above for examples

The only disadvantage I see with adding this API is that one could say we'd be encouraging users to store data files into XDG_CONFIG_HOME instead of XDG_DATA_HOME on XDG systems. However, those few programs that wish to differentiate their data directory from their config directory could simply do:

func userDataDir() (string, error)
    if dir := os.Getenv("XDG_DATA_HOME"); dir != "" {
        return dir, nil
    }
    // fall back to something sane on all platforms
    return os.UserConfigDir()
}

/cc @kolyshkin @bradfitz @rsc @ianlancetaylor @stapelberg @robpike

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions