It's important to understand how Go's http package handles route matching as it's a bit different from other languages/frameworks. HandleFunc uses ServeMux under the hood and (from the docs):
ServeMux is an HTTP request multiplexer. It matches the URL of each incoming request against a list of registered patterns and calls the handler for the pattern that most closely matches the URL. [emphasis mine]
Given this behavior, I would recommend creating explicit handlers for each folder in static (e.g. css/, js/), or putting all in a single subfolder of static, and then respond with your index.html file for all other requests (using the root route (/)). This works because requests with routes prefixed by /css/ or /js/ will more closely match the appropriate static handler routes, while all others will not and therefore only most closely match the root route. You just need to be sure not to create conflicting routes on your front-end.
This way any request explicitly for CSS/JS/image assets will be handled by serving the static directory and all other requests will be responded to with your React app.
Here's an example (leaving out your wrapHandler for simplicity):
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "static/index.html")
})
http.Handle("/js/", http.FileServer(http.Dir("static")))
http.Handle("/css/", http.FileServer(http.Dir("static")))
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
or if you want to be a bit more explicit:
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "static/index.html")
})
jsFs := http.FileServer(http.Dir("static/js"))
http.Handle("/js/", http.StripPrefix("/js", jsFs))
cssFs := http.FileServer(http.Dir("static/css"))
http.Handle("/css/", http.StripPrefix("/css", cssFs))
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
My website works pretty much the same way (using Vue instead of React).
An Improvement
As mentioned above, you might consider putting all you static assets in a sub folder of your current static/ folder. Consider structuring your files like this:
public/
index.html
static/
css/
js/
img/
Which is the default file structure for built React apps (but public is called build by default).
This will let you use the above approach in a more streamlined way since you'll only need one fileserver handler for all static assets. Then you can use the following code:
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/index.html")
})
fs := http.FileServer(http.Dir("public/static/"))
http.Handle("/static/", http.StripPrefix("/static", fs))
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}