【每日笔记】【Go学习笔记】2019-01-04 Codis笔记

栏目: Go · 发布时间: 5年前

内容简介:作者:谭淼dlv是调试go语言的工具,与gdb类似。下面是一些dlv的常用命令:调试命令(常用的为break,continue,next,print):

作者:谭淼

1、dlv的使用

dlv是调试 go 语言的工具,与gdb类似。下面是一些dlv的常用命令:

  • (1)dlv attach pid:类似与gdb attach pid,可以对正在运行的进程直接进行调试(pid为进程号)。
  • (2)dlv debug:运行dlv debug test.go会先编译go源文件,同时执行attach命令进入调试模式,该命令会在当前目录下生成一个名为debug的可执行二进制文件,退出调试模式会自动被删除。
  • (3)dlv exec executable_file:直接从二进制文件启动调试模式。

调试命令(常用的为break,continue,next,print):

【每日笔记】【Go学习笔记】2019-01-04 Codis笔记

注意:dlv可以通过goroutines查看所有的协程,并通过“goroutine 协程号”来切换协程。

2、martini框架

github地址: https://github.com/go-martini...

Martini是一个为了编写模块化Web应用而生的强大的GO语言框架。其使用参考: https://github.com/go-martini...

3、codis-fe的启动

codis-fe启动首先要解析参数,然后启动martini。

m := martini.New()
m.Use(martini.Recovery())
m.Use(render.Renderer())
m.Use(martini.Static(assets, martini.StaticOptions{SkipLogging: true}))

首先调用martini.New()方法创建一个Martini结构体,然后在调用该结构体的Use方法注册中间件。

中间件的注册比较简单,就是向handlers切片添加方法。

func (m *Martini) Use(handler Handler) {
   //校验方法
   validateHandler(handler)

   m.handlers = append(m.handlers, handler)
}

在处理请求时,会遍历注册的处理函数执行。

func (c *context) run() {
   for c.index <= len(c.handlers) {
      _, err := c.Invoke(c.handler())
      if err != nil {
         panic(err)
      }
      c.index += 1

      if c.Written() {
         return
      }
   }
}

除此之外,还有一个疑问,对于静态资源,是在哪里决定Content-Type的呢?

func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker) {
    ......
    // If Content-Type isn't set, use the file's extension to find it, but
    // if the Content-Type is unset explicitly, do not sniff the type.
    ctypes, haveType := w.Header()["Content-Type"]
    var ctype string
    if !haveType {
        ctype = mime.TypeByExtension(filepath.Ext(name))
        if ctype == "" {
           // read a chunk to decide between utf-8 text and binary
           var buf [sniffLen]byte
           n, _ := io.ReadFull(content, buf[:])
           ctype = DetectContentType(buf[:n])
           _, err := content.Seek(0, io.SeekStart) // rewind to output whole file
           if err != nil {
              Error(w, "seeker can't seek", StatusInternalServerError)
              return
           }
        }
        w.Header().Set("Content-Type", ctype)
    } else if len(ctypes) > 0 {
       ctype = ctypes[0]
    }
    ......
}

从代码可以看出,是根据后缀名来决定的。

后面将会新建一个路由实例,并添加路由。

r := martini.NewRouter()
r.Get("/list", func() (int, string) {
   names := router.GetNames()
   sort.Sort(sort.StringSlice(names))
   return rpc.ApiResponseJson(names)
})

r.Any("/**", func(w http.ResponseWriter, req *http.Request) {
   name := req.URL.Query().Get("forward")
   if p := router.GetProxy(name); p != nil {
      p.ServeHTTP(w, req)
   } else {
      w.WriteHeader(http.StatusForbidden)
   }
})

注册路由后便开启服务。

hs := &http.Server{Handler: h}
if err := hs.Serve(l); err != nil {
   log.PanicErrorf(err, "serve %s failed", listen)
}

Serve函数的实现也很简单,就是循环进行accept,每收到请求便创建一个协程进行处理。

func (srv *Server) Serve(l net.Listener) error {
   ......
   for {
      rw, e := l.Accept()
      ......
      tempDelay = 0
      c := srv.newConn(rw)
      c.setState(c.rwc, StateNew) // before Serve can return
      go c.serve(ctx)
   }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Scalable Internet Architectures

Scalable Internet Architectures

Theo Schlossnagle / Sams Publishing / 2006-7-31 / USD 49.99

As a developer, you are aware of the increasing concern amongst developers and site architects that websites be able to handle the vast number of visitors that flood the Internet on a daily basis. Sc......一起来看看 《Scalable Internet Architectures》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具