Embed static files in Go binaries (replacement for gobuffalo/packr)

Pkger

github.com/markbates/pkger is a tool for embedding static files into Go binaries. It will, hopefully, be a replacement for github.com/gobuffalo/packr/v2.

Requirements

  • Go 1.13+
  • Go Modules

How it Works (Module Aware Pathing)

Pkger is powered by the dark magic of Go Modules, so they're like, totally required.

With Go Modules pkger can resolve packages with accuracy. No more guessing and trying to figure out build paths, GOPATHS, etc... for this tired old lad.

With the module's path correctly resolved, it can serve as the "root" directory for that module, and all files in that module's directory are available.

Paths:

  • Paths should use UNIX style paths: /cmd/pkger/main.go
  • If unspecified the path's package is assumed to be the current module.
  • Packages can specified in at the beginning of a path with a : seperator. github.com/markbates/pkger:/cmd/pkger/main.go
  • There are no relative paths. All paths are absolute to the modules root.
  • Fully-qualified paths are embedded into the metadata of your static assets. If this behavior is undesirable, a preference is to build in a containerized environ, like docker, where the path strings are not ex-filtrating data about your development environment.
"github.com/gobuffalo/buffalo:/go.mod" => /go/pkg/mod/github.com/gobuffalo/[email protected]/go.mod

CLI

Installation

$ go get github.com/markbates/pkger/cmd/pkger
$ pkger -h

Usage

$ pkger

The result will be a pkged.go file in the root of the module with the embedded information and the package name of the module.

// ./pkged.go
package <.>

// Pkger stuff here

The -o flag can be used to specify the directory of the pkged.go file.

$ pkger -o cmd/reader

The result will be a pkged.go file in the cmd/reader folder with the embedded information and the package name of that folder.

// cmd/reader/pkged.go
package <reader>

// Pkger stuff here

Including Files at Package Time

There may be reasons where you don't reference a particular file, or folder, that you want embedded in your application, such as a build artifact.

To do this you may use either the github.com/markbates/pkger#Include function to set a no-op parser directive to include the specified path.

Alternatively, you may use the -include flag with the pkger and pkger list commands.

$ pkger list -include /actions -include github.com/gobuffalo/buffalo:/app.go

app
 > app:/actions
 > app:/actions/actions.go
 > app:/assets
 > app:/assets/css
 > app:/assets/css/_buffalo.scss
 > app:/assets/css/application.scss
 > app:/assets/images
 > app:/assets/images/favicon.ico
 > app:/assets/images/logo.svg
 > app:/assets/js
 > app:/assets/js/application.js
 > app:/go.mod
 > app:/locales/all.en-us.yaml
 > app:/public
 > app:/public/assets
 > app:/public/assets/.keep
 > app:/public/assets/app.css
 > app:/public/images
 > app:/public/images/img1.png
 > app:/public/index.html
 > app:/public/robots.txt
 > app:/templates
 > app:/templates/_flash.plush.html
 > app:/templates/application.plush.html
 > app:/templates/index.plush.html
 > app:/web
 > app:/web/web.go
 > github.com/gobuffalo/buffalo:/app.go
 > github.com/gobuffalo/buffalo:/logo.svg

Reference Application

The reference application for the README examples, as well as all testing, can be found at https://github.com/markbates/pkger/tree/master/pkging/pkgtest/testdata/ref.

├── actions
│   └── actions.go
├── assets
│   ├── css
│   │   ├── _buffalo.scss
│   │   └── application.scss
│   ├── images
│   │   ├── favicon.ico
│   │   └── logo.svg
│   └── js
│       └── application.js
├── go.mod
├── go.sum
├── locales
│   └── all.en-us.yaml
├── main.go
├── mod
│   └── mod.go
├── models
│   └── models.go
├── public
│   ├── assets
│   │   └── app.css
│   ├── images
│   │   └── img1.png
│   ├── index.html
│   └── robots.txt
├── templates
│   ├── _flash.plush.html
│   ├── application.plush.html
│   └── index.plush.html
└── web
    └── web.go

13 directories, 20 files

API Usage

Pkger's API is modeled on that of the os package in Go's standard library. This makes Pkger usage familiar to Go developers.

The two most important interfaces are github.com/markbates/pkger/pkging#Pkger and github.com/markbates/pkger/pkging#File.

