Golang: 操作共享数据

在反复琢磨之后,最后还是决定用通过channel来模拟dispatcher的效果,网上的说法很多,不管了,可能我C#写多了,暂时就这样。

Go学习问题汇总

  • 代码如何组织? package main不能拆分成多个文件,必须分包?
  • T和&T有什么区别? 会产生什么影响?
  • 如何理解”Do not communicate by sharing memory; instead, share memory by communicating.”? channel是否可以取代mutex实现共享数据的读写?
  • new和make的区别? 设计意图是什么?
  • 如何建立异常体系? 实践panic, recover?

Go在线学习资料汇总

The Go Programming Language Specification – The Go Programming Language

CHANNEL

Go! (Part 4) – channel

go起头就是请求方法并行执行,然后通过channel进行通信同步。channel是同步对象,所以可以写入读取都是安全的,<-p是阻塞的,此处等同于join。

其实在go里面还是需要仔细甄别mutex和channel的选择问题,当然你可以用channel一定程度上代替mutex,比如,

取自: goroutine – How can we use channels in Google Go in place of mutex? – Stack Overflow

问题是channel和mutex还是略有区别,当然channel本身是机遇mutex来实现的,其实可以理解为mutex还是针对global data, cache, state等状态同步,而channel更是一种同步机制,在Use a sync.Mutex or a channel?一文中作了一个区分,

Channel Mutex 
passing ownership of data,
distributing units of work,
communicating async results
caches,
state

只能说术业有专攻,各取所需罢了。

Go! (Part 3) – Object

this的概念通过显示方式传入,传值和传引用和C是一致的。

最为关键的是interface体系,

虽说可以通过不同的方式创建对象,看上去也没什么区别,看代码,

Go! (Part 2) – Syntax

变量

  • 大小写敏感
  • var x int = 1或x := 1,:=表示声明同时初始化变量,根据初始化对象反推x类型。
  • 支持多重赋值,i, j = j, i
  • const表示常量,和C一样,但多了一个itoa,遇到const清零,每次itoa自增1
  • 基础类型包括:bool, byte, int8, int16, int, uint, uintptr, float32, float64, complex64, complex128, string ,rune(字符), error
  • 复合类型包括:pointer, array, slice, map, chan(通道), struct, interface
  • string对中文支持很好,内部很明显采用utf8编码
  • 数组:[32]byte, [3][5]int, [2][2][2]float64
  • Go语言中和C一样区分值类型(value type)和引用类型
  • 内置的map

流程控制

无非就是if, switch, for goto, 对,没有while,直接跳转Golang-控制语句 – 奇语闲谭

说实话,蛮妖怪的。

函数

  • first class, 多返回值,支持匿名和闭包
  • 最简单的函数: func x() { }
  • 最完整的函数: func x(a int, b string) (ret int, err error) { }
  • 简化: func x(a, b int) int { }, 当a,b同为int,且只有一个返回值时
  • 不定参数:func x(args …int)
  • 匿名

Go! (Part 1)

开始学习Go,首先需要明确的是Go是静态语言,就是说需要编译链接后生成可执行文件才能运行。

从hello world开始,
vi hello.go

直接运行,go run hello.go
编译,go build hello.go

由于Go天生跨平台所以在*nix/mac下会生成hello,./hello运行,而windows下则直接生成hello.exe,如果你跨平台用gcc就知道有多麻烦了,而且go在平台层面直接支持x86和ia64,所以你也不需要考虑这些事情。

我个人感觉Go就是一个全新的C升级版,跨平台,直接支持utf8,支持异常处理,匿名函数和lambda,简化过于灵活的指针,抽象32/64bit架构,直接支持并行,直接生成二进制,混C,你还等什么呢?

Mongodb 笔记 (Part 2)

熟悉MongoDB

  • 每个document都由一个”_id”特殊的键,这个键在此document所属的collection中是唯一的, _id不是guid,而是一个特定的ObjectId, 12字节长。

    ObjectId=时间戳(4)+机器名散列(3)+PID(3)+计数器(4),所以1秒内同一进程插入的数据只有最后3位不同,如果插入的document没有_id,MongoDB会自动创建。
  • 区分类型,区分大小写。{“foo”:3}和{“foo”:”3″}是不同的,foo, Foo当然也是不同的。
  • document中不能出现重复key
  • collection不能以”system.”开头,不能包含”$”字符
  • database-collection-document,database最终会变成文件系统里的文件,文件名就是数据库名(/data/db下并没有以数据库为名的文件,这是为什么呢?)
  • 通过mongod –rest启动内置web interface,允许rest的数据操作,见官方说明

    运行mongod –rest首先要确保关闭先前的mongod instance,进入mongo admin,然后db.shutdownServer()
  • shell(mongo)是一个javascript解释器加上mongo语法糖(db, use)等
  • Mac下开机启动通过homebrew的script参考brew info mongo, 手动启动服务,launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mongodb.plist

使用MongoDB shell

连接远程mongodb: mongo 192.168.0.105:27017/mydb,如果需要远程连接需要关闭默认配置中的bind_ip,修改mongod.conf,注释掉bind_ip:

