Categorygithub.com/63isok/golearn
module
0.0.0-20191212051225-55170d735e5c
Repository: https://github.com/63isok/golearn.git
Documentation: pkg.go.dev

# README

part1: introduce about go web app

go

  • simple
  • efficient
  • back end system

for web app and *-as-a-server system

large-scale web app features:

  • scalable
    • vertical scaling: increasing cpu goroutine
    • horizontal scaling: increasing machines layer: add a proxy layer
  • modular easy to add/remove/modify feature easy to reusing modular components
  • maintainable
  • high performance

web app and web server

app: software program

web app:

  • return html,(client render html and display to user)
  • transport data by http

web service:

  • not return html
  • server for other program

http

app-level communication protocol

  • stateless
  • text-based
  • request-response
  • c/s

request

a request consists of a few line:

  • request-line
  • zero or more request headers
  • an empty line
  • the message body (optional)

GET /Protocols/rfc2616/rfc2616.html HTTP/1.1 Host: www.w3.org User-Agent: Mozilla/5.0 (empty line) abc

request-line = request method + uri + http version request headers = a:b c:d

request method

  • get: Tells the server to return the specified resource.
  • head: The same as GET except that the server must not return a message body.
  • post: Tells the server that the data in the message body should be passed to the resource identified by the URI .
  • put: Tells the server that the data in the message body should be the resource at the given URI .
  • delete: Tells the server to remove the resource identified by the URI .
  • trace: Tells the server to return the request
  • options: Tells the server to return a list of HTTP methods that the server supports.
  • connect: Tells the server to set up a network connection with the client.
  • patch: Tells the server that the data in the message body modifies the resource identified by the URI .

idempotent
the result of 1 call = the result of 1000 times call

request_header

request header consists:

  • info of request
  • info of client

if request have a message, Content-Length and Transfer-Encoding is need

common http request headers:

  • Accept: Content types that are acceptable by the client as part of the HTTP response.
  • Accept-Charset: The character sets required from the server.
  • Authorization: This is used to send Basic Authentication credentials to the server.
  • Cookie: The client should send back cookies that were set by the calling server.
  • Content-Length: The length of the request body in octets.
  • Content-Type: The content type of the request body.
  • Host: The name of the server, along with the port number.
  • Referrer: The address of the previous page that linked to the requested page.
  • User-Agent: Describes the calling client.

response

a response consists of a few line:

  • a status line
  • zero ro more response headers
  • an empty line
  • the message body (optional)

status line = status code + reason phrase

status_code

  • 1xx: Informational. This tells the client that the server has already received the request and is processing it.
  • 2xx: Success. This is what clients want; the server has received the request and has processed it successfully. The standard response in this class is 200 OK.
  • 3xx: Redirection. This tells the client that the request is received and processed but the client needs to do more to complete the action.
  • 4xx: Client Error. This tells the client that there’s something wrong with the request.
  • 5xx: Server Error. This tells the client that there’s something wrong with the request but it’s the server’s fault.

response_header

common http response headers:

  • Allow: Tells the client which request methods are supported by the server.
  • Content-Length: The length of the response body in octets
  • Content-Type: The content type of the response body
  • Date: Tells the current time
  • Location: This header is used with redirection, to tell the client where to request the next URL.
  • Server: Domain name of the server that’s returning the response.
  • Set-Cookie: Sets a cookie at the client.
  • WWW-Authenticate: Tells header the client what type of authorization clients should supply in their Authorization request header.

  • rui: name of resource
  • rul: location of resource

