current position:Home>Go basic syntax 3 (socket, httpserver)

Go basic syntax 3 (socket, httpserver)

2022-04-29 08:18:01hualaoshuan

10. Socket Server and client ;

10.1 It's easy to create Socket Server and client code ;

A network model :
 Insert picture description here
Socket

  • Socket It's right TCP/UDP The package provides Layer 1 interface
  • utilize Socket Sure Write server and client , So as to realize the interconnection between the two
  • Different languages have similar socket Interface support
     Insert picture description here
  • Server side : file /Users/go/src/com.net/myserver/main.go
package main

import (
	"fmt"
	"io"
	"net"
)

func main() {
    
	//  establish  socket
	lis,err := net.Listen("tcp", "127.0.0.1:8099")
	if err != nil {
    
		fmt.Println(err)
		return
	}
	defer lis.Close()
	fmt.Println(" Listening created successfully , Wait for the client to connect ")

	//  Block waiting for client connection 
	client,err := lis.Accept()
	if err != nil {
    
		fmt.Println(err)
		return
	}
	defer client.Close()

	for {
    
		buf := make([]byte, 512)	//  If it is  8, Then the truncated output is : Read 8, The content is :i am pro Read 7, The content is :grammer
		n, err := client.Read(buf)
		if err != nil{
    
			if err == io.EOF{
    
				break
			}
			fmt.Println(err)
			return
		}
		fmt.Printf(" Read %d, The content is :%s",n,string(buf))
		//  Listening created successfully , Wait for the client to connect 
		//  Read 15, The content is :i am programmer
	}
}
  • client : file /Users/go/src/com.net/myclient/main.go
package main

import (
	"fmt"
	"net"
)

func main() {
    
	conn,err := net.Dial("tcp","127.0.0.1:8099")
	if err != nil{
    
		fmt.Println(err)
		return
	}
	defer conn.Close()

	conn.Write([]byte("i am programmer"))
}

Run configuration
 Insert picture description here

10.2 " Dead cycle "Socket Server side 、 Support browser output ;

  • The transformation of the service end is an endless cycle : file /Users/go/src/com.net/myserver/main.go
package main

import (
	"fmt"
	"io"
	"net"
)

func main() {
    
	//  establish  socket
	lis,err := net.Listen("tcp", "127.0.0.1:8099")
	if err != nil {
    
		fmt.Println(err)
		return
	}
	defer lis.Close()
	fmt.Println(" Listening created successfully , Wait for the client to connect ")

	//  Server end dead cycle , It won't end 
	for {
    
		//  Block waiting for client connection 
		client,err := lis.Accept()
		if err != nil {
    
			fmt.Println(err)
			return
		}
		//  Single process processing 、 Put anonymous functions 
		func (c net.Conn) {
    
			defer c.Close()

			buf := make([]byte, 4096)
			n, err := c.Read(buf)
			if err != nil{
    
				fmt.Println(err)
				return
			}
			fmt.Printf(string(buf[0:n]))	//  The slice shows , perhaps  buf[:n]
		}(client)	//  Pass in  client

	}

}

Browser output
 Insert picture description here

  • Server side : file /Users/go/src/com.net/myserver/main.go
package main

import (
	"fmt"
	"net"
)

//  Write a dead string 
func response() string {
    
	str:=`HTTP/1.1 200 OK Server: myserver Content-Type: text/html this is body `
	return str
}

func main() {
    
	//  establish  socket
	lis,err := net.Listen("tcp", "127.0.0.1:8099")
	if err != nil {
    
		fmt.Println(err)
		return
	}
	defer lis.Close()
	fmt.Println(" Listening created successfully , Wait for the client to connect ")

	//  Server end dead cycle , It won't end 
	for {
    
		//  Block waiting for client connection 
		client,err := lis.Accept()
		if err != nil {
    
			fmt.Println(err)
			return
		}
		//  Single process processing 、 Put anonymous functions 
		func (c net.Conn) {
    
			defer c.Close()

			buf := make([]byte, 4096)
			n, err := c.Read(buf)
			if err != nil{
    
				fmt.Println(err)
				return
			}
			fmt.Printf(string(buf[0:n]))	//  The slice shows , perhaps  buf[:n]
			c.Write([]byte(response()))

		}(client)	//  Pass in  client

	}
}
  • client : file /Users/go/src/com.net/myclient/main.go
