Embed: file.ModTime returns time.Time{} instead of the file's modification time at the time it was embedded

I embedded a file like this:

package main

import (
	"fmt"
	"embed"
	"net/http"
)

//go:embed test.txt
var fs embed.FS

func main() {
	f, _ := fs.Open("test.txt")
	fi, _ := f.Stat()
	fmt.Println(fi.ModTime()) // 0001-01-01 00:00:00 +0000 UTC

	// With Last-Modified header
	http.Handle("/dir/", http.StripPrefix("/dir/", http.FileServer(http.Dir("."))))
	
	// Without Last-Modified header -> easy to circumvent, but not suitable as drop-in replacement
	http.Handle("/embed/", http.StripPrefix("/embed/", http.FileServer(http.FS(fs))))

	http.ListenAndServe(":8080", nil)
}

I expected fi.ModTime to return the file’s modification time at the time it was embedded.

time.Time{} is returned instead (https://golang.org/src/embed/embed.go#229). The above program includes an example of when this becomes relevant. Please help me understand this design decision.

If I’m reading the git blame correctly, it looks like it was committed this way in the initial implementation. Based on that, I suspect it wasn’t considered important to include it. You could open an issue requesting the functionality, maybe add a PR with an implementation submitting a patch that implements this functionality.

I’m curious, what do you want the embedded file’s original modification time for?

EDIT: You could probably wrap the embedded fs.FS to implement this yourself with a go:generate command.

Oh, I found it:

It’s about build reproducibility. Embedded files with different modification times but the same contents shouldn’t result in different builds.

2 Likes

Excellent find, thanks. I now understand the rationale behind this design, but this makes the documentation (https://golang.org/pkg/embed/#hdr-File_Systems) misleading. At the very least this justifies a warning. Do you know how to properly report this?