当前位置: 首页 > 面试题库 >

为什么以及何时ResponseWriter会生成原始html?

潘鸿文
2023-03-14
问题内容

我不明白为什么代码会正确生成view.html和post.html数据,但全部显示为原始文本。我一直在这里遵循指南,并且在构建它时,我认为将从Execute函数生成的html发送到ResponserWriter,后者将处理显示该消息,但是出现的错误似乎表明我对Execute的理解或ResponseWriter错误。

package main

import (
    "os"
    "fmt"
    "time"
    "bufio"
    "net/http"
    "html/template"
)

type UserPost struct {
    Name string
    About string
    PostTime string
}

func check(e error) {
    if e != nil {
        fmt.Println("Error Recieved...")
        panic(e)
    }
}


func lineCounter(workingFile *os.File) int {
    fileScanner := bufio.NewScanner(workingFile)
    lineCount := 0
    for fileScanner.Scan() {
        lineCount++
    }
    return lineCount
}

func loadPage(i int) (*UserPost, error) {
    Posts,err := os.Open("dataf.txt")
    check(err)
    var PostArray [512]UserPost = parsePosts(Posts,i)
    Name := PostArray[i].Name 
    About := PostArray[i].About
    PostTime := PostArray[i].PostTime
    Posts.Close()
    return &UserPost{Name: Name[:len(Name)-1], About: About[:len(About)-1], PostTime: PostTime[:len(PostTime)-1]}, nil
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
    tmp,err := os.Open("dataf.txt")
    check(err)
    num := (lineCounter(tmp)/3)
    tmp.Close()
    for i := 0; i < num; i++ {
        p, _ := loadPage(i)
        t, _ := template.ParseFiles("view.html")
        t.Execute(w, p)
    }
    p := UserPost{Name: "", About: "", PostTime: ""}
    t, _ := template.ParseFiles("post.html")
    t.Execute(w, p)
}

func inputHandler(w http.ResponseWriter, r *http.Request) {
    Name := r.FormValue("person")
    About := r.FormValue("body")
    PostTime := time.Now().String()

    filePaste,err := os.OpenFile("dataf.txt", os.O_RDWR | os.O_CREATE | os.O_APPEND | os.SEEK_END, 0666)
    check(err)
    filePaste.WriteString(Name+"~\n")
    filePaste.WriteString(About+"~\n")
    filePaste.WriteString(PostTime+"~\n")
    filePaste.Close()
    fmt.Println("Data recieved: ", Name,About,PostTime)
    http.Redirect(w, r, "/#bottom", http.StatusFound) //Use "/#bottom" to go to bottom of html page.
}

//os.File is the file type.
func parsePosts(fileToParse *os.File,num int) [512]UserPost {
    var buffer [512]UserPost
    reader := bufio.NewReader(fileToParse)

    //This For loop reads each "forum post" then saves it to the buffer, then iterates to the next.
    for i := 0;i <= num; i++ {
        currentPost := new(UserPost)
        str, err := reader.ReadString('~')
        check(err)
        currentPost.Name = str

        //I search for '~' because my files save the end of reading line with that, so i can keep formatting saved (\n placement).
        str2, err2 := reader.ReadString('~')
        check(err2)
        currentPost.About = str2

        str3, err3 := reader.ReadString('~')
        check(err3)
        currentPost.PostTime = str3

        buffer[i] = *currentPost
        }   
    return buffer
}

func main() {
    fmt.Println("Listening...")
    http.HandleFunc("/", viewHandler)
    http.HandleFunc("/post/", inputHandler)
    http.ListenAndServe(":8080", nil)
}

view.html

<h4>{{.Name}}</h4>

<font size="3">
    <div>{{printf "%s" .About}}</div>
</font>
<br>
<font size="2" align="right">
    <div align="right">{{.PostTime}}</div>
</font>

post.html

<form action="/post/" method="POST">

<div><textarea name="person" rows="1" cols="30">{{printf "%s" .Name}}</textarea></div>

<div><textarea name="body" rows="5" cols="100">{{printf "%s" .About}}</textarea></div>

<div><input type="submit" value="Submit"></div>

<a name="bottom"></a>
</form>