package main

import (
	"fmt"
	"net"
)

func main() {
    
	conn,err := net.Dial("tcp","127.0.0.1:8099")
	if err != nil{
    
		fmt.Println(err)
		return
	}
	defer conn.Close()

	conn.Write([]byte("i am programmer!"))

	buf := make([]byte, 4096)
	n, err := conn.Read(buf)
	if err != nil{
    
		fmt.Println(err)
		return
	}
	fmt.Printf(string(buf[0:n]))
}

10.3 Introduction to regularization 、 Analysis request path、Socket The server starts the process support ;

Regular :

//  Package :regexp
r,err := regexp.Compile(expr string) (*Regexp, error) //  Compile a regular expression into a regular object 
r :=regexp.MustCompile(str string) *Regexp //  ditto , If you make a mistake , Will put the exception panic come out 
r.MatchString(s string) bool  //  Judge whether it can match ( Generally used for judgment , Judge if there is no , Don't do the following steps )
r.FindStringSubmatch
r.FindAllStringSubmatch
//  The former finds the first matching result and grouping content , The latter supports multiple matching results ,n Parameters ( How many times , Negative numbers are unlimited )
  • file /Users/go/src/com.net/mytest/main.go
package main

import (
	"fmt"
	"regexp"
)

func GetRqPath(rq string) string {
    
	r := regexp.MustCompile(`^GET\s(.*?)\sHTTP`)	//  A space \
	if r.MatchString(rq) {
    
		return r.FindStringSubmatch(rq)[1]	//  Take the first match 
	} else {
    
		return "/"
	}
}

func main() {
    
	str:=`GET /abc.php HTTP/1.1 Host: localhost:8099 Connection: keep-alive Upgrade-Insecure-Requests: 1`

	fmt.Println(GetRqPath(str))
}

Analysis request path

  • file /Users/go/src/com.net/myserver/netutil.go
package main

import "regexp"

func GetRqPath(rq string) string {
    
	r := regexp.MustCompile(`^GET\s(.*?)\sHTTP`)	//  A space \
	if r.MatchString(rq) {
    
		return r.FindStringSubmatch(rq)[1]	//  Take the first match 
	} else {
    
		return "/"
	}

}
  • Server side : file /Users/go/src/com.net/myserver/main.go
package main

import (
	"fmt"
	"net"
	"runtime"
	"time"
)

//  Write a dead string 
func response() string {
    
	str:=`HTTP/1.1 200 OK Server: myserver Content-Type: text/html this is body `
	return str
}

func main() {
    
	//  establish  socket
	lis,err := net.Listen("tcp", "127.0.0.1:8099")
	if err != nil {
    
		fmt.Println(err)
		return
	}
	defer lis.Close()
	fmt.Println(" Listening created successfully , Wait for the client to connect ")
	// * Get the current number of processes 
	go func() {
    
		for{
    
			fmt.Printf(" Current number of tasks :%d\n",runtime.NumGoroutine())
			time.Sleep(time.Second*2)

		}
	}()

	//  Server end dead cycle , It won't end 
	for {
    
		//  Block waiting for client connection 
		client,err := lis.Accept()
		if err != nil {
    
			fmt.Println(err)
			return
		}
		// * Use CO processing 
		go func (c net.Conn) {
    
			defer c.Close()

			buf := make([]byte, 4096)
			n, err := c.Read(buf)
			if err != nil{
    
				fmt.Println(err)
				return
			}
			// * Sleep  5  second 
			if GetRqPath(string(buf[0:n])) == "/delay" {
    
				time.Sleep(time.Second*5)
			}
			// fmt.Printf(string(buf[0:n])) //  The slice shows , perhaps  buf[:n]
			c.Write([]byte(response()))

		}(client)	//  Pass in  client

	}
}

10.4 Realize the access of browser static files 、 Handle 404;

 Insert picture description here

  • file /Users/go/src/com.net/myserver/netutil.go
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
)

func GetRequestPath(rq string) string {
    
	r := regexp.MustCompile(`^GET\s(.*?)\sHTTP`)	//  A space \
	if r.MatchString(rq) {
    
		return r.FindStringSubmatch(rq)[1]	//  Take the first match 
	} else {
    
		return "/"
	}

}


