ResponseWriter为什么以及何时生成原始html?
我不明白为什么代码正确地生成view.html和post.html数据,但将其全部显示为原始文本。我一直在遵循指南,在构建它的过程中,我认为从Execute函数生成的html将被发送到负责显示它的ResponseWriter,但我得到的错误似乎表明我对Execute的理解或ResponseWriter是错误的ResponseWriter为什么以及何时生成原始html?,html,templates,go,Html,Templates,Go,我不明白为什么代码正确地生成view.html和post.html数据,但将其全部显示为原始文本。我一直在遵循指南,在构建它的过程中,我认为从Execute函数生成的html将被发送到负责显示它的ResponseWriter,但我得到的错误似乎表明我对Execute的理解或ResponseWriter是错误的 package main import ( "os" "fmt" "time" "bufio" "net/http" "html/temp
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)
}
主程序包
进口(
“操作系统”
“fmt”
“时间”
“布菲奥”
“net/http”
“html/模板”
)
类型UserPost结构{
名称字符串
关于字符串
后期字符串
}
功能检查(e错误){
如果e!=nil{
fmt.Println(“收到错误…”)
恐慌(e)
}
}
func lineCounter(工作文件*os.File)int{
fileScanner:=bufio.NewScanner(工作文件)
行数:=0
对于fileScanner.Scan(){
行号++
}
返回行计数
}
func加载页(i int)(*UserPost,错误){
Posts,err:=os.Open(“dataf.txt”)
检查(错误)
var PostArray[512]UserPost=parsePosts(Posts,i)
名称:=PostArray[i]。名称
About:=PostArray[i]。关于
PostTime:=PostArray[i]。PostTime
Posts.Close()
return&UserPost{Name:Name[:len(Name)-1],About:About[:len(About)-1],PostTime:PostTime[:len(PostTime)-1]},无
}
func viewHandler(w http.ResponseWriter,r*http.Request){
tmp,err:=os.Open(“dataf.txt”)
检查(错误)
num:=(行计数器(tmp)/3)
tmp.Close()
对于i:=0;i 对于提示的i:=0;i,这是因为您尚未设置内容类型。引用自:
如果您不自己设置内容类型,首先调用ResponseWriter.Write()
将调用以猜测要设置的内容。如果您发送的内容以“
”开头,则不会将其检测为HTML,但将设置“text/plain;charset=utf-8”
(指示)浏览器可以将内容显示为文本,而不尝试将其解释为HTML)
例如,如果内容以“
开头,则会自动设置内容类型”text/html;charset=utf-8“
,并且无需进一步操作
但是,如果您知道要发送什么,就不要依赖自动检测,而且自己设置要比在其上运行检测算法快得多,因此只需在写入/发送任何数据之前添加这一行:
w.Header().Set("Content-Type", "text/html; charset=utf-8")
并使您的post.html
模板成为完整、有效的html文档
还有一条建议:在代码中,您完全忽略了检查返回的错误。不要这样做。您至少可以在控制台上打印它们。如果不忽略错误,您将为自己节省大量时间。正如所暗示的,这是因为您没有设置内容类型。引用自:
如果您不自己设置内容类型,首先调用ResponseWriter.Write()
将调用以猜测要设置的内容。如果您发送的内容以“
”开头,则不会将其检测为HTML,但将设置“text/plain;charset=utf-8”
(指示)浏览器可以将内容显示为文本,而不尝试将其解释为HTML)
例如,如果内容以“
开头,则会自动设置内容类型”text/html;charset=utf-8“
,并且无需进一步操作
但是,如果您知道要发送什么,就不要依赖自动检测,而且自己设置要比在其上运行检测算法快得多,因此只需在写入/发送任何数据之前添加这一行:
w.Header().Set("Content-Type", "text/html; charset=utf-8")
并使您的post.html
模板成为完整、有效的html文档
还有一条建议:在代码中,您完全忽略了检查返回的错误。不要这样做。您至少可以在控制台上打印它们。如果不忽略错误,您将为自己节省大量时间。您没有在HTTP响应头中指定内容类型。请尝试添加内容类型头。就像@josh一样如前所述,您需要设置内容类型,而不是源访问控制。因此,如果您希望输出为html,您需要执行以下操作:w.Header()。设置(“内容类型”,“文本/html”)“访问控制允许源”不是“内容类型”,因此您的“无更改”这是意料之中的。joshlf要求提供内容类型,他是对的。进行检测的函数是DetectContentType(实现)。这是一个非常简单的函数-基本上它只是尝试与非常简单的基于文本的签名列表进行匹配,并查看是否有匹配。HTML签名(请参阅)不要包含
或
,因为这些是您的资源开头的标记,这是它需要匹配的,以便正确检测内容类型(因为它只关注前几个字节)。我敢打赌,如果您发送的文档以
开头,则
// 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)
w.Header().Set("Content-Type", "text/html; charset=utf-8")