遇到的问题

用mime/multipart上传file和value时出现了一个问题,用postman可以正常上传file和value,但是用net/http库上传时则出现了可以上传file会失败的情况,err为unexpected EOF,证明了问题出现在自己的client代码中

问题代码
to := "http://" + host.Text + ":" + port.Text + "/blog/" + title.Text
		// PostFile(full, flab.Text, to, kind.Text, kindCn.Text)
		// 设置参数
		bodyBuf := &bytes.Buffer{}
		writer := multipart.NewWriter(bodyBuf)
		// fn, _ := filename.Get()
		part, err := writer.CreateFormFile("file", flab.Text)
		if err != nil {
			// 弹窗
			return
		}
		// io.WriteString(part, string(full))
		io.WriteString(part, string(full))

		writer.WriteField("topicCn", kindCn.Text)
		writer.WriteField("topicEn", kind.Text)
		// fmt.Fprint(part, full)
		// fmt.Println(string(full))
		// defer writer.Close()

		contentType := writer.FormDataContentType()
		defer writer.Close()
		resp, err := http.Post(to, contentType, bodyBuf)
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		 defer resp.Body.Close()

		switch resp.StatusCode {
		case 200:
			fmt.Println("ok")
		case 400:
			vts, _ := io.ReadAll(resp.Body)
			fmt.Println(string(vts))

		}
		fmt.Println(resp.StatusCode)
问题分析

根据错误类型,可以推测问题出在了wirter或者part中,经过测试,找到了问题出在了writer里
我们写go代码一般有一个人习惯就是用 defer 关闭打开了的io.reader但是*multipart.Writer不可以呀用defer,因为要在发送请求前调用CLOSE,否则上传的数据会缺少EOF,导致后端读取出错。

正确代码
to := "http://" + host.Text + ":" + port.Text + "/blog/" + title.Text
		// PostFile(full, flab.Text, to, kind.Text, kindCn.Text)
		// 设置参数
		bodyBuf := &bytes.Buffer{}
		writer := multipart.NewWriter(bodyBuf)
		// fn, _ := filename.Get()
		part, err := writer.CreateFormFile("file", flab.Text)
		if err != nil {
			// 弹窗
			return
		}
		// io.WriteString(part, string(full))
		io.WriteString(part, string(full))

		writer.WriteField("topicCn", kindCn.Text)
		writer.WriteField("topicEn", kind.Text)
		// fmt.Fprint(part, full)
		// fmt.Println(string(full))
		// defer writer.Close()

		contentType := writer.FormDataContentType()
		writer.Close()
		resp, err := http.Post(to, contentType, bodyBuf)
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		 defer resp.Body.Close()

		switch resp.StatusCode {
		case 200:
			fmt.Println("ok")
		case 400:
			vts, _ := io.ReadAll(resp.Body)
			fmt.Println(string(vts))

		}
		fmt.Println(resp.StatusCode)
总结

使用io.reader 时用defer关键词来关闭
使用io.writer时要视情况而使用defer