func response(body []byte, status HttpStatus) string {
    
	str:=`HTTP/1.1 %d %s Server: myserver Content-Type: text/html %s `
	ret:= fmt.Sprintf(str, status.Code, status.Message, body)
	return ret
}

//  Judge whether the file exists 
func ExistsFile(path string) (bool,error)  {
    
	_,err:=os.Stat("./web"+path)
	if err == nil {
    
		return true,nil
	}else{
    
		if os.IsNotExist(err) {
     // non-existent 
			return false,nil
		} else {
    
			return false,err
		}
	}
}

func ReadHtml(path string) string  {
    
	exist, _ := ExistsFile(path)
	if exist {
    

		file, _ := ioutil.ReadFile("./web"+path)
		return response(file, NewHttpStatus(200,"OK"))
	}else{
    
		return response([]byte("404"),NewHttpStatus(404,"Not Found"))
	}
}
  • file /Users/go/src/com.net/myserver/status.go
package main

type HttpStatus struct {
    
	Code int
	Message string
}

func NewHttpStatus(code int ,message string) HttpStatus  {
    
	hs:=HttpStatus{
    code,message}
	return hs
}
  • file /Users/go/src/com.net/web/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 This is the home page 
</body>
</html>
  • file /Users/go/src/com.net/myserver/main.go
package main

import (
	"fmt"
	"net"
	"runtime"
	"time"
)

func main() {
    
	//  establish  socket
	lis,err := net.Listen("tcp", "127.0.0.1:8099")
	if err != nil {
    
		fmt.Println(err)
		return
	}
	defer lis.Close()
	fmt.Println(" Listening created successfully , Wait for the client to connect ")
	//  Get the current number of processes 
	go func() {
    
		for{
    
			fmt.Printf(" Current number of tasks :%d\n",runtime.NumGoroutine())
			time.Sleep(time.Second*2)

		}
	}()

	//  Server end dead cycle , It won't end 
	for {
    
		//  Block waiting for client connection 
		client,err := lis.Accept()
		if err != nil {
    
			fmt.Println(err)
			return
		}
		//  Use CO processing 
		go func (c net.Conn) {
    
			defer c.Close()

			buf := make([]byte, 4096)
			n, err := c.Read(buf)
			if err != nil{
    
				fmt.Println(err)
				return
			}
			//  Sleep  5  second 
			//if GetRequestPath(string(buf[0:n])) == "/delay" {
    
			// time.Sleep(time.Second*5)
			//}
			// fmt.Printf(GetRequestPath(string(buf[0:n]))) //  The slice shows , perhaps  buf[:n]
			// c.Write([]byte(response()))

			c.Write([]byte(ReadHtml(GetRequestPath(string(buf[:n])))))

		}(client)	//  Pass in  client
	}

}

11. httpserver;

11.1 Use http Quick package creation server、 Customize handler;

  • file /Users/go/src/com.net/myhttpserver/main.go
package main

import (
	"fmt"
	"net/http"
)

func main() {
    
	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    
		writer.Write([]byte("hello"))
	})

	http.HandleFunc("/abc", func(writer http.ResponseWriter, request *http.Request) {
    
		writer.Write([]byte("abc"))
	})
	//err := http.ListenAndServe(":8099", nil) //  The second parameter  nil, The route is automatically generated 
	//if err != nil {
    
	// fmt.Println(err)
	//}

	//  ditto 
	server := http.Server{
    Addr: ":8099", Handler: nil}
	err := server.ListenAndServe()
	if err != nil {
    
		fmt.Println(err)
	}
}

Optimize :

package main

import (
	"fmt"
	"net/http"
)

type MyHandler struct {
    

}

func(*MyHandler) ServeHTTP (writer http.ResponseWriter, request *http.Request){
    
	writer.Write([]byte("hello,myhandler"))
}



func main() {
    
	handler := new(MyHandler)
	server := http.Server{
    Addr: ":8099", Handler: handler}	// Handler  Interface 
	err := server.ListenAndServe()
	if err != nil {
    
		fmt.Println(err)
	}
}

11.2 route 、 Set up cookie、 Cancellation 、 Judgement login ;

 Insert picture description here

