mysql导入codis_【每日笔记】【Go学习笔记】2019-01-04 Codis笔记

作者:谭淼

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

bVbmMS2?w=1826&h=1466

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

2、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)

}

}

有疑问加站长微信联系(非本文作者)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值