RUI form:
< scheme name> : < hierarchical part> [ ? < query> ][ # < fragment> ]"

http://user:[email protected]/doc/file?name=test&ip=123#sum

http2

  • focuse on performance
  • based on spdy/2
  • binary protocol (http1.x base on text)
  • full multiplexed
  • compress the header
  • allow server to push response to client

in go1.6 and after, http2 is default

define web app

  • get a http request form client
  • process the requet, do some work
  • generate html and return it in an http response message

web app = handlers + template engine

handlers

  • receives and process the http request

  • call the template engine to generate the html and something about response

    mvc(model-view-controller pattern) divide a arogram into three parts: model, view, controller model - underlaying data view - visualization of the model for the user controller - use input(from user) to modify the model model change --> view update automatically

mvc is a good way for web app, but is not the only way

template engine

come form ssi technology

there are two type of template with different design philosophies:

  • static template or logic-less template use placeholder tokens no logic
  • active template placehoder tokens + other programming language eg: jsp asp erb

example - forums


part2: details in go web program

handling requests

货物崇拜编程:在不理解需求痛点的情况下,复制一份可运行的代码,
对代码也不很了解,最后导致扩展很困难。
换句话说就是使用了不理解的解决方案,导致无法明确预期。
在编程中,可能是使用了一个强大的框架,但不知道正确的使用规则。

为什么client要持久化cookie,server要持久化session信息:
因为http是无状态协议,而且每次请求,不会带上上次请求的相关信息

web app的框架首推标准库中的net/htpp + html/template,其次是其他三方库, 为了避免货物崇拜编程,需要了解一下标准库中的一些规则(就像上面的cookie和session)

  func ListenAndServe(addr string, handler Handler) error
  // addr 网络地址,空字符串表示使用80端口
  // handler 为nil,默认处理器(handler)就是默认复用器,DefaultServeMux

  http.ListenAndServe(":80", nil);  // 这个server未做配置
  server := http.Server{Addr: ":80", Handler: nil,}
  server.ListenAndServe()  // 这个是通过Server结构体来配置server

监听tcp端口,处理request,

在web app中(golang中),handler和handler function并不是一个, handler是一个接口:

    type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
    }

任何实现这个这个方法的,都可以被称为一个handler

接下来看看DefaultServeMux:

// ListenAndServe listens on the TCP network address addr and then calls
// Serve with handler to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// The handler is typically nil, in which case the DefaultServeMux is used.
//
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}
// 用两个参数去初始化一个Server结构体,然后调用其中的方法

type Server struct {
    Addr    string  // TCP address to listen on, ":http" if empty
    Handler Handler // handler to invoke, http.DefaultServeMux if nil
    ...
}
// 如果Handler未指定,就默认取http.DefaultServeMux

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux
// 结构是ServeMux

func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
// 绕了一圈,DefaultServeMux是实现了Handler接口的

这个默认Handler的来历是理顺了,那她的作用是:
根据不同的rul,将请求丢给不同的handler,说白了就是一个默认的复用器。

为什么需要一个复用器?
如果不用复用器,请求全都会被一个handler处理, 显然从设计上讲,分层是必须的,至少扩展是非常方便的

尽量避免一个handler处理全部的request

    http.Handle("/hello", &hello)

用这个来指定对固定uri的处理,除了/是匹配所有,其他的都是完全匹配, 有一点差别都会报404, /hello/ 多了一个/也是404, 为啥设计时不考虑将/hello 和/hello/兼容呢? 最小惊讶原则

再总结一下Handler:

  • 是一个接口
  • 有一个方法来实现这个接口
  • http.Handle(uri, &handler)来指定如何处理

什么是handler function:

  • 和handler的功能类似
  • 不是方法,不是接口,只是一个函数,参数和ServeHTTP一致
  • http.HandleFunc(uri, handler function)来指定如何处理
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(pattern, handler)
}
// 这个直接是使用了DefaultServeMux默认复用器

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}
// 实际上调用了ServeMux的方法
// 这个HandlerFunc,是一个函数类似,T(a)这种写法是类型转换
// 用处是将handler function 转换成Handler

// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
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)
	}
	e := muxEntry{h: handler, pattern: pattern}
	mux.m[pattern] = e
	if pattern[len(pattern)-1] == '/' {
		mux.es = appendSorted(mux.es, e)
	}

	if pattern[0] != '/' {
		mux.hosts = true
	}
}
// 这个就是将uri和handler成对保存起来
// 说白了就是一个handler注册过程,后面遇到对应的uri,调用不同的handler来处理

handler 和 handler function, 一个是接口,一个是函数, handler = HandleFunc(handler function),可使用类型转换直接转换

为什么要提供功能相同,只是写法上有所区别的两种概念:
实际上使用的还是handler,但写法上,handler function简单很多,所以这就是原因