//  The code in the previous chapter :
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    
       writer.Write([]byte("hello"))	
 })
http.ListenAndServe(":8099",nil)

//  You can see  HandleFunc There's a  
var defaultServeMux ServeMux

//  If server Object does not provide handler, The default is enabled ServeMux, This is a routing manager 

mux:=http.NewServeMux()
mux.Handle("/",new(MyHandler))
 
server:=http.Server{
    Addr:":8099",Handler:mux}
err:=server.ListenAndServe()
if err!=nil{
    
	fmt.Println(err)
}
//  Hypothetical visit  /  everything OK. If you visit  /admin  You need to log in ( Judge  cookie  If there  usename  This one )
//  Write the login route first 
  mux.HandleFunc("/login", func(writer http.ResponseWriter, request *http.Request) {
    
	writer.Write([]byte(" Here is the login page "));
})
//  In order to login , Our rules   If the interview is 
/login?username=xxxoo
//  Then set  cookie: username=xxxoo( Write dead value )
//  obtain query Parameters 
request.URL.Query().Get("xxoo")  //  If not, return "" ( No nil)

//  Set up cookie
c:=&http.Cookie{
    Name:"username",Value:getusername,Path:"/"}
http.SetCookie(writer,c)
  • file /Users/go/src/com.net/myhttpserver/main.go
package main

import (
	"net/http"
	"time"
)

type MyHandler struct {
    

}

func(*MyHandler) ServeHTTP (writer http.ResponseWriter, request *http.Request){
    
	// request.URL.Path //  Available url
	writer.Write([]byte("hello,myhandler"))
}

func main() {
    
	//  route 
	mymux := http.NewServeMux()
	// mymux.Handle("/", &MyHandler{})

	//  Simulation requirements : Hypothetical visit /  everything OK. If you visit /admin You need to log in ( Judge  cookie  If there  usename  This one )
	mymux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    
		//  You can define the route here 
		writer.Write([]byte("index"))
	})

	//  Sign in 
	mymux.HandleFunc("/login", func(writer http.ResponseWriter, request *http.Request){
    
		getUserName := request.URL.Query().Get("username")
		if getUserName != "" {
    
			c := &http.Cookie{
    Name:"username", Value:getUserName, Path:"/"}
			http.SetCookie(writer,c)	//  Set up  cookie
		}
		writer.Write([]byte(" Here is the login page "))
	})

	//  sign out 
	mymux.HandleFunc("/unlogin", func(writer http.ResponseWriter, request *http.Request) {
    
		c := &http.Cookie{
    Name:"username", Value:"", Path:"/", Expires:time.Now().AddDate(-1,0,0)}
		http.SetCookie(writer,c)
		//  Join in  http  Protocol header 
		writer.Header().Set("Content-type","text/html")
		writer.Write([]byte("unlogin...."));
		script:=`<script> setTimeout(()=>{self.location='/'},2000) </script>`
		writer.Write([]byte(script))
	})

	http.ListenAndServe(":8099", mymux)
}

another : Plug-in thinking

//  Nest a function , like python Decorator mode in 
func LoginHandler(hander http.Handler) http.Handler{
    
	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
    
		 /// Here's the business logic 
	})
}

//  obtain cookie
cookie,err:=request.Cookie("username")
if err!=nil || cookie==nil{
    
	 xxxooo
}

// Redirect
http.Redirect(writer,request,"/login",302)

//
func LoginHandler(hander http.Handler) http.Handler{
    
	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
    
		cookie,err:=request.Cookie("username")
		if err!=nil || cookie==nil{
    
			http.Redirect(writer,request,"/login",302)
		}else{
    
			hander.ServeHTTP(writer,request)
		}
	})
}

11.3 Custom routing 、 Support GET / POST visit ;

  • file /Users/go/src/com.net/myhttpserver/core/MyRouter.go
package core

import (
	"net/http"
)

type MyRouter struct {
    
	Mapping map[string]map[string]http.HandlerFunc
}

func DefaultRouter() *MyRouter {
    
	return &MyRouter{
    make(map[string]map[string]http.HandlerFunc)}
}

func(this *MyRouter) Get(path string, f http.HandlerFunc)  {
    
	if this.Mapping["GET"] == nil{
    
		this.Mapping["GET"] = make(map[string]http.HandlerFunc)
	}
	this.Mapping["GET"][path] = f
}