我目前正在从一个空的dataf.txt文件读取。


问题答案:

如提示所示,这是因为您尚未设置内容类型。引用自http.ResponseWriter

// Write writes the data to the connection as part of an HTTP reply.
// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
// before writing the data.  If the Header does not contain a
// Content-Type line, Write adds a Content-Type set to the result of passing
// the initial 512 bytes of written data to DetectContentType.
Write([]byte) (int, error)

如果您自己未设置内容类型,则第一个调用ResponseWriter.Write()将调用http.DetectContentType()以猜测要设置的内容。如果您发送的内容以开头"<form>",则不会将其检测为HTML,而是"text/plain; charset=utf-8"会进行设置(“指示”浏览器将内容显示为文本,而不尝试将其解释为HTML)。

"<html>"例如,如果内容以开头,则内容类型"text/html; charset=utf-8"将自动设置,并且无需进一步操作即可工作。

但是,如果您知道要发送的内容,请不要依赖自动检测,而且,自己设置它比在其上运行检测算法要快得多,因此只需在写入/发送任何数据之前添加以下行即可:

w.Header().Set("Content-Type", "text/html; charset=utf-8")

并使post.html模板成为完整的有效HTML文档。

Also another piece of advice: in your code you religiously omit checking
returned errors. Don’t do that. The least you could do is print them on the
console. You will save a lot of time for yourself if you don’t omit errors.



 类似资料:
  • 问题内容: 我正在使用ant生成javadocs,但是一遍又一遍地获取此异常-为什么? 我正在使用JDK 1.6.0_06 版本。 问题答案: 看来这已被报告为Java错误。这似乎是由于使用了第三方库(例如JUnit)中的注释,而在Javadoc调用中不包含带有该注释的jar。 如果是这种情况,只需在javadoc上使用-classpath选项并包括额外的jar文件。

  • 问题内容: 抱歉,如果我有点模棱两可,但是我试图了解使用Node.js而不是其他服务器端语言的真正优势。 我是JavaScript爱好者,所以我可能会玩Node.js,但我想知道是否应该在项目中使用它。 问题答案: 在V8上发生了异步非阻塞I / O 构建。 因此,我们拥有了Google JavaScript解释器V8的所有性能提升。由于JavaScript性能竞赛尚未结束,您可以期望Google

  • 所有其他唤醒锁都是有意义的,例如开发人员希望在执行某些操作时屏幕不会关闭。但在部分唤醒锁定文档中说: 如果您保持部分唤醒锁定,CPU将继续运行,而不考虑任何显示超时或屏幕状态,甚至在用户按下电源按钮后。在所有其他唤醒锁中,CPU将运行,但用户仍可以使用电源按钮将设备置于睡眠状态。 这是否意味着在执行某些操作时CPU可能会关闭?是否需要在服务中获取唤醒锁?

  • 首先,我知道volatile不会使多个操作(如)成为原子操作。这个问题是关于单个读或写操作的。 我最初的理解是,volatile只是执行了一个内存屏障(即其他线程将能够看到更新的值)。 现在我已经注意到JLS第17.7节说volatile还提供了一个读取或写入原子。例如,给定两个线程,两个线程都将不同的值写入,那么x最终将恰好表示其中一个值。 我很好奇这怎么可能。在一个32位系统上,如果两个线程并

  • 我正在使用 https://github.com/OpenAPITools/openapi-generator 为我的应用编程接口创建一个客户端。它基本上工作正常,但是生成器创建了许多类型,这些类型封装了包括任何复杂性类型的参数,例如、、 例如 其中InlineObject11定义为 这有什么意义?为什么生成的客户端不接受流再平衡贸易文件(Stream rebalanceTradeFile),而不

  • 问题内容: 我一直在将从服务接收的所有数据直接保存到局部变量,控制器或范围。我认为这将被视为浅表副本,对吗? 最近,有人告诉我使用angular.copy来创建深层副本。 但是,当我的Angular应用程序使用深层复制信息时,它们似乎以相同的方式工作。 使用深层副本(angular.copy)有什么特别的好处,请您向我解释一下吗? 问题答案: 将对象或数组的值分配给另一个变量时, 请使用angul