博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【每日笔记】【Go学习笔记】2019-01-04 Codis笔记
阅读量:6704 次
发布时间:2019-06-25

本文共 2910 字,大约阅读时间需要 9 分钟。

作者:谭淼

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):

clipboard.png

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

2、martini框架

github地址:

Martini是一个为了编写模块化Web应用而生的强大的GO语言框架。其使用参考:

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)   }}

转载地址:http://rbblo.baihongyu.com/

你可能感兴趣的文章
CSS学习(一)
查看>>
SQL Server 数据库安全
查看>>
Android双机(网络和USB)调试及其完美ROOT
查看>>
Linux Suspend过程【转】
查看>>
变量命名那点小事
查看>>
Java 基础【02】 Super 用法
查看>>
makefile初步制作,arm-linux- (gcc/ld/objcopy/objdump)详解【转】
查看>>
VS2005中建立解决方案及多项目
查看>>
第 15 章 Div+CSS页面设计
查看>>
Git tag 给当前分支打标签
查看>>
route命令实例练习
查看>>
spring boot 2.0之基础入门
查看>>
钟南山:高收入群体往往老得快
查看>>
线程相关内存参数sort_buffer/join_buffer等的内存分配时机
查看>>
MSSQL · 最佳实践 · SQL Server备份策略
查看>>
如何调整word中表格某一列占半分比
查看>>
重构——34分解条件表达式(Decompose Conditional)
查看>>
mysql死锁问题分析(转)
查看>>
阿里云推出应用配置管理新工具 助力企业效能几何式提升
查看>>
一个程序员的陪产经历--写在宝宝百日之际
查看>>