func(this *MyRouter) Post(path string, f http.HandlerFunc)  {
    
	if this.Mapping["POST"] == nil{
    
		this.Mapping["POST"] = make(map[string]http.HandlerFunc)
	}
	this.Mapping["POST"][path] = f
}

func(this *MyRouter) ServeHTTP(writer http.ResponseWriter, request *http.Request){
    
	f := this.Mapping[request.Method][request.URL.Path]
	f(writer,request)
}
  • file /Users/go/src/com.net/myhttpserver/main.go
package main

import (
	"com.net/myhttpserver/core"
	"net/http"
)

type MyHandler struct {
    

}

func(*MyHandler) ServeHTTP (writer http.ResponseWriter, request *http.Request){
    
	// request.URL.Path //  Available url
	writer.Write([]byte("hello,myhandler"))
}

func main() {
    
	router := core.DefaultRouter()

	router.Get("/", func(writer http.ResponseWriter, request *http.Request) {
    
		writer.Write([]byte("get abc"))
	})

	router.Post("/", func(writer http.ResponseWriter, request *http.Request) {
    
		writer.Write([]byte("post abc"))
	})

	http.ListenAndServe(":8099",router)
}

11.4 Create your own simple " Context " object ;

  • file /Users/go/src/com.net/myhttpserver/core/MyRouter.go
package core

import (
	"net/http"
)

type MyHandlerFunc func(ctx *MyContext)

type MyRouter struct {
    
	Mapping map[string]map[string]MyHandlerFunc
	Ctx *MyContext
}

func DefaultRouter() *MyRouter {
    	//  initialization 
	return &MyRouter{
    make(map[string]map[string]MyHandlerFunc),&MyContext{
    }}
}

func(this *MyRouter) Get(path string, f MyHandlerFunc)  {
    
	if this.Mapping["GET"] == nil{
    
		this.Mapping["GET"] = make(map[string]MyHandlerFunc)
	}
	this.Mapping["GET"][path] = f
}
func(this *MyRouter) Post(path string, f MyHandlerFunc)  {
    
	if this.Mapping["POST"] == nil{
    
		this.Mapping["POST"] = make(map[string]MyHandlerFunc)
	}
	this.Mapping["POST"][path] = f
}


func(this *MyRouter) ServeHTTP(writer http.ResponseWriter, request *http.Request){
    
	this.Ctx.request=request
	this.Ctx.ResponseWriter=writer

	// chrome  The default request icon address 
	if f,OK:=this.Mapping[request.Method][request.URL.Path];OK{
    
		f(this.Ctx)
	}
}
  • file /Users/go/src/com.net/myhttpserver/core/MyContext.go
package core

import "net/http"

type MyContext struct {
    		// Context object 
	request *http.Request
	http.ResponseWriter
}

func(this *MyContext) WriteString(str string){
    
	this.Write([]byte(str))
}
  • file /Users/go/src/com.net/myhttpserver/main.go
package main

import (
	"com.net/myhttpserver/core"
	"net/http"
)

type MyHandler struct {
    

}

func(*MyHandler) ServeHTTP (writer http.ResponseWriter, request *http.Request){
    
	// request.URL.Path //  Available url
	writer.Write([]byte("hello,myhandler"))
}

func main() {
    
	router:=core.DefaultRouter()

	router.Get("/", func(ctx *core.MyContext) {
    
		ctx.WriteString("my string GET")
	})
	router.Post("/", func(ctx *core.MyContext) {
    
		ctx.WriteString("my string POST")
	})

	http.ListenAndServe(":8099",router)
}

11.5 " frame " Support controller prototype ;

The basic structure :
 Insert picture description here

  • file /Users/go/src/com.net/myhttpserver/core/MyRouter.go
package core

import (
	"net/http"
)
type MyHandlerFunc func(ctx *MyContext)
type MyRouter struct {
    
	Mapping map[string]ControllerInterface

}

func DefaultRouter() *MyRouter {
    
	return &MyRouter{
    make(map[string]ControllerInterface)}
}

// Join in  path  and  Controller  Correspondence of 
func(this *MyRouter) Add(path string, c ControllerInterface)  {
    
	this.Mapping[path] = c
}

