Intelligence without ambition is a bird without wings.

2015-10-14
go-windows环境搭建

  1. 官网

  2. 解压到E:\Soft\go\bin\go1.5.1.windows-amd64

  3. 设置环境变量

    GOROOT=E:\Soft\go\bin\go1.4.2.windows-amd64\go
    GOPATH=E:\Soft\go\gopath
    PATH+=%GOROOT%\bin
    PATH+=%GOPATH%\bin
    

参考

  1. https://golang.org/doc/install?download=go1.5.1.windows-amd64.zip
阅读此文

2015-10-13
go-gorilla-rpc

流程分析

  1. 外部接口
1
2
3
4
5
s := rpc.NewServer() // 定义一个rpc server

s.RegisterCodec(json2.NewCustomCodec(&rpc.CompressionSelector{}), "application/json")
// 定义一个codec(用来响应请求)
// 为rpc注册(当收到的http,`Content-Type`为`application/json`时,调用该codec响应处理)

参考

  1. https://github.com/gorilla/rpc
  2. http://www.gorillatoolkit.org/pkg/rpc
阅读此文

2015-10-13
go-json

要点

  • 编码解码是相对于json字符串(utf-8编码的slice)来讲的

    • 编码=>将go数据类型值转换为json字符串

    • 解码=>将json字符串转换为go中数据类型值

常用API

  • Marshal(v interface{}) ([]byte, error)

    编码

  • Unmarshal(data []byte, v interface{}) error

    解码

  • NewDecoder(r io.Reader) *Decoder (dec *Decoder) Decode(v interface{}) error

    从实现了io.Reader接口中的对象读取json字符串来解码

参考

  1. build-web-application-with-golang 7.2 JSON处理
  2. https://golang.org/pkg/encoding/json/
  3. https://godoc.org/github.com/bitly/go-simplejson
阅读此文

2015-10-10
mysql-alias

要点

  • 对目标列使用,

    • 输出列名可读性更强
  • 对表名使用

    • 简写表名

    • 同名表关联

  • 在select的目标输出列中(select_expr)

    • 别名可以在GROUP BY,ORDER BY,HAVING中使用

    • 标准SQl不允许在WHERE中使用

      因为WHERE是执行的,而SELECT目标列是基于WHERE结果的,
      所以WHERE中不能使用还没产生的别名!

  • AS可以省略

    select id userid from user;
    select a.id from user a;
    

参考

  1. https://dev.mysql.com/doc/refman/5.0/en/problems-with-alias.html
阅读此文

2015-10-10
数据库-命名规范

表名采用小写下划线

auth_user

列名采用小写下划线

is_superuser

关于id主键

  1. 表名_id(优先采用)

    • 输出目标列时,不用alias,对前端人员来说,附带一个表名,会使数据库可读性更强

      select user_id from user
      
    • 在多表查询,关联条件时,比较清晰

      select order.user_id, name, order_id from user, order where order.user_id = user.user_id
      
  2. id

    • 若需要引用某个表的id列,该列名还需要附带表名

      select user_id from order;
      
    • 输出目标列时,每个都需要alias,非常麻烦!

      select user.id as user_id, order.id as order_id from user, order where user.id = order.user_id
      

参考:

  1. http://stackoverflow.com/questions/3933803/database-design-primary-key-naming-conventions?rq=1
阅读此文

2015-10-09
mysql-decimal

要点

  1. decimal是使用字符存储数字的,所以不存在精度丢失问题

  2. decimal(M, N)

    • M说明存储数位长度(包括小数部分, 又叫精度, precision),取值范围1~65

    • N说明小数位数(scale, 标度),取值范围0~30,必须不大于M

参考

  1. https://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-characteristics.html
  2. http://stackoverflow.com/questions/2377174/how-do-i-interpret-precision-and-scale-of-a-number-in-a-database
阅读此文

2015-09-30
app-后台经验

数据库

  1. 业务逻辑实现难易程度,拓展性等跟表结构设计相关

  2. API优雅跟SQL语句的熟练,精妙程度相关

  3. 不要为了一点性能或存储空间而增加程序或逻辑的复杂度

    如用int来存储小数, 存储和读取都需要转换,还需要知道精度,增加复杂度,得不偿失

语言设计

  • 定义重要类型的别名,如typedef uint32_t uid_t
阅读此文

2015-09-30
sql

update

  • 当需要部分更新时,不要使用多表关联更新

    因为可能部分关联失败,导致需要更新的数据没有更新

    1
    update product a, order b set ... where a.product_id = b.product_id
阅读此文

2015-09-28
mysql-数据库备份恢复

备份恢复指定表

mysqldump -uwallace -pwallace stock_app t_banner_100 >stock_app.t_banner_100

mysql -uroot -pxianji -hsz003-db -P3309 stock_app <stock_app.t_banner_100
阅读此文

2015-09-25
go-database