反过来,既然handler function很方便,为啥还要暴露出handler概念:
设计上的需求,可以提高模块化(实际上是为了更好的兼容性)

go 不是一个函数性的语言,但函数形语言的一些基本特征还是包括的:
函数类型,匿名函数, 闭包。

有个新的概念叫aop 和oop可以互补,aop 面向切面编程,属于设计模式的延伸, 其中有个概念叫cross-cutting concern,叫横切关注点, 映射到go中,就是日志handler,安全handler,等很多独立的功能handler, 只关注自己业务上的事,至于和其他业务模块联合起来,就是aop中的织网, 在go语言中,织网可以用chain(链式handler)来实现。

链式
假定我们的模块都已经做好了(各个功能性的handler已经完成,且高内聚低耦合),
下一步就是织网,在c++中,要考虑的是各个模块调用的参数问题,
在go中使用统一的格式即可:
func xxx(h http.HandlerFunc) http.HandlerFunc {}
这样织网时就不需要考虑模块之间参数的问题,
A(B(C)), A(C) 按业务进行组合即可

链式的handler,可以非常长,也被称为 pipeline processing

    func xxx(h http.HandlerFunc) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            ...  // 做模块自己的事
            h(w, r)
        }
    }
    // 最后一个链式节点,使用方法(实现Handler的)

链式的handler和链式的handler function是一样的

除了默认的复用器,也有第三方的, ServeMux用来处理固定的uri是很合适的,处理动态uri就力有不怠

http2 需要使用https

process request

前面提到过:
RUI form:
< scheme name> : < hierarchical part> [ ? < query> ][ # < fragment> ]"

http://user:[email protected]/doc/file?name=test&ip=123#sum

RUL form:
scheme://[userinfo@]host/path[?query][#fragment]
eg: http://www.example.com/post?id=123&thread_id=456

query是k-v键值对,fragment在浏览器发送请求之前就被丢弃了,所以服务端不考虑这个, 但是非浏览器工具发送请求时,有可能有这个fragment,就需要做特殊处理了

http头,在库中用Header类型来表示

    type Header map[string][]string  // 是一个map类型

    // 主要4个基本方法,用于增删改查
    func (h Header) Add(key, value string)
    func (h Header) Del(key string)
    func (h Header) Get(key string) string
    func (h Header) Set(key, value string)

    // Add和Set的区别
    // Header的key是string, value是[]string 切片
    // Set是先创建一个空白切片,切片的第一个值就是value
    // Add是在切面后面追加

http消息体,用 Body io.ReadCloser来表示

    Body io.ReadCloser

    type ReadCloser interface {
      Reader
      Closer
    }

    type Reader interface {
        Read(p []byte) (n int, err error)
    }

    type Closer interface {
        Close() error
    }

消息体是一个接口,实际上用两个接口来表示:

  • Reader:用于读body
  • Close:

http GET 请求不带消息体,POST才带,浏览器地址栏的请求都是GET请求, 如果要发post请求,只能用其他工具

表单

http post一般会带一个表单,也就是form, 而request中message的组织有多种方式,都可由请求之前指定:

  • 简单的文本,使用url编码格式
  • 大数据(eg:file),使用multipart- MIME格式
  • 二进制,使用base64编码格式

http get是没有消息体,也就是没有body的,她的参数都是加在url后面的

new book

new lib

everyday

debug

net

blog

package(pkg)

标准库关系

未来 TODO

需要奋力追赶的方向,也是欠下的技术债

  • 规范 git流 github流 k8s流等,提升沟通效率,是主流社区交流的语言,也是对开发测试部署/项目工程管理的一些共同认识
  • 效能工具 高效能开发的基础,将目光集中在创新(coding),提高自己和团队的效率,包括源码管理,ci/cd
  • 技能 包括基础的语言和开发包,核心价值的基础,目前主要方向是go语言
  • 开发部署套件 和效能工具有所区别,效能工具侧重点在使用,而这里主要关注工具的深度学习,eg:docker git k8s vim等
  • 方向 包含的东西很多:架构(包括设计和系统部署) 微服务 性能架构
  • 团队管理 30岁的年纪,20岁的情商
  • CNCF

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author