设为首页 加入收藏

TOP

Go web开发初探(一)
2017-09-30 13:38:29 】 浏览:8632
Tags:web 开发 初探

2017年的第一篇博客,也是第一次写博客,写的不好,请各位见谅。

本人之前一直学习javajava web,最近开始学习Go语言,所以也想了解一下Go语言中web的开发方式以及运行机制。

在《Go web编程》一书第三节中简要的提到了Go语言中http的运行方式,我这里是在这个的基础上更加详细的梳理一下。

这里先提一句,本文中展示的源代码都是在Go安装目录下src/net/http/server.go文件中(除了自己写的实例程序),如果各位还想理解的更详细,可以自己再去研究一下源代码。

《Go web编程》3.4节中提到http有两个核心功能:Conn, ServeMux , 但是我觉得还有一个Handler接口也挺重要的,后边咱们提到了再说。

先从一个简单的实例来看一下Go web开发的简单流程:

package main

import (
	"fmt"
	"log"
	"net/http"
)

func sayHello(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Hello World!")

}
func main() {
	http.HandleFunc("/hello", sayHello)  //注册URI路径与相应的处理函数
	er := http.ListenAndServe(":9090", nil)  // 监听9090端口,就跟javaweb中tomcat用的8080差不多一个意思吧
	if er != nil {
		log.Fatal("ListenAndServe: ", er)
	}
}

  在浏览器运行localhost:9090/hello   就会在命令行或者所用编辑器的输出窗口 “Hello World!” (这里为了简便,就没往网页里写入信息)

根据这个简单的例子,一步一步的分析它是如何运行。

首先是注册URI与相应的处理函数,这个就跟SpringMVC中的Controller差不多。

 

http.HandleFunc("/hello", sayHello)

  来看一下他的源码:

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

  里边实际是调用了DefaultServeMux的HandlerFunc方法,那么这个DefaultServeMux是啥,HandleFunc又干了啥呢?

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
}


func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} }


var DefaultServeMux = NewServeMux() 

  事实上这个DefaultServeMux就是ServeMux结构的一个实例(好吧,看名字也看的出来),ServeMux是Go中默认的路由表,里边有个一map类型用于存储URI与处理方法的对应的键值对(String,muxEntry),muxEntry中的Handler类型就是对应的方法。

再来看HandleFunc方法:

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	mux.Handle(pattern, HandlerFunc(handler))
}
func (mux *ServeMux) Handle(pattern string, handler Handler) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

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

	mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}

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

	// Helpful behavior:
	// If pattern is /tree/, insert an implicit permanent redirect for /tree.
	// It can be overridden by an explicit registration.
	n := len(pattern)
	if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
		// If pattern contains a host name, strip it and use remaining
		// path for redirect.
		path := pattern
		if pattern[0] != '/' {
			// In pattern, at least the last character is a '/', so
			// strings.Index can't be -1.
			path = pattern[strings.Index(pattern, "/"):]
		}
		url := &url.URL{Path: path}
		mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern}
	}
}

  HandleFunc中调用了ServeMux的handle方法,这个handle才是真正的注册处理函数,而且注意到调用handle方法是第二个参数进行了强制类型转换(红色加粗标注部分),将一个func(ResponseWriter, *Request)函数转换成了HanderFunc(ResponseWriter, *Request)函数(注意这里HandlerFunc比一开始调用的HandleFunc多了个r,别弄混了

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇基于资源的权限系统-API设计 下一篇go: GOPATH entry is relative; m..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目