{"id":16516185,"url":"https://github.com/aphistic/goblin","last_synced_at":"2026-05-15T07:05:56.986Z","repository":{"id":136842787,"uuid":"134922213","full_name":"aphistic/goblin","owner":"aphistic","description":"Goblin is a library and utility for working with filesystems in Go. It includes support for the proposed FS interfaces in the Go standard library.","archived":false,"fork":false,"pushed_at":"2023-08-30T14:01:28.000Z","size":52,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-13T04:23:10.203Z","etag":null,"topics":[],"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/aphistic.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}},"created_at":"2018-05-26T02:21:35.000Z","updated_at":"2020-09-06T19:36:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"ae65317c-997a-473b-ba9d-0a041d215211","html_url":"https://github.com/aphistic/goblin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aphistic%2Fgoblin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aphistic%2Fgoblin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aphistic%2Fgoblin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aphistic%2Fgoblin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aphistic","download_url":"https://codeload.github.com/aphistic/goblin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241541451,"owners_count":19979121,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-11T16:19:54.723Z","updated_at":"2026-05-15T07:05:56.900Z","avatar_url":"https://github.com/aphistic.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![GoDoc](https://godoc.org/github.com/aphistic/goblin?status.svg)](https://godoc.org/github.com/aphistic/goblin)\n[![Build Status](https://travis-ci.org/aphistic/gomol.svg?branch=master)](https://travis-ci.org/aphistic/gomol)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=aphistic_goblin\u0026metric=coverage)](https://sonarcloud.io/dashboard?id=aphistic_goblin)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=aphistic_goblin\u0026metric=sqale_rating)](https://sonarcloud.io/dashboard?id=aphistic_goblin)\n[![Go Report Card](https://goreportcard.com/badge/github.com/aphistic/goblin)](https://goreportcard.com/report/github.com/aphistic/goblin)\n\nGoblin\n======\n\nGoblin is a library and utility for interacting with filesystems in Go, including filesystems\nembedded in Go binaries. It's designed around the\n[proposed](https://go.googlesource.com/proposal/+/master/design/draft-iofs.md) `io/fs`\ninterfaces. At some point it will likely also support the\n[proposed](https://go.googlesource.com/proposal/+/master/design/draft-embed.md) embedded static\nassets support.\n\n**Warning:** Since the interfaces this library is based on are not stable, neither is this API!\nIt will evolve with the proposal and thus should be considered unstable. The goal is to avoid a\nlot of API churn but sometimes it's inevitable!\n\n## Installation\n\nIf you'd only like to use Goblin as a library you can install it with:\n\n```bash\n$ go get github.com/aphistic/goblin\n```\n\nIf you'd like to make use of Goblin's capability to embed files in a Go binary, you'll want to\ninstall the `goblin` utility to create those files.\n\n```bash\ngo get github.com/aphistic/goblin/cmd/goblin\n```\n\n## General Usage\n\nThe representation of a filesystem in Goblin is known as a vault (get it? goblins? vaults? 😁).\nThe `Vault` interface in Goblin implements at least a few of the `io/fs` interfaces and adds a\nfew additional utility methods (some hopefully having `io/fs` interfaces in the future).\n\n```go\n// Create a new memory vault\nmVault := goblin.NewMemoryVault()\n\n// Create a reader to write the file from with\n// some file contents.\nfileData := bytes.NewReader([]byte(\"I'm a file!\"))\n\n// Write the file contents to your/file/here.txt with\n// a file modified time of April 8, 2020 at Midnight UTC.\n_ = mVault.WriteFile(\n    \"your/file/here.txt\", fileData,\n    goblin.FileModTime(time.Date(2020, 4, 8, 0, 0, 0, 0, time.UTC)),\n)\n\n// Read all the files in the root of the memory vault. In\n// our case it's only the \"your\" directory.\ninfos, _ := mVault.ReadDir(\".\")\nfmt.Printf(\"Root Files:\\n\")\nfor _, info := range infos {\n    fmt.Printf(\"  - %s\\n\", info.Name())\n}\n\n// Read the contents of the file we previously wrote.\nreadData, _ := mVault.ReadFile(\"your/file/here.txt\")\nfmt.Printf(\"File Data: %s\\n\", readData)\n\n// Output:\n// Root Files:\n//   - your\n// File Data: I'm a file!\n```\n\n## Mixing Vaults at Runtime\n\nIt's sometimes desired to be able to choose between one or more vaults at runtime. Since this\nis a common pattern, Goblin provides a way to do it for you with a `VaultSelector`. The\n`VaultSelector` is a `Vault`, so it can be used anywhere a `Vault` would be, and provides a few\noptions for selecting a `Vault` by default but also supports creating custom selectors.\n\n```go\n// Use a FilesystemVault if a path is provided as an environment variable,\n// but fall back to using a MemoryVault by default. This, for example,\n// could be useful during development when you are iterating on embedded\n// files and don't want to have to rebuild for every change.\nconst assetVaultPathKey = \"ASSET_VAULT_PATH\"\n\n_ = os.Setenv(assetVaultPathKey, \"/\")\n\n// Create a filesystem vault and a memory vault to use.\nfsysAssetVault := goblin.NewFilesystemVault(os.Getenv(assetVaultPathKey))\nmemAssetVault := goblin.NewMemoryVault() // Loaded from an embedded vault\n\n// Create a vault selector that will use the filesystem asset vault\n// if the environment variable ASSET_VAULT_PATH has a non-empty vault,\n// use the embedded asset vault if not.\nassetVaultSelector := goblin.NewVaultSelector(\n    goblin.SelectEnvNotEmpty(assetVaultPathKey, fsysAssetVault),\n    goblin.SelectDefault(memAssetVault),\n)\n\n// Since ASSET_VAULT_PATH is not empty, we use the filesystem vault.\nv, _ := assetVaultSelector.GetVault()\nfmt.Printf(\"Vault: %s\\n\", v)\n\n// Output:\n// Vault: Filesystem Vault (/)\n```\n\n## Embedding Files\n\nTo embed files in your binary using Goblin, you'll use the `goblin` utility to generate a Go\ncode file with the contents of the file and a method to load the contents at runtime.\n\n**Note:** The public interface for the `goblin` utility will be changing and is not stabilized.\nIt'll be changing to hopefully be cleaner and more intuitive.\n\nThere are two common command line arguments that are used when create an embedded vault:\n\n* `--name` or `-n`: The name of the vault to embed. This will be used for any package, vault,\n  and file names in the generated code.\n* `--include-root` or `-r`: The root path of any included files. Any file paths in the vault\n  will be relative to this path. Defaults to the current working directory.\n* `--include` or `-i`: A [glob](https://golang.org/pkg/path/filepath/#Match) path to include\n  files for. Can be provided more than once.\n\nTo include all `.html` files in your project's web directory or a directory below it in a\nvault, for example, you would use:\n\n```bash\n$ goblin create --name assets --include-root /src/web --include *.html --include **/*.html \n```\n\nThis would result in a file called `goblin_assets.go` in the current directory to be created\nwith contents similar to the following:\n\n```go\npackage assets\n\nimport goblin \"github.com/aphistic/goblin\"\n\nfunc loadVaultAssets() (goblin.Vault, error) {\n\treturn goblin.LoadMemoryVault(goblinMemoryVaultXassets)\n}\n\nvar goblinMemoryVaultXassets = []byte{ /* lots of bytes */ }\n```\n\nIf you need to specify a package name other than the default (`assets` in our example), you can\nuse the `--package` or `-p` command line option to provide a different one.\n\n## What's With the Name?\n\nWhen I was trying to come up with a project name for a utility to embed binary files in Go\nbinaries one of the names I was working with included `gobin` for **Go** **Bin**aries and when\nI read it I misread it as `goblin` at one point and thought that would be a fun name since\ngoblins love treasure (your files!) and keeping things in vaults.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faphistic%2Fgoblin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faphistic%2Fgoblin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faphistic%2Fgoblin/lists"}