在Go(Golang)中使用http.filesystem提供没有第三方库的字符串映射

时间:2018-09-11 02:18:08

标签: go embeddedwebserver

我只是从Go开始,正在尝试学习如何构建简单的Web应用程序而无需使用第三方库/软件包。

我以this postthis code为准则,共同破解了以下内容:

package main

import (
    "bytes"
    "net/http"
    "os"
    "path"
    "time"
)

type StaticFS map[string]*staticFile

type staticFile struct {
    name string
    data []byte
    fs   StaticFS
}

func LoadAsset(name string, data string, fs StaticFS) *staticFile {
    return &staticFile{name: name,
        data: []byte(data),
        fs:   fs}
}

func (fs StaticFS) prepare(name string) (*staticFile, error) {
    f, present := fs[path.Clean(name)]
    if !present {
        return nil, os.ErrNotExist
    }
    return f, nil
}

func (fs StaticFS) Open(name string) (http.File, error) {
    f, err := fs.prepare(name)
    if err != nil {
        return nil, err
    }
    return f.File()
}

func (f *staticFile) File() (http.File, error) {
    type httpFile struct {
        *bytes.Reader
        *staticFile
    }
    return &httpFile{
        Reader:     bytes.NewReader(f.data),
        staticFile: f,
    }, nil
}

//implement the rest of os.FileInfo
func (f *staticFile) Close() error {
    return nil
}

func (f *staticFile) Stat() (os.FileInfo, error) {
    return f, nil
}

func (f *staticFile) Readdir(count int) ([]os.FileInfo, error) {
    return nil, nil
}

func (f *staticFile) Name() string {
    return f.name
}

func (f *staticFile) Size() int64 {
    return int64(len(f.data))
}

func (f *staticFile) Mode() os.FileMode {
    return 0
}

func (f *staticFile) ModTime() time.Time {
    return time.Time{}
}

func (f *staticFile) IsDir() bool {
    return false
}

func (f *staticFile) Sys() interface{} {
    return f
}

func main() {

    const HTML = `<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<p>Hello World</p>
</main>
</body>
</html>
`

    const CSS = `
p {
    color:red;
    text-align:center;
} 
`
    ASSETS := make(StaticFS)
    ASSETS["index.html"] = LoadAsset("index.html", HTML, ASSETS)
    ASSETS["style.css"] = LoadAsset("style.css", CSS, ASSETS)
    http.Handle("/", http.FileServer(ASSETS))
    http.ListenAndServe(":8080", nil)
}

可以很好地编译,但是除了找不到404页以外,实际上不会产生任何结果。

我想要实现的是在我的应用程序中包含一个程序包,该程序包使我可以制作地图,将一些静态内容(如CSS和JS)嵌入其中,然后将其与http.Handle一起使用-无需使用go等第三方工具-bindata,米饭或其他任何东西。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

这是我们需要查看的主要代码,该代码来自Sub Test() Dim xWb As Workbook Dim xToBook As Workbook Dim xStrPath As String Dim xFileDialog As FileDialog Dim xFile As String Dim xFiles As New Collection Dim I As Long Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker) xFileDialog.AllowMultiSelect = False xFileDialog.Title = "Select a folder [Kutools for Excel]" If xFileDialog.Show = -1 Then xStrPath = xFileDialog.SelectedItems(1) End If If xStrPath = "" Then Exit Sub If Right(xStrPath, 1) <> "\" Then xStrPath = xStrPath & "\" xFile = Dir(xStrPath & "*.xlsx") If xFile = "" Then MsgBox "No files found", vbInformation, "Kutools for Excel" Exit Sub End If Do While xFile <> "" xFiles.Add xFile, xFile xFile = Dir() Loop Set xToBook = ThisWorkbook If xFiles.Count > 0 Then For I = 1 To xFiles.Count Set xWb = Workbooks.Open(xStrPath & xFiles.Item(I)) xWb.Worksheets(1).Copy after:=xToBook.Sheets(xToBook.Sheets.Count) On Error Resume Next ActiveSheet.Name = xWb.Name On Error GoTo 0 xWb.Close False Name xStrPath & xFiles.Item(I) As "C:\Users\userfolder\Desktop\Archive Test\" & xFiles.Item(I) ' new added' Kill xStrPath & xFiles.Item(I) ' new added' Next I End If End Sub 的来源:

http.FileServer

func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) { upath := r.URL.Path if !strings.HasPrefix(upath, "/") { upath = "/" + upath r.URL.Path = upath } serveFile(w, r, f.root, path.Clean(upath), true) } // name is '/'-separated, not filepath.Separator. func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) { const indexPage = "/index.html" // redirect .../index.html to .../ // can't use Redirect() because that would make the path absolute, // which would be a problem running under StripPrefix if strings.HasSuffix(r.URL.Path, indexPage) { localRedirect(w, r, "./") return } f, err := fs.Open(name) if err != nil { msg, code := toHTTPError(err) Error(w, msg, code) return } defer f.Close() ... } 方法中,您将看到对未导出函数的调用。

ServeHTTP

其中serveFile(w, r, f.root, path.Clean(upath), true) 是请求的URL路径,保证以“ /”开头。

upath中,将调用serveFile,其中fs.Open(name)是您提供的fs,而FileSystem是我们作为name传递的参数。请注意,path.Clean(upath)已经被调用,因此您无需在path.Clean方法中调用它。

这里的要点是,您存储的“文件名”前面没有“ /”,这表示它们位于文件系统的根目录中。

您可以用两种不同的方法来解决。

1。

prepare

2。

ASSETS["/index.html"] = LoadAsset("index.html", HTML, ASSETS)
ASSETS["/style.css"] = LoadAsset("style.css", CSS, ASSETS)