vitess源码阅读笔记cache系列之memcache客户端(兼谈让人又爱又恨的gc和golang的错误处理机制)
memcache.go还是非常值得一看的。奇怪的是vitess的安装文档没有提到要求安装memcached,至于为什么使用memcache,
而不是进程内的cache以节省开销呢?vitess的文档是这样描述的:
所以选择了memcache。另外这里有篇文章分享了从ruby到golang到c的历程也说明go的gc还不够成熟。
豆瓣的一哥们也分享了golang手动管理内存的心得,见这里
func newConnection(nc net.Conn) *Connection {
return &Connection{
conn: nc,
buffered: bufio.ReadWriter{
bufio.NewReader(nc), //只要实现了Read接口就可以用来构造Reader
bufio.NewWriter(nc), //只要实现了Write接口就可以用来构造Writer
},
}
}
func (self *Connection) Close() {
self.conn.Close()
self.conn = nil //用于判断一个connection是否关闭了,见IsClosed函数
}
func (self *Connection) IsClosed() bool {
return self.conn == nil
}
以Get函数为例:
defer handleError(&err)
value, flags, _ = self.get("get", key)
return
}
没有看到长长的try和cache了,代码又少了5行左右。有人说了,不就是几个大括号嘛,亲,再给你几个函数看看
defer handleError(&err)
value, flags, cas = self.get("gets", key)
return
}
func (self *Connection) Set(key string, flags uint16, timeout uint64, value []byte) (stored bool, err error) {
defer handleError(&err)
return self.store("set", key, flags, timeout, value, 0), nil
}
func (self *Connection) Add(key string, flags uint16, timeout uint64, value []byte) (stored bool, err error) {
defer handleError(&err)
return self.store("add", key, flags, timeout, value, 0), nil
}
func (self *Connection) Replace(key string, flags uint16, timeout uint64, value []byte) (stored bool, err error) {
defer handleError(&err)
return self.store("replace", key, flags, timeout, value, 0), nil
}
func (self *Connection) Append(key string, flags uint16, timeout uint64, value []byte) (stored bool, err error) {
defer handleError(&err)
return self.store("append", key, flags, timeout, value, 0), nil
}
func (self *Connection) Prepend(key string, flags uint16, timeout uint64, value []byte) (stored bool, err error) {
defer handleError(&err)
return self.store("prepend", key, flags, timeout, value, 0), nil
}
func (self *Connection) Cas(key string, flags uint16, timeout uint64, value []byte, cas uint64) (stored bool, err error) {
defer handleError(&err)
return self.store("cas", key, flags, timeout, value, cas), nil
}
func (self *Connection) Delete(key string) (deleted bool, err error) {
defer handleError(&err)
// delete <key> [<time>] [noreply]\r\n
self.writestrings("delete ", key, "\r\n")
reply := self.readline()
if strings.Contains(reply, "ERROR") {
panic(NewMemcacheError("Server error"))
}
return strings.HasPrefix(reply, "DELETED"), nil
}
乖乖,这下可少了不少代码行,少了50行左右,不能不说这个defer漂亮。
Message string
}
//可变参数,这个在golang里面也是个常见的模式
func NewMemcacheError(format string, args ...interface{}) MemcacheError {
return MemcacheError{fmt.Sprintf(format, args...)}
}
func (self MemcacheError) Error() string {
return self.Message
}
func handleError(err *error) {
if x := recover(); x != nil {
*err = x.(MemcacheError) //golang是强类型的,interface需要强制要转化一下,这也是golang的常见模式
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。