func(this *MyRouter) ServeHTTP(writer http.ResponseWriter, request *http.Request){
    
	// chrome  The default request icon address 
	if f,OK := this.Mapping[request.URL.Path];OK{
    
		f.Init(&MyContext{
    request,writer}) // Key code 
		if request.Method == "GET" {
    		// No error proofing 
			f.GET()
		}
		if request.Method == "POST" {
    	// No error proofing 
			f.POST()
		}
	}
}
  • file /Users/go/src/com.net/myhttpserver/core/MyContext.go
package core

import "net/http"

type MyContext struct {
    		// Context object 
	request *http.Request
	http.ResponseWriter
}

func(this *MyContext) WriteString(str string){
    
	this.Write([]byte(str))
}
  • file /Users/go/src/com.net/myhttpserver/core/MyController.go
package core

type MyController struct {
    
	Ctx *MyContext	//  Context object 
}

//  initialization 
func(this *MyController) Init (ctx *MyContext)  {
    
	this.Ctx=ctx
}

type ControllerInterface interface {
    
	Init(ctx *MyContext)
	GET()
	POST()
}

  • file /Users/go/src/com.net/myhttpserver/NewsController.go
package main

import "com.net/myhttpserver/core"

type NewsController struct {
    
	core.MyController
}

func(this *NewsController) GET()  {
    
	this.Ctx.WriteString("this is newscontroller")
}

func(this *NewsController) POST()  {
    
	this.Ctx.WriteString("this is newscontroller for POST")
}
  • file /Users/go/src/com.net/myhttpserver/main.go
package main

import (
	"com.net/myhttpserver/core"
	"net/http"
)

type MyHandler struct {
    

}

func(*MyHandler) ServeHTTP (writer http.ResponseWriter, request *http.Request){
    
	// request.URL.Path //  Available url
	writer.Write([]byte("hello,myhandler"))
}

func main() {
    
	router:=core.DefaultRouter()
	router.Add("/",&NewsController{
    })
	http.ListenAndServe(":8099",router)
}

11.6 Support GET / POST Parameters 、JSON Output and Model mapping ;

 Insert picture description here
Realization WriteJSON function

//  Before using third-party packages ffjson
// https://github.com/pquerna/ffjson
func(this *MyContext) WriteJSON(m interface{
    }){
    
	this.Header().Add("Content-type","application/json")
	result,err:=ffjson.Marshal(m)
	if err!=nil{
    
		panic(err)
	}
	this.Write(result)
}

Processing parameters

//  obtain GET Parameters 
//  Written in MyController in , This is not a context 
func(this *MyController) GetParam(paramName string,defValue  ...string) string {
    
	p:=this.Ctx.request.URL.Query().Get(paramName)
	if p=="" && len(defValue)>0{
    
		return defValue[0]
	}
	return p
}

//  obtain POST Parameters ( Simple version )
//  This code is written in MyController in , This is not a context 
func(this *MyController) PostParam(paramName string,defValue  ...string) string {
    
	p:=this.Ctx.request.PostFormValue(paramName)
	if p=="" && len(defValue)>0{
    
		return defValue[0]
	}
	return p
}

//  obtain JSON Parameters 
//  stay Java in , A common practice is to get JSON Content mapping to model (Model) in ,golang  In, we can also simulate and implement 
func(this *MyController) JSONParam(obj interface{
    })  {
    
	c,err:=ioutil.ReadAll(this.Ctx.request.Body)
	if err!=nil{
    
		panic(err)
	}
	err=ffjson.Unmarshal(c,obj)
	if err!=nil{
    
		panic(err)
	}
}
  • file /Users/go/src/com.net/myhttpserver/core/MyContext.go
package core

import (
	"github.com/pquerna/ffjson/ffjson"
	"net/http"
)

type MyContext struct {
    		// Context object 
	request *http.Request
	http.ResponseWriter
}

func(this *MyContext) WriteString(str string){
    
	this.Write([]byte(str))
}

// writeJson
func(this *MyContext) WriteJSON(m interface{
    }){
    
	this.Header().Add("Content-type","application/json")
	ret,err := ffjson.Marshal(m)
	if err!=nil{
    
		panic(err)
	}
	this.Write(ret)
}
  • file /Users/go/src/com.net/myhttpserver/core/MyRouter.go
