go: `//go:embed ` doesn't work

What version of Go are you using (go version)?

go version go1.16.4 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/user/.cache/go-build"
GOENV="/home/user/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/user/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/user/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.4"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3225948580=/tmp/go-build -gno-record-gcc-switches"

What did you do?

There is a following package:

  • main.go
  • README.md
  • assets:
    • assets.go

assets.go contains package assets loaded with //go:embed directive. I’d like to add README.md file to assets.go, but //go:embed ../README.md doesn’t work

What did you expect to see?

the program should compile and work fine.

What did you see instead?

assets/assets.go:59:12: pattern ../README.md: invalid pattern syntax

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 22
  • Comments: 25 (4 by maintainers)

Commits related to this issue

Most upvoted comments

I agree. It makes sense to limit go:embed access to the whole directory of the current module rather than the current directory. One should be able to embed files within the whole “sub-tree” of the root directory of the current module. Right now, I end up applying the following pattern:

//go:generate cp -r ../../assets ./local-asset-dir
//go:embed local-asset-dir
var assetFs embed.FS

This works but it looks bad and I would like to avoid it.

Wouldn’t it be nice if embed could support predefined variables like ‘dirname’ or ‘projectname’ to avoid some unexpected bug and thus avoid the ‘…’ or ‘.’?

This is intentional and documnted

Patterns may not contain ‘.’ or ‘…’ or empty path elements, nor may they begin or end with a slash.

This was an explicit design decision:

Because embed.Files implements fs.FS, it cannot provide access to files with names beginning with …, so files in parent directories are also disallowed entirely, even when the parent directory named by … does happen to be in the same module.

ref: https://go.googlesource.com/proposal/+/master/design/draft-embed.md

maybe do this,Create a new assets.go in the directory that needs to be packaged

package assets

import "embed"

//go:embed *
var Assets embed.FS

Then use this variable in another package

a :=&assets.Assets

it sounds nice! Maybe we should make a new issue @JuanigTorres ?

If it’s still relevant I found good answer here.

it sounds nice! Maybe we should make a new issue @JuanigTorres ?

yah, this solution is possible, but it would be a bit crazy. I’d need to add go:embed directive in main.go and pass on embeded variable to my app? it doesn’t seem right.

It still can’t cross module boundaries, and if it’s in the same module you can just put the embed directive in a go file in the parent directory

It is stupid to just match child direction. Why do you always want to teach us how to layout our projects?

@korya , does your solution work to embed one file into a slice of bytes?

It should work.

@korya what do you mean by go:generate ../../assets ./local-asset-dir?

Sorry, there is a typo. I missed cp -r. It should be //go:generate cp -r ../../assets ./local-asset-dir. I’ve fixed my original post.