要点

  • go官方没有直接提供数据库驱动,而是定义了一些标准接口(database/sql)

  • 第三方驱动通过包初始化函数init()调用sql.Register(name string, driver driver.Driver)完成注册

重要类型

driver.Conn

Conn是一个数据库连接的接口定义,他定义了一系列方法,这个Conn只能应用在一个goroutine里面,不能使用在多个goroutine里面

1
2
3
4
5
type Conn interface {
Prepare(query string) (Stmt, error)
Close() error
Begin() (Tx, error)
}
  • Prepare函数返回与当前连接相关的执行Sql语句的准备状态,可以进行查询、删除等操作。

  • Close函数关闭当前的连接,执行释放连接拥有的资源等清理工作.

  • Begin函数返回一个代表事务处理的Tx,通过它你可以进行查询,更新等操作,或者对事务进行回滚、递交。

driver.Stmt

Stmt是一种准备好的状态,和Conn相关联,而且只能应用于一个goroutine中,不能应用于多个goroutine

1
2
3
4
5
6
type Stmt interface {
Close() error
NumInput() int
Exec(args []Value) (Result, error)
Query(args []Value) (Rows, error)
}
  • Close函数关闭当前的链接状态,但是如果当前正在执行query,query还是有效返回rows数据

  • NumInput函数返回当前预留参数的个数,当返回>=0时数据库驱动就会智能检查调用者的参数。当数据库驱动包不知道预留参数的时候,返回-1

  • Exec函数执行Prepare准备好的sql,传入参数执行update/insert等操作,返回Result数据

  • Query函数执行Prepare准备好的sql,传入需要的参数执行select操作,返回Rows结果集

driver.Tx

事务处理一般就两个过程,递交或者回滚

1
2
3
4
type Tx interface {
Commit() error
Rollback() error
}

driver.Execer

这是一个Conn可选择实现的接口

1
2
3
type Execer interface {
Exec(query string, args []Value) (Result, error)
}

如果这个接口没有定义,那么在调用DB.Exec,就会首先调用Prepare返回Stmt,然后执行Stmt的Exec,然后关闭Stmt。

driver.Result

这个是执行Update/Insert等操作返回的结果接口定义

1
2
3
4
type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
}
  • LastInsertId函数返回由数据库执行插入操作得到的自增ID号。

  • RowsAffected函数返回query操作影响的数据条目数。

driver.Rows

Rows是执行查询返回的结果集接口定义

1
2
3
4
5
type Rows interface {
Columns() []string
Close() error
Next(dest []Value) error
}
  • Columns函数返回查询数据库表的字段信息,这个返回的slice和sql查询的字段一一对应,而不是返回整个表的所有字段。

  • Close函数用来关闭Rows迭代器。

  • Next函数用来返回下一条数据,把数据赋值给dest。dest里面的元素必须是driver.Value的值除了string,返回的数据里面所有的string都必须要转换成[]byte。如果最后没数据了,Next函数最后返回io.EOF。

driver.RowsAffected

RowsAffected其实就是一个int64的别名,但是他实现了Result接口,用来底层实现Result的表示方式

1
2
3
4
5
type RowsAffected int64

func (RowsAffected) LastInsertId() (int64, error)

func (v RowsAffected) RowsAffected() (int64, error)

driver.Value

Value其实就是一个空接口,他可以容纳任何的数据

1
type Value interface{}

drive的Value是驱动必须能够操作的Value,Value要么是nil,要么是下面的任意一种

1
2
3
4
5
6
int64
float64
bool
[]byte
string [*]除了Rows.Next返回的不能是string.
time.Time

driver.ValueConverter

ValueConverter接口定义了如何把一个普通的值转化成driver.Value的接口

1
2
3
type ValueConverter interface {
ConvertValue(v interface{}) (Value, error)
}

在开发的数据库驱动包里面实现这个接口的函数在很多地方会使用到,这个ValueConverter有很多好处:

  • 转化driver.value到数据库表相应的字段,例如int64的数据如何转化成数据库表uint16字段
  • 把数据库查询结果转化成driver.Value值
  • 在scan函数里面如何把driver.Value值转化成用户定义的值

driver.Valuer

Valuer接口定义了返回一个driver.Value的方式

1
2
3
type Valuer interface {
Value() (Value, error)
}

很多类型都实现了这个Value方法,用来自身与driver.Value的转化。

使用相关

sql.Stmt

sql.DB.Prepare返回的语句操作

1
2
3
4
(s *Stmt) Exec(args ...interface{}) (Result, error) // 带参数执行prepare语句(insert, update...)
(s *Stmt) Query(args ...interface{}) (*Rows, error) // 带参数执行select语句, 返回结果集
(s *Stmt) QueryRow(args ...interface{}) *Row // 带参数执行select语句,通过scan获取单行结果!(函数糖)
(s *Stmt) Close() error // 释放资源

sql.Row

QueryRow返回,结合scan用来获取单行查询结果

参考

  1. go web编程
阅读此文