Go web基础1

       Go中进行web开发是十分快捷和方便的,因为封装的比较好,并且,由于Go语言天生的并发性,这使得我们开发一个并发性很好的服务端很容易。我也是刚开始学习Go语言,这篇文章就是一个学习笔记,水平很菜,错误之处,还请各位看官指出!

1.最简单的版本:

package main

import (
	"net/http"
)

func main() {
	http.HandleFunc("/", sayHello)
	http.ListenAndServe(":8080", nil)
}
func sayHello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello world"))
}

这个是基本的,有一个小的疑问,就是sayHello函数中的参数,第二个是指针,而第一个不是。查看官网,我们发现,type ResponseWriter interface和type Request struct的区别,结构体当然要用指针,这样的省去复制带来的开销。而接口为什么这样不用指针类型:我的理解是:”如果用指针类型,而实现这个接口的是一个结构的指针的话,这样就是指针的指针,而一般实现接口的都是结构的指针“,当然这个理解可能是错误的。这个程序中首先是用handleFunc()进行路由设置,然后就是监听端口。func HandleFunc(pattern string, handler func(ResponseWriter, *Request))和func ListenAndServe(addr string, handler Handler) error这是二个函数的API,type Handler interface { ServeHTTP(ResponseWriter, *Request) },而listenAndServe这个函数的第二个参数便是一个接口。现在,我们来看看HandleFunc()函数的源码:

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

原来这个函数是调用了ServerMux的HandleFunc方法的,

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    if handler == nil {
        panic("http: nil handler")
    }
    mux.Handle(pattern, HandlerFunc(handler))
}

HandlerFunc(handler)只是将handler转化成了HandlerFunc类型的了。type HandlerFunc func(ResponseWriter, *Request)这是定义。那么,我们稍微深入一下,试着用Handle函数来做一下。

2.稍微深入:

我们注意到,注册路由的函数还有一个就是func Handle(pattern string, handler Handler),第二个参数是一个接口,这个接口实现ServeHTTP(ResponseWriter, *Request)函数的接口,我们就用这个函数来做一个。

package main

import (
	"net/http"
)

type myHandle struct {
}

func main() {
	http.Handle("/", &myHandle{})
	http.ListenAndServe(":8080", nil)
}
func (*myHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello world2"))
}

通过API,我们也注意到,ListenAndServe()函数的第二个参数也是handle接口,那么这个handle是不是也是自定义的实现接口那?不是,通过API的一段”The handler is typically nil, in which case the DefaultServeMux is used.“原来,这儿实现handle接口的结构体已经有规范了,是ServerMux,这个ServerMux是一个什么类型,:

type ServeMux struct { // contains filtered or unexported fields }

是一个结构体,着结构体的意义:”ServeMux是一个HTTP请求多路复用器。它将每个传入请求的URL与已注册模式的列表进行匹配,并调用与URL最匹配的模式的处理程序”。这是API上的简介。那么我们可以通过ServerMux来进行路由注册等操作。可以选择func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))方法进行路由注册。

package main

import (
	"net/http"
)

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", sayHello)
	http.ListenAndServe(":8080", mux)
}
func sayHello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello world3"))
}

上面,已经用Handle函数实现了。再看看Handle函数的源码:

func (mux *ServeMux) Handle(pattern string, handler Handler) {
    mux.mu.Lock()
    defer mux.mu.Unlock()

    if pattern == "" {
        panic("http: invalid pattern")
    }
    if handler == nil {
        panic("http: nil handler")
    }
    if _, exist := mux.m[pattern]; exist {
        panic("http: multiple registrations for " + pattern)
    }

    if mux.m == nil {
        mux.m = make(map[string]muxEntry)
    }
    mux.m[pattern] = muxEntry{h: handler, pattern: pattern}

    if pattern[0] != '/' {
        mux.hosts = true
    }
}

我们发现它是利用ServeMux结构来操作的,

type ServeMux struct {
        mu    sync.RWMutex
        m     map[string]muxEntry
        hosts bool // whether any patterns contain hostnames
    }

type muxEntry struct {
        explicit bool
        h        Handler
        pattern  string
    }

其实,我们也可以通过自己定义一个map实现这种匹配:

3.稍微再深入:

现在进行自定义server,server的API上的定义:

type Server struct {
    Addr    string  // TCP address to listen on, ":http" if empty
    Handler Handler // handler to invoke, http.DefaultServeMux if nil
    TLSConfig *tls.Config
    ReadTimeout time.Duration
    ReadHeaderTimeout time.Duration  
    WriteTimeout time.Duration  
    IdleTimeout time.Duration 
    MaxHeaderBytes int
    TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
    ConnState func(net.Conn, ConnState)
    ErrorLog *log.Logger
   
}

这种形式的代码如下:

package main

import (
	"net/http"
	"time"
)

var mux map[string]func(http.ResponseWriter, *http.Request)

func main() {
	server := http.Server{
		Addr:        ":8080",
		Handler:     &myHandle{},
		ReadTimeout: 10 * time.Second,
	}
	mux = make(map[string]func(http.ResponseWriter, *http.Request))
	mux["/hello"] = sayHello
	server.ListenAndServe()
}

type myHandle struct{}

func (*myHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if h, ok := mux[r.URL.String()]; ok {
		h(w, r)
		return
	}
	w.Write([]byte("others"))
}

func sayHello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello world 4"))
}

代码比较简单,也没什么可以解释的。

以上的三种形式的web简单代码,如有错误,还请指正!声明:以上代码,没有进行错误处理,只是简单演示。分享一个关于Go语言方便的API查询网站:https://gowalker.org/net/http#Server

参考链接:1.关于interface的讲解:https://mp.weixin.qq.com/s?__biz=MzA4NzAzMjk4Mw==&mid=2247483733&idx=1&sn=9ef6e26c334599c0074a3fbe262d3a1b&chksm=903ed4ada7495dbbc3b4ec6feccf419cb2df9389b3227a45c6f1c8c350d033ba7960339b89da&mpshare=1&scene=1&srcid=0723EcpTK2GWJAONVQ1GTwJj&key=dc7dfb672b5ac5a823e8c1c3404c26554179516a85f2dee9e2935c8aa6055f0bc3847dd9510f02aa1d1802bbe8b76f16776318eda060969e8fa2e439756b7bceed9fd13c4042251dc9e406fed3c13951&ascene=0&uin=OTUyMjY5NDgw&devicetype=iMac%20MacBookPro11,5%20OSX%20OSX%2010.11.6%20build(15G1004)&version=12

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值