本篇博客分两种情况来解决golang项目访问静态资源404问题,第一种是自己将静态页面手动创建或者复制到golang项目中。第二种情况是采用第三方框架vue-elementui-template打包生成的文件静态资源404问题

简单项目的静态资源404问题

运行golang项目后,打开index.html页面后各种js、css加载404问题。不多比比,直接上代码。

test1.go

package main
import (
	"fmt"
	"html"
	"html/template"
	"log"
	"net/http"
	"time"
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("index.html")
	if err != nil {
		log.Println(err)
	err = t.Execute(w, nil)
	if err != nil {
		log.Println(err)
var count int = 1
func Task(w http.ResponseWriter, r *http.Request) {
	fmt.Printf(" ------ here is Task[%d] ------- \n", count)
	defer r.Body.Close()
	// 模拟延时
	time.Sleep(time.Second * 2)
	fmt.Fprintf(w, "Response.No.%d: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))
	count++
	answer := `{"status:":"OK"}`
	w.Write([]byte(answer))
func Task1(w http.ResponseWriter, r *http.Request) {
	fmt.Printf(" ------ here is Task1[%d] ------- \n", count)
	defer r.Body.Close()
	// 模拟延时
	time.Sleep(time.Second * 2)
	fmt.Fprintf(w, "Response.No[%d]: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))
	count++
	answer := `{"status:":"OK"}`
	w.Write([]byte(answer))
func main() {
	// 调用后台接口
	http.HandleFunc("/hello/world", Task)
	http.HandleFunc("/hello/world1", Task1)
	// 启动静态文件服务
	http.Handle("/template/", http.StripPrefix("/template/", http.FileServer(http.Dir("template")))) 
	http.Handle("/libs/", http.StripPrefix("/libs/", http.FileServer(http.Dir("libs"))))
	http.HandleFunc("/index", IndexHandler)
	fmt.Println("服务端口:8000") //控制台输出信息
	err := http.ListenAndServe(":8000", nil) //设置监听的端口
	if err != nil {
		log.Fatal("ListenAndServe: ", err)

解释1:go语言中的http.HandleFunc("/index", IndexHandler)相当于,前端访问接口index,后端去调用方法IndexHandler。
相当于java的

@RequestMapping("/index")
public void IndexHandler() {
	// 在此,怀念我那逝去的java

等价于go中的

http.HandleFunc("/index", IndexHandler)

index.html代码

<!DOCTYPE html>
  <meta charset="UTF-8">
  <!-- import CSS -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <link rel="stylesheet" href="template/css/test.css">
</head>
  <div id="app">
      <span class="mybtn">也无风雨、也无晴</span>
      <el-button @click="httpGet1">get请求</el-button>
    <el-button @click="openPage">Button</el-button>
    <el-dialog :visible.sync="visible" title="Hello world">
      <p>Try Element</p>
    </el-dialog>
  </div>
</body>
  <!-- import Vue before Element -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <!--script src="./libs/axios-0.16.2.min.js"></script,不知道这个为啥不行,可以把下面这个直接下载下来,打包到项目里-->
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="./libs/vue/vue-2.2.2.min.js"></script>
  <script src="./libs/jquery/jquery.min.js"></script>
  <!-- import JavaScript -->
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: function() {
        return { visible: false }
      methods:{
        openPage:function(){
            alert("sdfsdfs")
            window.open("./template/user/user.html")
        httpGet1:function(){
          axios({
                method:'get',
                // 对链接前缀进行封装,后台使用的时候直接引用前缀即可
                url:'http://localhost:8000/hello/world'
            }).then(function(resp){
                console.log(resp.data);
            }).catch(resp => {
                console.log('请求失败:'+resp.status+','+resp.statusText);
            });
  </script>
</html>
go run test1.go

其中蓝色字体是为了验证不同文件夹下的css的引用

点击下载项目完整代码

vue-element-template打包生成的静态资源404问题

上面的项目是自己手动创建的静态页面和js,html页面里对于js、css的引用都是人为可控的。但是如果是使用的第三方框架,如vue-elemen-template,因为浏览器是不认识.vue文件的,那么开发完成后是将vue等打包成浏览器能解析的js、css、html等文件。打包生成的.html里对于js等的引用路径是可以修改的,但是太过于麻烦,有兴趣的道友可以自行百度,我这里就按它默认生成的资源,然后在go代码里去解决404问题。

工欲善其事,必先利其器。既然是404那么就是静态资源没有加载到,我们就需要了解go是怎么加载静态资源的。那就是函数http.StripPrefix与http.FileServer

我们来看看这行代码

http.Handle("/template/", http.StripPrefix("/template/", http.FileServer(http.Dir("template")))) 

以上http.Handle("/template/",就是相当于一个请求,当前端发起http:www.xxx.com:9527/template时,会进入该方法。即
相当于java的

@RequestMapping("/index")
public void IndexHandler() {
	// 在此,怀念我那逝去的java

等价于go中的

http.HandleFunc("/index", IndexHandler)

然后我们看http.StripPrefix方法,它就是拦截请求中含有/template/前缀的资源请求,然后将该前缀替换成http.Dir(“template”)中的template。

http.Dir表示文件的起始路径,空即为当前路径。调用Open方法时,传入的参数需要在前面拼接上该起始路径得到实际文件路径。

http.FileServer的返回值类型是http.Handler,所以需要使用Handle方法注册处理器。http.FileServer将收到的请求路径传给http.Dir的Open方法打开对应的文件或目录进行处理。 在上面的程序中,如果请求路径为/static/hello.html,那么拼接http.Dir的起始路径.,最终会读取路径为./static/hello.html的文件。

有时候,我们想要处理器的注册路径和http.Dir的起始路径不相同。有些工具在打包时会将静态文件输出到public目录中。 这时需要使用http.StripPrefix方法,该方法会将请求路径中特定的前缀去掉,然后再进行处理:如下代码

package main
import (
  "log"
  "net/http"
func main() {
  mux := http.NewServeMux()
  mux.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir("./public"))))
  server := &http.Server {
    Addr: ":8080",
    Handler: mux,
  if err := server.ListenAndServe(); err != nil {
    log.Fatal(err)

这时,请求localhost:8080/static/hello.html将会返回./public/hello.html文件。 路径/static/index.html经过处理器http.StripPrefix去掉了前缀/static得到/index.html,然后又加上了http.Dir的起始目录./public得到文件最终路径./public/hello.html。
如果你就想请求static下的文件,那么就将http.Dir中写static即可。
简单点理解就是将含有static的请求拦截,并将http.Dir中的路径替换掉http.StripPrefix中的路径,拼接成新的文件路径然后相应给前端。

好了,大致原理我们明白了。那么实际操作一下,看我的代码。
目录结构
在这里插入图片描述
dist文件夹结构
在这里插入图片描述
index.html页面的代码
在这里插入图片描述
,我们可以看到它打包生成后对静态文件的应用全部都是以static开头的,那么在浏览器加载静态资源的时候,请求的路径就是

GET http://127.0.0.1:8090/static/js/app.js

在这里插入图片描述
这样的请求路径显然是请求不到数据的,那么我们只需要将http://127.0.0.1:8090/static/js/app.js的请求路径修改为
http://127.0.0.1:8090/src/views/vue-element-template/dist/static/js/app.js即可。也就是我们上面分析的将static的请求拦截并且替换路径即可,
我们的项目文件路径是/src/views/vue-element-template/dist/static/
就一行代码,

// 启动静态文件服务
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./src/views/vue-element-template/dist/static/")))) 

vscode里切换到main.go所在的路径,运行

go run main.go

再次打开浏览器,问题解决

在这里插入图片描述
此处贴出部分代码
main.go

package main
import (
	"fmt"
	"engine_stability_platform/src/app/httpServer"
func main() {
	fmt.Println("main.....")
	httpServer.Start()

httpServer.go

package httpServer
import (
	"fmt"
	. "fmt"
	"html"
	"html/template"
	"net/http"
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("src/views/vue-element-template/dist/index.html")
	if err != nil {
		fmt.Println(err)
	err = t.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
var count int = 1
// 测试demo
func Task(w http.ResponseWriter, r *http.Request) {
	Printf(" ------ here is Task[%d] ------- \n", count)
	Fprintf(w, "Response.No.%d: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))
	count++
	answer := `{"status:":"OK"}`
	w.Write([]byte(answer))
func Task1(w http.ResponseWriter, r *http.Request) {
	Printf(" ------ here is Task1[%d] ------- \n", count)
	Fprintf(w, "Response.No[%d]: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))
	count++
	answer := `{"status:":"OK"}`
	w.Write([]byte(answer))
var server *http.Server
func Start() {
	Println("===== This is http server =====")
	mux := http.NewServeMux()
	mux.HandleFunc("/hello/world", Task)
	mux.HandleFunc("/hello/world1", Task1)
	// 启动静态文件服务
	mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./src/views/vue-element-template/dist/static/"))))
	mux.HandleFunc("/index", IndexHandler)
	if server != nil {
		// 避免重复start server 端口泄露
		server.Close()
	// 设置服务器
	server := &http.Server{
		Addr: "127.0.0.1:8090",
		Handler: mux,
	// 设置服务器监听端口
	server.ListenAndServe()

index.html

<!DOCTYPE html>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="icon" href="favicon.ico">
    <title>Vue Admin Template</title>
  <link href="static/js/app.js" rel="preload" as="script"><link href="static/js/chunk-elementUI.js" rel="preload" as="script"><link href="static/js/chunk-libs.js" rel="preload" as="script"><link href="static/js/runtime.js" rel="preload" as="script"></head>
    <noscript>
      <strong>We're sorry but Vue Admin Template doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  <script type="text/javascript" src="static/js/runtime.js"></script><script type="text/javascript" src="static/js/chunk-elementUI.js"></script><script type="text/javascript" src="static/js/chunk-libs.js"></script><script type="text/javascript" src="static/js/app.js"></script></body>
</html>

补充:vue-element-template生成的资源文件夹也可以在vue.config.js里进行更改
在这里插入图片描述

参考文章:https://blog.csdn.net/whatday/article/details/109747385?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242.1

go读取静态文件.html、css、js404问题简单项目的静态资源404问题vue-element-template打包生成的静态资源404问题本篇博客分两种情况来解决golang项目访问静态资源404问题,第一种是自己将静态页面手动创建或者复制到golang项目中。第二种情况是采用第三方框架vue-elementui-template打包生成的文件静态资源404问题简单项目的静态资源404问题问题运行golang项目后,打开index.html页面后各种js、css加载404问题。不多比比,直 csstext := "td {width: 100px; height: 100px;}" ss := css.Parse(csstext) rules := ss.GetCSSRuleList() for _, rule := range rules { fmt.Println(rule.Style.Selector.Text()) fmt.Println(rule.Style.Styles)
golang自带的http.SeverMux路由实现简单,本质是一个map[string]Handler,是请求路径与该路径对应的处理函数的映射关系。实现简单功能也比较单一: 不支持正则路由, 这个是比较致命的 只支持路径匹配,不支持按照Method,header,host等信息匹配,所以也就没法实现RESTful架构 而gorilla/mux是一个强大的路由,小巧但是稳定高效,不仅...
一、检查URL和页面名字拼写是否正确 二、检查URL的端口号是否和项目设置的端口号一致 三、如果HTML写在spring项目的resource的template 文件夹里,检查pom.xml是否添加以下依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId&g 在 GitHub 上稳定更新,觉得不错请点个 Star ❤️ 如转载分享,请保留出处,谢谢 ???? 原文地址: https://shockerli.net/post/go-awesome GitHub: https://github.com/shockerli/go-awesome 官网: ...
vtk.js 是一个 JavaScript 库,用于创建三维计算机图形。它不能直接读取 DICOM 文件。你需要使用其他库,如 CornerstoneJS 或 dcmjs,将 DICOM 文件转换为 vtk.js 可识别的格式,然后再在 vtk.js 中使用。 示例代码: // 使用 CornerstoneJS 库读取 DICOM 文件 cornerstone.loadImage(dicomFile).then(function(image) { // 将 CornerstoneJS 返回的图像数据转换为 vtk.js 可识别的格式 var vtkImageData = vtk.Common.DataModel.vtkImageData.newInstance({ spacing: image.rowPixelSpacing, origin: [0, 0, 0], extent: [0, image.columns - 1, 0, image.rows - 1, 0, 0], scalarType: 'Int16' vtkImageData.getPointData().setScalars(image.getPixelData()); // 在 vtk.js 中使用转换后的图像数据 var volumeMapper = vtk.Rendering.Core.vtkVolumeMapper.newInstance(); volumeMapper.setInputData(vtkImageData); var volume = vtk.Rendering.Core.vtkVolume.newInstance(); volume.setMapper(volumeMapper); renderer.addVolume(volume);

点击下载项目完整代码