仅启动shell: mongo –nodb
启动后再连接,即shell内连接:

可以传入javavscript给shell,

或者

–quiet即重定向stdout到null
如果在shell内可以通过load(“script.js”)调用script, load只能处理绝对路径无法处理~。

shell启动时会默认加载.mongorc.js,通常在rc.js中放入常用函数省去每次加载的麻烦。

继续,

  • upsert等同于insert+update,如果有则update,没有则insert
  • find支持正则表达式,db.users.find({“name”: /joe/i}), MongoDB的正则采用Perl的PCRE库来实现
  • 可以通过script.js来扩展mongo服务端功能,这个后期着重研究,先提一下

使用MongoDB进行开发

索引

通过db.users.ensureIndex({“name”:1});建立索引,通常一个特定的collection上不应该拥有2个以上的索引,挑选合适的字段建立索引非常重要。因为索引涉及的开销包括内存以及CUD时的更新。

通过explain()来检查效率,db.users.find({“name”:”user101″});

聚合

MapReduce

复制

分片

应用程序管理

服务器管理

参考内容:

Mongodb 笔记 (Part 1)

  1. Mac OSX下通过brew安装mongodb(brew install mongodb),如果需要升到最新版本则如下步骤,
  2. 安装完成后如需开机启动,则跟着brew info mongodb配置即可,

    mongod默认的数据库路径为/data/db,所以sudo mkdir -p /data/db,然后需要将权限调回启动mongod的用户,sudo chown nonocast:wheel /data/db。
  3. mongod是服务程序,而mongo是mongod的shell,是client,这点需要明确。
  4. 热身,shell下打开mongo,默认use test数据库,切换到你自己use mydb,然后db.test.insert({name: “nonocast”})即完成了新建collection以及创建document 2个动作,然后通过db.test.drop()删除测试数据。
  5. 通过show collections可以查看当前的collection,通过db.createCollection(name)创建,通过具体collection drop删除,use会自动切换到新的数据库,而通过db.dropDatabase()删除当前所选中的数据库。
  6. 具体的database api可以见Database Methods — MongoDB Manual 2.6.4
  7. mongodb的2个核心概念,collection和document
  8. collection.find中可加入搜索条件,比如db.users.find( { age: { $gt: 18 } }, { name: 1, address: 1 } ).limit(5)
  9. CRUD,对应collection.insert(document), collection.update(criteria, document), collection.remove(criteria)
  10. mongodb admin UIs提供了很多通过web/app来管理mongodb的工具,眼花缭乱。最终在smog和mongo-express中选了mongo-express。

    npm install mongo-express -g后cd /usr/local/lib/node_modules/mongo-express,通过npm get config prefix获取全局安装路径,cp config.default.js config.js,基本不用修改,然后node app打开浏览器localhost:8081即可。

RFC 6455笔记

RFC 6455: http://tools.ietf.org/html/rfc6455

  • The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The security model used for this is the origin-based security model(同源策略) commonly used by web browsers. The protocol consists of an opening handshake followed by basic message framing,layered over TCP. The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers.
  • WebSocket的版本历程,

    如上表所见,RFC 6455已经是正式版本,也是整个草案的第十个版本,网上也有用人hybi09,hybi10来表示RFC 6455,知道一下就OK了。
  • 整个WebSocket协议分为2个阶段,先握手,握手成功后升级为WebSocket开始通信,原文描述: After a successful handshake, clients and servers transfer data back and forth in conceptual units referred to in ths specification as “message”. On the wire, a message is composed of one or more frames.
  • A frame has an associated type. Each frame belonging to the same message contains the same type of data. Broadly speaking, there are types for texture data(UTF-8), binary data and control frames. This version of the protocol defines six frame types and leaves ten reserved for future use.
  • The handshake from the client looks as follows:

    其中Leading Line + Request Line符合HTTP[RFC2612],首先由client发起请求升级为WebSocket协议连接,Host区分网站(domain)这个不用解释了,而/chat则区分同站点中不同的websocket域,即同一站点内允许多个websocket server。Upgrade+Connection+Sec-WebSocket-Key则是向server申请提升。
    其中Sec-WebSocket-Key为base64编码,此key需要验证后续response中的Sec-WebSocket-Accept是否匹配。
    而Sec-WebSocket-Protocol则是应用协议,这个看程序了,协议本身不关心。
  • The handshake from the server looks as follows:

    server回复就简单很多,如果提交上来又Upgrade+Connection+Sec-WebSocket-Key则将此Key+”258EAFA5-E914-47DA-95CA-C5AB0DC85B11″然后计算此字符串的SHA-1通过base64返回给client。
    回复的Leading line如果同意提升则status code为101,其余都认为失败。一旦101后双方就可以通信了。
  • WebSocket是基于TCP的,仅依赖HTTP进行握手,升级后脱离HTTP协议,WebSocket协议允许和HTTP共用80端口,或者同时共用443。
  • WebSocket URI定义了2种scheme,如下,
    • ws-URI = “ws:” “//” host [ “:” port ] path [ “?” query ]
    • wss-URI = “wss:” “//” host [ “:” port ] path [ “?” query ]

    ws端口默认80,wss默认443。

Continue reading