Http: multiple response.WriteHeader calls

package main

import (

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", wrapController("Home", &TODO{}))
	http.ListenAndServe(":3000", r)

type TODO struct {

func (t *TODO) Home() {
	t.Response.Write([]byte("todo home"))

// Helper
func handleController(w http.ResponseWriter, req *http.Request, fn string, ctrl Controller) {
	ctrl.New(w, req)
	in := make([]reflect.Value, 0)
func wrapController(fn string, ctrl Controller) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		handleController(w, req, fn, ctrl)

// Controller
type Controller interface {
	New(http.ResponseWriter, *http.Request)

type BaseController struct {
	Request  *http.Request
	Response http.ResponseWriter

func (b *BaseController) New(w http.ResponseWriter, r *http.Request) {
	b.Request = r
	b.Response = w

When run wrk -t12 -c900 -d10s http://localhost:3000, got errors http: multiple response.WriteHeader calls, i can’t find how to fix it,thanks.

I suspect it’s because you’re using the same Controller for all requests. When you do &TODO{} in your main(), that only creates one Controller and all requests share the same one.

By the way, this is very unusual Go code. Can I ask why you’re doing this?

I want to write a mini framework to learn go. I referenced some code from

Run your program with the -race flag and see if it finds any race conditions first. I’m suspicious of that Controller.

Thanks, i tried, but nothing happend,

Solved. Use sync.RWMutex can fix this.Thanks.

Remember to mark your reply as the answer (click the chrck mark) so others who find this thread can find the answer quickly :wink:

OK, thank you.

This is a very odd design (as @mholt points out) - in fact, it’s pretty dangerous as you have one controller instance and will leak data across requests (as you are finding out).

Sharing the same controller across requests is not how to write a Go HTTP server.

Take a look at these articles and move away from the “Controller” pattern —which doesn’t port well to Go, as you’re finding:


@elithrar Thanks, because i learned golfing from beego, so my code referenced from and

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.