type Pkger interface {
  Parse(p string) (Path, error)
  Current() (here.Info, error)
  Info(p string) (here.Info, error)
  Create(name string) (File, error)
  MkdirAll(p string, perm os.FileMode) error
  Open(name string) (File, error)
  Stat(name string) (os.FileInfo, error)
  Walk(p string, wf filepath.WalkFunc) error
  Remove(name string) error
  RemoveAll(path string) error
}

type File interface {
  Close() error
  Info() here.Info
  Name() string
  Open(name string) (http.File, error)
  Path() Path
  Read(p []byte) (int, error)
  Readdir(count int) ([]os.FileInfo, error)
  Seek(offset int64, whence int) (int64, error)
  Stat() (os.FileInfo, error)
  Write(b []byte) (int, error)
}

These two interfaces, along with the os#FileInfo, provide the bulk of the API surface area.

Open

func run() error {
	f, err := pkger.Open("/public/index.html")
	if err != nil {
		return err
	}
	defer f.Close()

	info, err := f.Stat()
	if err != nil {
		return err
	}

	fmt.Println("Name: ", info.Name())
	fmt.Println("Size: ", info.Size())
	fmt.Println("Mode: ", info.Mode())
	fmt.Println("ModTime: ", info.ModTime())

	if _, err := io.Copy(os.Stdout, f); err != nil {
		return err
	}
	return nil
}

Stat

func run() error {
	info, err := pkger.Stat("/public/index.html")
	if err != nil {
		return err
	}

	fmt.Println("Name: ", info.Name())
	fmt.Println("Size: ", info.Size())
	fmt.Println("Mode: ", info.Mode())
	fmt.Println("ModTime: ", info.ModTime())

	return nil
}

Walk

func run() error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 0, ' ', tabwriter.Debug)
	defer w.Flush()

	return pkger.Walk("/public", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		fmt.Fprintf(w,
			"%s \t %d \t %s \t %s \t\n",
			info.Name(),
			info.Size(),
			info.Mode(),
			info.ModTime().Format(time.RFC3339),
		)

		return nil
	})

}

Understanding the Parser

The github.com/markbates/pkger/parser#Parser works by statically analyzing the source code of your module using the go/parser to find a selection of declarations.

The following declarations in your source code will tell the parser to embed files or folders.

  • pkger.Dir("<path>") - Embeds all files under the specified path.
  • pkger.Open("<path>") - Embeds the file, or folder, of the specified path.
  • pkger.Stat("<path>") - Embeds the file, or folder, of the specified path.
  • pkger.Walk("<path>", filepath.WalkFunc) - Embeds all files under the specified path.
  • pkger.Include("<path>") - Include is a no-op that directs the pkger tool to include the desired file or folder.

CLI Usage

To see what declarations the parser has found, you can use the pkger parse command to get a JSON list of the declarations.

$ pkger parse

{
 ".": [
  {
   "file": {
    "Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/foo/bar/baz",
    "Path": {
     "Pkg": "app",
     "Name": "/foo/bar/baz"
    },
    "Here": {
     "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
     "ImportPath": "app",
     "Module": {
      "Path": "app",
      "Main": true,
      "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
      "GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
      "GoVersion": "1.13"
     },
     "Name": "main"
    }
   },
   "pos": {
    "Filename": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/main.go",
    "Offset": 629,
    "Line": 47,
    "Column": 27
   },
   "type": "pkger.MkdirAll",
   "value": "/foo/bar/baz"
  },
  {
   "file": {
    "Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/foo/bar/baz/biz.txt",
    "Path": {
     "Pkg": "app",
     "Name": "/foo/bar/baz/biz.txt"
    },
    "Here": {
     "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
     "ImportPath": "app",
     "Module": {
      "Path": "app",
      "Main": true,
      "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
      "GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
      "GoVersion": "1.13"
     },
     "Name": "main"
    }
   },
   "pos": {
    "Filename": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/main.go",
    "Offset": 706,
    "Line": 51,
    "Column": 25
   },
   "type": "pkger.Create",
   "value": "/foo/bar/baz/biz.txt"
  },
  ...
 ]
}

For a module aware list use the pkger list command.

$ pkger list

