{"id":34123875,"url":"https://github.com/struct0x/envconfig","last_synced_at":"2026-01-27T13:00:45.737Z","repository":{"id":314597576,"uuid":"1054987201","full_name":"struct0x/envconfig","owner":"struct0x","description":"A small, dependency-free Go library for loading configuration from environment variables directly into your structs.","archived":false,"fork":false,"pushed_at":"2026-01-26T21:06:47.000Z","size":54,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-27T07:46:41.119Z","etag":null,"topics":["envconfig","environment-variables","go","golang","structtags"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/struct0x.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-11T15:51:15.000Z","updated_at":"2026-01-26T20:59:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"7c5571cd-63ba-45e8-9a05-2e32f0386874","html_url":"https://github.com/struct0x/envconfig","commit_stats":null,"previous_names":["struct0x/envconfig"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/struct0x/envconfig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/struct0x%2Fenvconfig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/struct0x%2Fenvconfig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/struct0x%2Fenvconfig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/struct0x%2Fenvconfig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/struct0x","download_url":"https://codeload.github.com/struct0x/envconfig/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/struct0x%2Fenvconfig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28813223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T12:25:15.069Z","status":"ssl_error","status_checked_at":"2026-01-27T12:25:05.297Z","response_time":168,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["envconfig","environment-variables","go","golang","structtags"],"created_at":"2025-12-14T22:54:49.766Z","updated_at":"2026-01-27T13:00:45.730Z","avatar_url":"https://github.com/struct0x.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# envconfig\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/struct0x/envconfig.svg)](https://pkg.go.dev/github.com/struct0x/envconfig)\n[![Go Report Card](https://goreportcard.com/badge/github.com/struct0x/envconfig)](https://goreportcard.com/report/github.com/struct0x/envconfig)\n![Coverage](https://img.shields.io/badge/Coverage-92.7%25-brightgreen)\n\nA small,\ndependency-free Go library for loading configuration from environment variables directly into your structs.\n\nIt supports nested structs, prefixes, defaults, required fields,\nslices, maps, arrays, pointers, durations, and custom (un)marshalers.\nA helper is provided to read variables from a .env file.\n\n- Zero dependencies\n- Simple, tag-driven API\n- Works with standard os.LookupEnv or a custom lookups\n- Optional .env file loader (supports comments, export, quoting, inline comments)\n\n## Installation\n\n```bash \ngo get github.com/struct0x/envconfig\n```\n\n## Quick start\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/struct0x/envconfig\"\n)\n\ntype HTTPServer struct {\n\tEnv     string            `env:\"ENV\"`\n\tHost    string            `env:\"HOST\" envDefault:\"127.0.0.1\"`\n\tPort    int               `env:\"PORT\" envRequired:\"true\"`\n\tEnabled bool              `env:\"ENABLED\"`\n\tTags    []string          `env:\"TAGS\"`    // \"a,b,c\" -\u003e []string{\"a\",\"b\",\"c\"}\n\tHeaders map[string]string `env:\"HEADERS\"` // \"k1=v1,k2=v2\"\n}\n\nfunc main() {\n\tvar cfg HTTPServer\n\n\t// Use OS environment by default\n\tif err := envconfig.Read(\u0026cfg); err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", cfg)\n}\n\n```\n\nExample environment:\n\n```shell\nexport PORT=8080\nexport ENABLED=true\nexport TAGS=\"alpha,beta\"\nexport HEADERS=\"X-Req=abc,X-Trace=on\"\n```\n\n## Using a .env file\n\nUse EnvFileLookup to source values from a .env file. Lines use KEY=VALUE, support comments and export statements, and handle quoted values with inline comments.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/struct0x/envconfig\"\n)\n\ntype App struct {\n\tName string `env:\"NAME\" envDefault:\"demo\"`\n\tPort int    `env:\"PORT\" envRequired:\"true\"`\n}\n\nfunc main() {\n\tvar cfg App\n\n\tif err := envconfig.Read(\u0026cfg, envconfig.EnvFileLookup(\".env\")); err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Printf(\"%+v\\n\", cfg)\n}\n```\n\nNotes:\n\n- If both the .env file and the OS define a key, the OS environment value wins.\n- EnvFileLookup panics if the file cannot be read.\n\n## Tags\n\nAdd struct field tags to control how values are loaded:\n\n- `env`: the env variable name. Use `env:\"-\"` to skip a field.\n- `envDefault`: fallback value if the variable is not set.\n- `envRequired:\"true\"`: marks the field as required, returns error when not set, and no default provided.\n- `envPrefix`: for struct-typed fields; prepends a prefix (with underscore) for all nested fields under that struct.\n\nPrecedence per field:\n\n1. Value from lookupEnv(name)\n2. envDefault (if present)\n3. Error if `envRequired:\"true\"`\n\n\n## Dynamic Environment Variables\n\nFor environment variables that can't be expressed via struct tags, like numbered sequences (USER_1, PASS_1, USER_2, PASS_2) – implement the EnvCollector interface:\n\n```go\npackage main\n\nimport (\n\t\"github.com/struct0x/envconfig\"\n)\n\ntype Config struct {\n\tCredentials Credentials `envPrefix:\"CREDS\"`\n}\n\ntype Credentials []Credential\n\ntype Credential struct {\n\tUser string `env:\"USER\"`\n\tPass string `env:\"PASS\"`\n}\n\nfunc (c *Credentials) CollectEnv(prefix string, env envconfig.EnvGetter) error {\n\t// Read IDs from CREDS=0,1,2 \n\tvar ids []string\n\tif err := env.ReadValue(prefix, \u0026ids); err != nil {\n\t\treturn err\n\t}\n\n\tfor _, id := range ids {\n\t\tvar cred Credential\n\t\t// Reads CREDS_0_USER, CREDS_0_PASS, etc.                                                                                                                                                                                                                                                                                                                                                                              \n\t\tif err := env.Read(prefix+\"_\"+id, \u0026cred); err != nil {\n\t\t\treturn err\n\t\t}\n\t\t*c = append(*c, cred)\n\t}\n\treturn nil\n}\n\n```\n\nFields implementing EnvCollector must use envPrefix (not env). \nThe EnvGetter provides three methods: \n- Lookup for raw access, \n- ReadValue for parsing single values, and \n- Read for populating nested structs with full tag support.\n\n\n### Examples\n\nBasic tags:\n\n```go\npackage main\n\ntype DB struct {\n\tHost string `env:\"DB_HOST\" envDefault:\"localhost\"`\n\tPort int    `env:\"DB_PORT\" envRequired:\"true\"`\n}\n\n```\n\nNested with prefix:\n\n```go\npackage main\n\ntype SubConfig struct {\n\tEnabled bool   `env:\"ENABLED\"`\n\tMode    string `env:\"MODE\" envDefault:\"safe\"`\n}\n\ntype Root struct {\n\tName string     `env:\"NAME\"`\n\tSub  *SubConfig `envPrefix:\"SUB\"` // Reads SUB_ENABLED, SUB_MODE\n}\n```\n\nSkipping a field:\n\n```go\npackage main\n\ntype T struct {\n\tIgnored string `env:\"-\"`\n}\n```\n\n## Supported types\n\n- string, bool\n- Integers: int, int8, int16, int32, int64\n- Unsigned integers: uint, uint8, uint16, uint32, uint64\n- Floats: float32, float64\n- time.Duration via time.ParseDuration\n- Arrays and slices (comma-separated values): \"a,b,c\"\n- Maps (comma-separated key=value pairs): \"k1=v1,k2=v2\"\n- Pointers to supported types (allocated when needed)\n- Custom types implementing any of:\n    - encoding.TextUnmarshaler\n    - encoding.BinaryUnmarshaler\n    - json.Unmarshaler\n\nIf a value cannot be parsed into the target type, `Read` returns a descriptive error.\n\n## Custom lookup (For Secret Managers, Vaults, etc.)\n\nBy default, Read uses os.LookupEnv, for more advanced use cases like reading values from secret managers like AWS Secret Manager, HashiCorp Vault you can provide a custom lookup function:\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"os\"\n  \"log/slog\"\n\n  \"github.com/struct0x/envconfig\"\n)\n\ntype SecretResolver struct {\n  startingCtx context.Context\n  sm          SecretManager\n}\n\nfunc (s *SecretResolver) Lookup(key string) (string, bool) {\n  val, ok := os.LookupEnv(key)\n  if s.isSecret(val) {\n    val, err := s.sm.ResolveSecret(s.startingCtx, val)\n    if err != nil {\n      slog.Error(\"missing value\", \"err\", err)\n      return \"\", false\n    }\n    return val, true\n  }\n\n  // fallback to standard lookup\n  return val, ok\n}\n\ntype C struct {\n  N int `env:\"N\"`\n}\n\nfunc main() {\n  sm := \u0026SecretResolver{ /*...*/ }\n\t\n  var c C\n  _ = envconfig.Read(\u0026c, sm.Lookup)\n}\n\n```\n\nError handling is your responsibility, use `envRequired` to ensure values are present regardless of lookup failures.\n\n## Error handling\n\n`Read` returns an error when:\n\n- The holder is not a non-nil pointer to a struct\n- A required field is missing and no default is provided\n- A value cannot be parsed into the target type\n\nErrors include the env variable name and context to aid debugging.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstruct0x%2Fenvconfig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstruct0x%2Fenvconfig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstruct0x%2Fenvconfig/lists"}