package core

import (
	"net/http"
)
type MyHandlerFunc func(ctx *MyContext)
type MyRouter struct {
    
	Mapping map[string]ControllerInterface

}

func DefaultRouter() *MyRouter {
    
	return &MyRouter{
    make(map[string]ControllerInterface)}
}

// Join in  path  and  Controller  Correspondence of 
func(this *MyRouter) Add(path string, c ControllerInterface)  {
    
	this.Mapping[path] = c
}

func(this *MyRouter) ServeHTTP(writer http.ResponseWriter, request *http.Request){
    
	// chrome  The default request icon address 
	if f,OK := this.Mapping[request.URL.Path];OK{
    
		f.Init(&MyContext{
    request,writer}) // Key code 
		if request.Method == "GET" {
    		// No error proofing 
			f.GET()
		}
		if request.Method == "POST" {
    	// No error proofing 
			f.POST()
		}
	}

}
  • file /Users/go/src/com.net/myhttpserver/core/MyUtil.go
package core

//  Customize  map  Interface 
type Map map[string]interface{
    }
  • file /Users/go/src/com.net/myhttpserver/core/MyController.go
package core

import (
	"github.com/pquerna/ffjson/ffjson"
	"io/ioutil"
)

type MyController struct {
    
	Ctx *MyContext	//  Context object 
}

//  initialization 
func(this *MyController) Init (ctx *MyContext)  {
    
	this.Ctx=ctx
}

type ControllerInterface interface {
    
	Init(ctx *MyContext)
	GET()
	POST()
}

//  obtain GET Parameter method 
// "..."  Uncertain parameters 
func(this *MyController) GetParam(key string, defValue ...string) string  {
    
	ret := this.Ctx.request.URL.Query().Get(key)
	if ret == "" && len(defValue) > 0{
    
		return defValue[0]
	}
	return ret
}

//  obtain POST Parameters , Single parameter 
func(this *MyController) PostParam(key string, defValue ...string) string  {
    
	ret := this.Ctx.request.PostFormValue(key)
	if ret == "" && len(defValue) > 0{
    
		return defValue[0]
	}
	return ret
}

//  obtain JSON Parameters , Single parameter 
func(this *MyController) JSONParam(obj interface{
    })  {
    
	body,err := ioutil.ReadAll(this.Ctx.request.Body)
	if err!=nil{
    
		panic(err)
	}
	err = ffjson.Unmarshal(body,obj)
	if err != nil{
    
		panic(err)
	}
}

  • file /Users/go/src/com.net/myhttpserver/NewsController.go
package main

import "com.net/myhttpserver/core"

type NewsController struct {
    
	core.MyController
}

func(this *NewsController) GET()  {
    
	// this.Ctx.WriteString("this is newscontroller")
	// WriteJSON
	// this.Ctx.WriteJSON(map[string]string{"username" : "hua"}) //  Customize  map  object 
	// this.Ctx.WriteJSON(map[string]string{"username" : "hua"})
	// this.Ctx.WriteJSON(core.Map{"username" : "hua"})
	p:=this.GetParam("username", "no param", "abc")
	this.Ctx.WriteString(p)


}

func(this *NewsController) POST()  {
    
	// this.Ctx.WriteString("this is newscontroller for POST")

	//p:=this.PostParam("username", "no param for post", "abc")
	//this.Ctx.WriteString(p)

	user := UserModel{
    }
	this.JSONParam(&user)
	this.Ctx.WriteJSON(user)
}
  • file /Users/go/src/com.net/myhttpserver/UserModel.go
package main

type UserModel struct {
    
	UserName string
	UserAge int
}
  • file /Users/go/src/com.net/myhttpserver/main.go
package main

import (
	"com.net/myhttpserver/core"
	"net/http"
)

type MyHandler struct {
    

}

func(*MyHandler) ServeHTTP (writer http.ResponseWriter, request *http.Request){
    
	// request.URL.Path //  Available url
	writer.Write([]byte("hello,myhandler"))
}

func main() {
    
	router:=core.DefaultRouter()

	router.Add("/",&NewsController{
    })

	http.ListenAndServe(":8099",router)
}

copyright notice
author[hualaoshuan],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/119/202204290600598219.html

Random recommended