app
 > app:/assets
 > app:/assets/css
 > app:/assets/css/_buffalo.scss
 > app:/assets/css/application.scss
 > app:/assets/images
 > app:/assets/images/favicon.ico
 > app:/assets/images/logo.svg
 > app:/assets/js
 > app:/assets/js/application.js
 > app:/go.mod
 > app:/locales/all.en-us.yaml
 > app:/public
 > app:/public/assets
 > app:/public/assets/.keep
 > app:/public/assets/app.css
 > app:/public/images
 > app:/public/images/img1.png
 > app:/public/index.html
 > app:/public/robots.txt
 > app:/templates
 > app:/templates/_flash.plush.html
 > app:/templates/application.plush.html
 > app:/templates/index.plush.html
 > app:/web
 > app:/web/web.go
 > github.com/gobuffalo/buffalo:/logo.svg

The -json flag can be used to get a more detailed list in JSON.

$ pkger list -json

{
 "ImportPath": "app",
 "Files": [
  {
   "Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets",
   "Path": {
    "Pkg": "app",
    "Name": "/assets"
   },
   "Here": {
    "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets",
    "ImportPath": "",
    "Module": {
     "Path": "app",
     "Main": true,
     "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
     "GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
     "GoVersion": "1.13"
    },
    "Name": "assets"
   }
  },
  {
   "Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets/css",
   "Path": {
    "Pkg": "app",
    "Name": "/assets/css"
   },
   "Here": {
    "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets",
    "ImportPath": "",
    "Module": {
     "Path": "app",
     "Main": true,
     "Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
     "GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
     "GoVersion": "1.13"
    },
    "Name": "assets"
   }
  },
  ...
}
Owner
Mark Bates
Mark Bates is a full stack web developer with over 18 years of experience building high quality scalable applications for companies.
Mark Bates
Comments
  • pkger hangs

    pkger hangs

    After go install github.com/markbates/pkger/cmd/pkger on my MBP/Mojave (10.14.6) using go version go1.13 darwin/amd64 pkger hangs when invoked. I've let it run for 10 min before CRL+Cing it.

    Code includes this usage:

    import (
    	"net/http"
    	"strconv"
    
    	"github.com/markbates/pkger"
    )
    
    func HandleIndexHTML(w http.ResponseWriter, r *http.Request) {
    	asset, err := pkger.Open("/ui/index.html")
    	if err != nil {
    		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
    	}
    
    	w.Header().Add("Content-Type", "text/html")
    	w.Header().Add("Content-Length", strconv.Itoa(len(asset)))
    	w.Write(asset)
    }
    

    Am I misunderstanding the usage?

  • Uses `package main` even with -o

    Uses `package main` even with -o

    Contrary to what documentation claims the package directive is still main if I ask pkger to write the file in another directory.

    $ pkger -o config
    $ head -n 1 config/pkged.go 
    package main
    
  • Not working from `init()` method

    Not working from `init()` method

    After generating pkged.go, I was hoping I can run the same way without public folder. but it is failing...

    Sample code to reproduce...

    pkger-example.zip

    Before renaming public

    go run main.go pkged.go
    in shared init
    Name:  index.html
    Size:  257
    Mode:  -rw-rw-r--
    ModTime:  2019-11-10 15:59:20 -0800 PST
    in main init
    hi
    Name:  index.html
    Size:  257
    Mode:  -rw-rw-r--
    ModTime:  2019-11-10 15:59:20 -0800 PST
    

    After renaming public to public1

    go run main.go pkged.go
    in shared init
    2019/11/10 22:04:25 stat /mywork/pkger-example/public/index.html: no such file or directory
    exit status
    
  • Error when a directory contains no `.go` or `go.mod` files

    Error when a directory contains no `.go` or `go.mod` files

    Hi Mark,

    More than issue is a doubt to know if I'm doing wrong while use your library. I try to follow your examples and I've the follow structure:

    ├── cmd
    │   ├── reader
    │   │   ├── main.go
    ├── files
    │   ├── swapi.go
    ├── reader.go
    ├── go.mod
    

    The reader.go code:

    package pkg
    
    import (
    	"fmt"
    	"io"
    	"os"
    	"time"
    
    	"github.com/markbates/pkger"
    )
    
    func ReadCsv() error {
    	f, err := pkger.Open("/files/swapi.csv")
    	if err != nil {
    		return err
    	}
    	defer f.Close()
    
    	data, err := f.Stat()
    	if err != nil {
    		return err
    	}
    
    	fmt.Println("File name: ", data.Name())
    	fmt.Println("File size: ", data.Size())
    	fmt.Println("File mode: ", data.Mode())
    	fmt.Println("Modification time: ", data.ModTime().Format(time.RFC3339))
    
    	fmt.Println()
    	if _, err := io.Copy(os.Stdout, f); err != nil {
    		return err
    	}
    
    	return nil
    
    }
    

    So when I executed the code go run cmd/reader/main.go everything is fine, but if I move the reader.go inside another directory:

    ├── cmd
    │   ├── reader
    │   │   ├── main.go
    ├── files
    │   ├── swapi.go
    ├── pkg
    │   ├── reader.go
    ├── go.mod
    

    And I executed again the code go run cmd/reader/main.go I got the follow error:

    2019/11/09 15:57:49 exit status 1: go: cannot find main module; see 'go help modules'
    
    2019/11/09 15:57:49 open /files/swapi.csv: no such file or directory
    exit status 1
    

    I understand if the static files are in a level without any .go file that indicate a package, then the pkger can't find the go.mod. Because if I add a simple sample.go in the root folder, to the same level that files directory, then the application works fine.

    Could you help me to understand what is my wrong here?

  • Walk function seems to only pack the first alphabetical path

    Walk function seems to only pack the first alphabetical path

    Hi @markbates 👋!

    Context

    I've been trying to use pkger as a replacement for packr2 in a small tool I've been writing (github.com/paganotoni/admon).

    The things I need to replace initially are the assets and templates Boxes. To do so, I'm walking both paths with pkger and filling in a pckd.MemoryBox with those files so buffalo can use them.

    var (
            assetsBox    = packd.NewMemoryBox()
    	templatesBox = packd.NewMemoryBox()
    )
    func init() {
    	logrus.Info("Reading templates")
    	err := pkger.Walk("/web/templates", func(path string, info os.FileInfo, err error) error {
    		logrus.Info(path)
    
    		if err != nil {
    			return err
    		}
    
    		if info.IsDir() {
    			return nil
    		}
    
    		file, err := pkger.Open(path)
    		if err != nil {
    			return err
    		}
    
    		data, err := ioutil.ReadAll(file)
    		if err != nil {
    			return err
    		}
    
    		return templatesBox.AddBytes(path, data)
    	})
    
    	if err != nil {
    		logrus.Error(err)
    	}
    
    	logrus.Info("Reading assets")
    	err = pkger.Walk("/web/public", func(path string, info os.FileInfo, err error) error {
    		logrus.Info(path)
    
    		if err != nil {
    			return err
    		}
    
    		if info.IsDir() {
    			return nil
    		}
    
    		file, err := pkger.Open(path)
    		if err != nil {
    			return err
    		}
    
    		data, err := ioutil.ReadAll(file)
    		return assetsBox.AddBytes(path, data)
    	})
    
    	if err != nil {
    		logrus.Error(err)
    	}
    
    	renderEngine = render.New(render.Options{
    		HTMLLayout:   "admon.plush.html",
    		TemplatesBox: templatesBox,
    
    		AssetsBox: assetsBox,
    		Helpers:   helpers,
    	})
    }
    

    The problem

    The problem i'm facing is that pkger seems to only walk through the first path alphabetically. And is ignoring the second one as the following logs show:

    time="2019-10-23T08:21:47-05:00" level=info msg="Reading templates"
    time="2019-10-23T08:21:47-05:00" level=info msg="Reading assets"
    time="2019-10-23T08:21:47-05:00" level=info msg="github.com/paganotoni/admon:/web/public"
    time="2019-10-23T08:21:47-05:00" level=info msg="github.com/paganotoni/admon:/web/public/assets"
    time="2019-10-23T08:21:47-05:00" level=info msg="github.com/paganotoni/admon:/web/public/assets/admin.e4904589a02627deb099.css"
    time="2019-10-23T08:21:47-05:00" level=info msg="github.com/paganotoni/admon:/web/public/assets/admin.f11b630e4512aaa573d4.js"
    time="2019-10-23T08:21:47-05:00" level=info msg="github.com/paganotoni/admon:/web/public/assets/manifest.json"
    
  • Anyway to use files on disk for development like gobuffalo/packr?

    Anyway to use files on disk for development like gobuffalo/packr?

    With gobuffalo/packr you can use the actual files on the system for development, allowing you to swap your static file's contents without needing to rebuild. Is there a similar functionality here?

  • Suggestion: add ioutil.ReadFile equivalent

    Suggestion: add ioutil.ReadFile equivalent

    Go has a very useful ioutil.ReadFile function which slurps an entire file into memory.

    It would be very helpful to have an equivalent both at the top level and as part of the Pkger interface.

  • Binary using pkger not working outside of source folder

    Binary using pkger not working outside of source folder

    Hi, I ran pkger in a go modules enabled project, built the binary and ran it from the source folder and it worked. When I run this binary from /tmp it fails.

    log:

    ~/p/play-pkger (master|✚2…) $ cat cmd/play-pkger/play-pkger.go 
    package main
    
    import (
    	"fmt"
    
    	"github.com/markbates/pkger"
    )
    
    func main() {
    	err := run()
    	if err != nil {
    		panic(err)
    	}
    }
    
    func run() error {
    	f, err := pkger.Open("/LICENSE")
    	if err != nil {
    		return err
    	}
    	defer f.Close()
    
    	info, err := f.Stat()
    	if err != nil {
    		return err
    	}
    
    	fmt.Println("Name: ", info.Name())
    	fmt.Println("Size: ", info.Size())
    	fmt.Println("Mode: ", info.Mode())
    	fmt.Println("ModTime: ", info.ModTime())
    	return nil
    }
    ~/p/play-pkger (master|✚2…) $ pkger
    ~/p/play-pkger (master|✚2…) $ tree
    .
    ├── cmd
    │   └── play-pkger
    │       └── play-pkger.go
    ├── go.mod
    ├── go.sum
    ├── LICENSE
    └── pkged.go
    
    2 directories, 5 files
    ~/p/p/c/play-pkger (master|✚2…) $ go build -o /tmp/play-pkger
    ~/p/p/c/play-pkger (master|✚2…) $ /tmp/play-pkger
    Name:  LICENSE
    Size:  11353
    Mode:  -rw-r--r--
    ModTime:  2019-11-20 10:46:18.276189286 +0100 CET
    ~/p/p/c/play-pkger (master|✚2…) $ cd /tmp/
    /tmp $ /tmp/play-pkger
    2019/11/20 10:51:45 exit status 1: "go list -json -m": go list -m: not using modules
    
    panic: open /LICENSE: no such file or directory
    
    goroutine 1 [running]:
    main.main()
    	/home/play/pr/play-pkger/cmd/play-pkger/play-pkger.go:12 +0x44
    /tmp [2] $ 
    
  • [Bug] Doesn't work with `go install`

    [Bug] Doesn't work with `go install`

    Hi!

    I'm using Go 1.13.5.

    On my ./cmd/myapp/main.go:

    package main
    
    import "github.com/markbates/pkger"
    
    func main() {
    	pkger.Include("/configs")
    
    	// ...
    }
    
    // CopyFolder function for copy all files from app config
    func CopyFolder() error {
    	return pkger.Walk("/configs/dotfiles", func(path string, file os.FileInfo, err error) error {
    		// Define files paths
    		folder := "." + string(os.PathSeparator) + file.Name()
    
    		// Create files (skip directories)
    		if !file.IsDir() {
    			// Open file
    			from, err := pkger.Open(path)
    			ErrChecker(err)
    			defer from.Close()
    
    			// Create file
    			to, err := os.Create(folder)
    			ErrChecker(err)
    			defer to.Close()
    
    			// Copy file
    			_, err = io.Copy(to, from)
    			ErrChecker(err)
    
    			// Show report for each file
    			fmt.Printf("— File '%v' was copied!\n", folder)
    		}
    
    		// Default return
    		return nil
    	})
    }
    

    App structure:

    $ tree .
    
    myapp
    ├── cmd
    │   └── myapp
    │       └── main.go
    ├── configs
    │   └── dotfiles
    │       └── .env
    ├── go.mod
    ├── go.sum
    └── pkged.go
    

    I packed my app like this:

    $ pkger && go build -o myapp ./cmd/myapp/*.go
    

    If I run binary ./myapp from folder — all okay. Files from ./config was copied.

    But, if I run $ go install ./cmd/myapp and call binary (who installed to $GOPATH/bin) as usual, by $ myapp [args], I got this error:

    Error: lstat configs/dotfiles: no such file or directory
    

    What's wrong? How to solve this? Help me please 😞

  • A .go file *REQUIRED* at root of module?

    A .go file *REQUIRED* at root of module?

    Still experiencing the same issue as outlined in #34. @markbates, you mentioned this would be fixed in v0.12.3 in that thread. I'm using v0.12.8

    I get error:

     "go list -json -find <my_package>: cannot find module providing package <my_package>
    

    I addressed this by putting a dummy.go file at the root of the module.

    Is having a .go file at the root of the module, a requirement?

  • How to save included files/dirs from binary to outer folder?

    How to save included files/dirs from binary to outer folder?

    Hello.

    I write simple CLI script, which make some automation for creating web server (based on net/http). I include folder with completed app structure via pkger to binary, but how to save (or copy) packed app from binary to outer folder?

    I read README, but not sure it's possible?

    Something like ioutil.WriteFile(fileOutput, fileInput, 0644) will be great, but doesn't work with pkger.Open() file.

  • Go 1.18 Type Parameters Support

    Go 1.18 Type Parameters Support

    Running pkger 1.17.1 will error when running on Go 1.18 code that uses type parameters/generics. An example can be found in this gist.

    $ pkger
    2022/03/30 13:10:19 /tmp/pkger-test/main.go:10:13: expected '(', found '[' (and 5 more errors): ParseDir failed /tmp/pkger-test: /tmp/pkger-test
    

    An example of Go code that will cause the error.

    package main
    
    import (
    	"io"
    	"os"
    
    	"github.com/markbates/pkger"
    )
    
    func Example[T any]() {}
    
    func main() {
    	f, err := pkger.Open("/file.txt")
    	if err != nil {
    		panic(err)
    	}
    	defer func() { _ = f.Close() }()
    
    	if _, err := io.Copy(os.Stdout, f); err != nil {
    		panic(err)
    	}
    }
    
  • Why should I use this library instead of the native embed functionality?

    Why should I use this library instead of the native embed functionality?

    Maybe it would be nice if the readme featured some kind of comparison between the native embed and wrapping pkger. After skimming over the description it feels more or less like using embed.FS. Edit: Just to clarify, I don't mean to disrespect the work you're doing here. I just would love to see some of the project's core features to make a decision whether it makes sense for me to add another 3rd party library or not.

  • Support Go 1.17 build stanzas (constraints)

    Support Go 1.17 build stanzas (constraints)

    Go 1.17 is starting a migration with build constraints, so they are looking for //go:build ... stanzas in source files before any //+build ... lines. This breaks builds which check source code formatting/validation in CI that automatically updated.

    It can be resolved with gofmt -s -w pkged.go which will add the required line. Example

    The 1.17 release notes mention this change and the design proposal has a migration section for more details.

  • pkger cli

    pkger cli

    I use go v1.16.4 and have a mac running mojave. I create a simple go project as a module and tried to download pkger. However after that when I try the command pkger -h or any cli it says command not found. Can anybody help?

    Error: bash: pkger: command not found

    Thanks

  • "Write" not work

    //go:generate pkger
    package main
    
    import (
    	"fmt"
    	"time"
    
    	"github.com/markbates/pkger"
    	"github.com/markbates/pkger/pkging"
    )
    
    func main() {
    	var err error
    	Dir := pkger.Include("/static/run.log")
    
    	var f pkging.File
    	if f, err = pkger.Open(Dir); err != nil {
    		fmt.Println(err)
    		return
    	}
    	if _, err = f.Write([]byte("bbb")); err != nil {
    		fmt.Println(err)
    		return
    	}
    	f.Close()
    
    	fmt.Println("write end")
    	time.Sleep(time.Second * 3)
    
    	var f2 pkging.File
    	if f2, err = pkger.Open(Dir); err != nil {
    		fmt.Println(err)
    		return
    	}
    	var da []byte = make([]byte, 100)
    	if n, err := f2.Read(da); err != nil {
    		fmt.Println(err)
    		return
    	} else {
    		fmt.Println(string(da[:n]))
    	}
    	f2.Close()
    
    }
    
    go generate
    go build -o run.exe
    run
    // echo
    // aaa
    
Related tags
Golang binaries compiled on-demand for your system
Golang binaries compiled on-demand for your system

Go Binaries Go Binaries is an on-demand binary server, allowing non-Go users to quickly install tools written in Go without installing go itself, and

Dec 3, 2022
Eget is the best way to easily get pre-built binaries for your favorite tools.
Eget is the best way to easily get pre-built binaries for your favorite tools.

Eget: easy pre-built binary installation Eget is the best way to easily get pre-built binaries for your favorite tools. It downloads and extracts pre-

Dec 27, 2022
Package binaries for different operating systems in a single script, executable everywhere.

CrossBin Packages MacOS, Linux and Windows binaries, into a single script that is executable everywhere and executes the correct binary for the system

Oct 24, 2022
Build and (re)start go web apps after saving/creating/deleting source files.

unmaintained Fresh Fresh is a command line tool that builds and (re)starts your web application everytime you save a Go or template file. If the web f

Jan 2, 2023
The simple and easy way to embed static files into Go binaries.

NOTICE: Please consider migrating your projects to github.com/markbates/pkger. It has an idiomatic API, minimal dependencies, a stronger test suite (t

Dec 25, 2022
Get an embed.FS from inside an embed.FS
Get an embed.FS from inside an embed.FS

embed.FS wrapper providing additional functionality Features Get an embed.FS from an embedded subdirectory Handy Copy(sourcePath, targetPath) method t

Sep 27, 2022
Using brotli compression to embed static files in Go.
Using brotli compression to embed static files in Go.

?? Broccoli go get -u aletheia.icu/broccoli Broccoli uses brotli compression to embed a virtual file system of static files inside Go executables. A f

Nov 25, 2022
Use this program to embed sh scripts in binaries

sh2bin Use this program to embed sh scripts in binaries. Feel free to fork this

Jan 4, 2023
a better customizable tool to embed files in go; also update embedded files remotely without restarting the server

fileb0x What is fileb0x? A better customizable tool to embed files in go. It is an alternative to go-bindata that have better features and organized c

Dec 27, 2022
Static binary analysis tool to compute shared strings references between binaries and output in JSON, YAML and YARA

StrTwins StrTwins is a binary analysis tool, powered by radare, that is capable to find shared code string references between executables and output i

May 3, 2022
Generates go code to embed resource files into your library or executable

Deprecating Notice go is now going to officially support embedding files. The go command will support //go:embed tags. Go Embed Generates go code to e

Jun 2, 2021
Embed files into a Go executable

statik statik allows you to embed a directory of static files into your Go binary to be later served from an http.FileSystem. Is this a crazy idea? No

Dec 29, 2022
A tool to be used with 'go generate' to embed external template files into Go code.

templify A tool to be used with 'go generate' to embed external template files into Go code. Scenario An often used scenario in developing go applicat

Sep 27, 2022
Embed files into a Go executable

statik statik allows you to embed a directory of static files into your Go binary to be later served from an http.FileSystem. Is this a crazy idea? No

Jan 6, 2023
Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

Dec 29, 2022
Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

kubectl-slice: split Kubernetes YAMLs into files kubectl-slice is a neat tool that allows you to split a single multi-YAML Kubernetes manifest into mu

Jan 3, 2023
The forgotten go tool that executes and caches binaries included in go.mod files.
The forgotten go tool that executes and caches binaries included in go.mod files.

The forgotten go tool that executes and caches binaries included in go.mod files. This makes it easy to version cli tools in your projects such as gol

Sep 27, 2022
Create all possible binaries from go files
Create all possible binaries from go files

nextBuild.go Create all possible binaries of a project in go ChangeLog 0.0.1 ─ First release. Flags You can alter a few things when creating the binar

Dec 8, 2022
Create all possible binaries from go files
Create all possible binaries from go files

nextBuild.go Create all possible binaries of a project in go ChangeLog 0.0.1 ─ First release. Flags You can alter a few things when creating the binar

Dec 8, 2022
Create all possible binaries from go files

gopher-build-all Create all possible binaries of a project in go ChangeLog 0.0.2 Flags bin-folder-name ─ With this flag you can rename the output dire

Dec 8, 2022