【go】操作数据库

Continue Read..

目录结构

点击查看原图

 

@GOPATH

点击查看原图

 

 

CREATE TABLE `userinfo` (

  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `name` varchar(20) NOT NULL DEFAULT '',

  `uid` int(10) unsigned NOT NULL DEFAULT '0',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8


 

1.go

package main
 
import (
	"conf"
	"fmt"
	// 或者
	// myDbConf "conf"
)
 
func main() {
	opend, db := conf.OpenDB()
	//opend, db := myDbConf.OpenDB()
 
	fmt.Println(db)
	if opend {
		fmt.Println("open success")
	} else {
		fmt.Println("open faile:")
	}
	// DeleteFromDB(db, 10)
	//QueryFromDB(db)
	//DeleteFromDB(db, 1)
	//UpdateDB(db, 5)
	conf.InsertToDB(db)
	//myDbConf.InsertToDB(db)
 
	//UpdateUID(db, 5)T
	//UpdateTime(db, 4)
 
}

 
 
 
dbConf.go
package dbConf
 
import (
	"crypto/md5"
	"database/sql"
	"encoding/hex"
	"fmt"
	"strconv"
	"time"
 
	_ "github.com/go-sql-driver/mysql"
)
 
const (
	DB_Driver = "root:root@tcp(127.0.0.1:3306)/test?charset=utf8"
)
 
func OpenDB() (success bool, db *sql.DB) {
	var isOpen bool
	db, err := sql.Open("mysql", DB_Driver)
	// fmt.Println(db)
	if err != nil {
		isOpen = false
	} else {
		isOpen = true
	}
	CheckErr(err)
	return isOpen, db
}
 
func InsertToDB(db *sql.DB) {
	uid := GetNowtimeMD5()
	// nowTimeStr := GetTime()
	stmt, err := db.Prepare("insert userinfo set name=?,uid=?")
	CheckErr(err)
	res, err := stmt.Exec("wangbiao", uid)
	CheckErr(err)
	id, err := res.LastInsertId()
	CheckErr(err)
	if err != nil {
		fmt.Println("插入数据失败")
	} else {
		fmt.Println("插入数据成功:", id)
	}
}
 
func QueryFromDB(db *sql.DB) {
	rows, err := db.Query("SELECT * FROM userinfo")
	CheckErr(err)
	if err != nil {
		fmt.Println("error:", err)
	} else {
	}
	for rows.Next() {
		var uid string
		var name string
 
		CheckErr(err)
		err = rows.Scan(&uid, &name)
		fmt.Println(name)
		fmt.Println(uid)
	}
}
 
func UpdateDB(db *sql.DB, uid string) {
	stmt, err := db.Prepare("update userinfo set name=? where uid=?")
	CheckErr(err)
	res, err := stmt.Exec("zhangqi", uid)
	affect, err := res.RowsAffected()
	fmt.Println("更新数据:", affect)
	CheckErr(err)
}
func DeleteFromDB(db *sql.DB, id int) {
	stmt, err := db.Prepare("delete from userinfo where id=?")
	CheckErr(err)
	res, err := stmt.Exec(id)
	affect, err := res.RowsAffected()
	fmt.Println("删除数据:", affect)
}
 
func CheckErr(err error) {
	if err != nil {
		panic(err)
		fmt.Println("err:", err)
	}
}
 
func GetTime() string {
	const shortForm = "2006-01-02 15:04:05"
	t := time.Now()
	temp := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), time.Local)
	str := temp.Format(shortForm)
	fmt.Println(t)
	return str
}
 
func GetMD5Hash(text string) string {
	haser := md5.New()
	haser.Write([]byte(text))
	return hex.EncodeToString(haser.Sum(nil))
}
 
func GetNowtimeMD5() string {
	t := time.Now()
	timestamp := strconv.FormatInt(t.UTC().UnixNano(), 10)
	return GetMD5Hash(timestamp)
}
 mysql.zip

 

声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权

beego分页bootstrap V3风格

Continue Read..

修改自简单的beego分页功能代码,原版里的样式比较特别,现在改成了bootstrap风格

看图:

点击查看原图

点击查看原图

点击查看原图

 

看代码:

package pager

/**
 * 分页功能
 * 支飞亚
 * 2014-9-1
 *
 * bootstrap V3风格
 * wulin
 * 2015-09-24
 */
import (
	// "fmt"

	"github.com/astaxie/beego/context"
	"github.com/astaxie/beego/orm"
	html "html/template"
	con "strconv"
	"strings"
	"time"
)

type PageOptions struct {
	TableName           string //表名  -----------------[必填]
	Conditions          string //条件
	Currentpage         int    //当前页 ,默认1 每次分页,必须在前台设置新的页数,不设置始终默认1.在控制器中使用方式:cp, _ := this.GetInt("pno")   po.Currentpage = int(cp)
	PageSize            int    //页面大小,默认20
	LinkItemCount       int    //生成A标签的个数 默认10个
	Href                string //A标签的链接地址  ---------[不需要设置]
	ParamName           string //参数名称  默认是pno
	FirstPageText       string //首页文字  默认"首页"
	LastPageText        string //尾页文字  默认"尾页"
	PrePageText         string //上一页文字 默认"上一页"
	NextPageText        string //下一页文字 默认"下一页"
	EnableFirstLastLink bool   //是否启用首尾连接 默认false 建议开启
	EnablePreNexLink    bool   //是否启用上一页,下一页连接 默认false 建议开启
}

/**
 * 分页函数,适用任何表
 * 返回 总记录条数,总页数,以及当前请求的数据RawSeter,调用中需要"rs.QueryRows(&tblog)"就行了  --tblog是一个Tb_log对象
 * 参数:表名,当前页数,页面大小,条件(查询条件,格式为 " and name='zhifeiya' and age=12 ")
 */
func GetPagesInfo(tableName string, currentpage int, pagesize int, conditions string) (int, int, orm.RawSeter) {
	if currentpage <= 1 {
		currentpage = 1
	}
	if pagesize == 0 {
		pagesize = 20
	}
	var rs orm.RawSeter
	o := orm.NewOrm()
	var totalItem, totalpages int = 0, 0                                                          //总条数,总页数
	o.Raw("SELECT count(*) FROM " + tableName + "  where 1>0 " + conditions).QueryRow(&totalItem) //获取总条数
	if totalItem <= pagesize {
		totalpages = 1
	} else if totalItem > pagesize {
		temp := totalItem / pagesize
		if (totalItem % pagesize) != 0 {
			temp = temp + 1
		}
		totalpages = temp
	}
	rs = o.Raw("select *  from  " + tableName + "  where id >0 " + conditions + " LIMIT " + con.Itoa((currentpage-1)*pagesize) + "," + con.Itoa(pagesize))
	return totalItem, totalpages, rs
}

/**
* 返回总记录条数,总页数,当前页面数据,分页html
* 根据分页选项,生成分页连接 下面是一个实例:
    func (this *MainController) Test() {
       var po util.PageOptions
       po.EnablePreNexLink = true
       po.EnableFirstLastLink = true
       po.LinkItemCount = 7
       po.TableName = "help_topic"
       cp, _ := this.GetInt("pno")
       po.Currentpage = int(cp)
       _,_,_ pager := util.GetPagerLinks(&po, this.Ctx)
       this.Data["Email"] = html.HTML(pager)
       this.TplNames = "test.html"
   }
*/
func GetPagerLinks(po *PageOptions, ctx *context.Context) (int, int, orm.RawSeter, html.HTML) {
	var str string = ""
	totalItem, totalpages, rs := GetPagesInfo(po.TableName, po.Currentpage, po.PageSize, po.Conditions)
	po = setDefault(po, totalpages)
	DealUri(po, ctx)
	if totalpages <= po.LinkItemCount { //总页数<10
		str = fun1(po, totalpages) //显示完全  12345678910
	} else if totalpages > po.LinkItemCount { //总页数>10
		if po.Currentpage < po.LinkItemCount {
			str = fun2(po, totalpages) //123456789...200
		} else {
			if po.Currentpage+po.LinkItemCount < totalpages { //最后10页前面
				str = fun3(po, totalpages)
			} else {
				str = fun4(po, totalpages)
			}
		}
	}
	return totalItem, totalpages, rs, html.HTML(str)
}

/**
 * 处理url,目的是保存参数
 */
func DealUri(po *PageOptions, ctx *context.Context) {
	uri := ctx.Request.RequestURI
	var rs string
	if strings.Contains(uri, "?") {
		arr := strings.Split(uri, "?")
		rs = arr[0] + "?" + po.ParamName + "time=" + con.Itoa(time.Now().Second())
		arr2 := strings.Split(arr[1], "&")
		for _, v := range arr2 {
			if !strings.Contains(v, po.ParamName) {
				rs += "&" + v
			}
		}
	} else {
		rs = uri + "?" + po.ParamName + "time=" + con.Itoa(time.Now().Second())
	}
	po.Href = rs
}

/**
 * 1...197 198 199 200
 */
func fun4(po *PageOptions, totalpages int) string {
	var rs string = ""
	rs += getHeader(po, totalpages)
	rs += "
  • " + con.Itoa(1) + "
  • " rs += "
  • ...
  • " for i := totalpages - po.LinkItemCount; i <= totalpages; i++ { if po.Currentpage != i { rs += "
  • " + con.Itoa(i) + "
  • " } else { rs += "
  • " + con.Itoa(i) + "(current)
  • " } } rs += getFooter(po, totalpages) return rs } /** * 1...6 7 8 9 10 11 12 13 14 15... 200 */ func fun3(po *PageOptions, totalpages int) string { var rs string = "" rs += getHeader(po, totalpages) rs += "
  • " + con.Itoa(1) + "
  • " rs += "
  • ...
  • " for i := po.Currentpage - po.LinkItemCount/2 + 1; i <= po.Currentpage+po.LinkItemCount/2-1; i++ { if po.Currentpage != i { rs += "
  • " + con.Itoa(i) + "
  • " } else { rs += "
  • " + con.Itoa(i) + "(current)
  • " } } rs += "
  • ...
  • " rs += "
  • " + con.Itoa(totalpages) + "
  • " rs += getFooter(po, totalpages) return rs } /** * totalpages > po.LinkItemCount po.Currentpage < po.LinkItemCount * 123456789...200 */ func fun2(po *PageOptions, totalpages int) string { var rs string = "" rs += getHeader(po, totalpages) for i := 1; i <= po.LinkItemCount+1; i++ { if i == po.LinkItemCount { rs += "
  • ...
  • " } else if i == po.LinkItemCount+1 { rs += "
  • " + con.Itoa(totalpages) + "
  • " } else { if po.Currentpage != i { rs += "
  • " + con.Itoa(i) + "
  • " } else { rs += "
  • " + con.Itoa(i) + "(current)
  • " } } } rs += getFooter(po, totalpages) return rs } /** * totalpages <= po.LinkItemCount * 显示完全 12345678910 */ func fun1(po *PageOptions, totalpages int) string { var rs string = "" rs += getHeader(po, totalpages) for i := 1; i <= totalpages; i++ { if po.Currentpage != i { rs += "
  • " + con.Itoa(i) + "
  • " } else { rs += "
  • " + con.Itoa(i) + "(current)
  • " } } rs += getFooter(po, totalpages) return rs } /** * 头部 */ func getHeader(po *PageOptions, totalpages int) string { var rs string = "" return rs } /** * 设置默认值 */ func setDefault(po *PageOptions, totalpages int) *PageOptions { if len(po.FirstPageText) <= 0 { po.FirstPageText = "首页" } if len(po.LastPageText) <= 0 { po.LastPageText = "尾页" } if len(po.PrePageText) <= 0 { po.PrePageText = "上一页" } if len(po.NextPageText) <= 0 { po.NextPageText = "下一页" } if po.Currentpage >= totalpages { po.Currentpage = totalpages } if po.Currentpage <= 1 { po.Currentpage = 1 } if po.LinkItemCount == 0 { po.LinkItemCount = 10 } if po.PageSize == 0 { po.PageSize = 20 } if len(po.ParamName) <= 0 { po.ParamName = "pno" } return po }

    声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权

    linux下golang环境安装

    Continue Read..

    安装很简单,

    1.安装必要包 yum install mercurial git gcc

    2.解压go到/usr/local/go,建立gopath目录/gopath,这里的2个目录随便找位置放

    3.添加环境变量

    sudo vim /etc/profile

    在最后加入如下内容,注意里面的路径

    export GOROOT=/usr/local/go

    export PATH=$GOROOT/bin:$PATH

    export GOPATH=/gopath

    4.刷新环境变量source /etc/profile

    5.完成,执行go version可以看到对应版本信息


    参考http://jingyan.baidu.com/article/90895e0ffb4f1764ec6b0baa.html

    声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权

    golang的encoding/binary包的write和read

    Continue Read..

    中文文档 http://mygodoc.oschina.mopaas.com/pkg/encoding_binary.htm#ByteOrder

     

    func Read(r io.Reader, order ByteOrder, data interface{}) error

    从r中读取binary编码的数据并赋给data,data必须是一个指向定长值的指针或者定长值的切片。从r读取的字节使用order指定的字节序解码并写入data的字段里当写入结构体是,名字中有'_'的字段会被跳过,这些字段可用于填充(内存空间)。

        b := []byte{0x00, 0x00, 0x03, 0xe8}
    	b_buf := bytes.NewBuffer(b)
    	var x int32
    	binary.Read(b_buf, binary.BigEndian, &x)
    	fmt.Println(x)

    从b_buf里面读x的数据类型长度,比如这里int32长度4字节,就从b_buf读取4个byte,

    第二个参数,设置数据排列方式,上例中b不同情况下分别如下

    binary.BigEndian大端[0 152 150 128]

    binary.LittleEndian小端[128 150 152 0]

     

    要注意的地方就是第三个参数,取的他的数据类型的长度!

    write函数一样了,写入数据所占的byte等于写入的数据类型的长度!

    比如写入int32类型的值为1000000的数据,所占用的byte还是4字节


    不知道数据类型占用多长字节可以用这个

    var x int32

    fmt.Println(binary.Size(x))

     

    读这篇文章可以了解到这个在网络传输中的具体应用

    golang网络socket粘包解决

    http://www.dotcoo.com/golang-socket-visio-packet

    声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权

    golang 数组引用传递的坑

    Continue Read..

    最近看go调用函数时传引用的问题,看起来和其他语言一样的,测试的时候发现还是有区别的,

    func main() {
    	var box []int = []int{0, 1, 2}
    
    	t(&box)
    	fmt.Println(box)
    }
    
    func t(b *[]int) {
    	fmt.Println(*b, *b[1])
    	//b[1] = 8
    }
    出现错误提示:

    invalid operation: b[1] (type *[]int does not support indexing)

    类型*[]int不支持索引,因为*b是地址,将*b[1]改为&b,

    可以看到真实的地址 0xc082026018

     

    func main() {
    	var box []int = []int{0, 1, 2}
    
    	t(box)
    	fmt.Println(box)
    }
    
    func t(b []int) {
    	fmt.Println(b)
    	b[1] = 8
    }

    打印出来结果是

    [0 1 2]
    [0 8 2]

    发现函数里面的复制操作影响到了全局变量,但是我们并没有传引用b &[]int啊,找了一会发现了问题

    http://stackoverflow.com/questions/2439453/go-using-a-pointer-to-array

    我们传[]或[]int之类的不定长度空数组时,实际上就是传的引用地址,

    我们将数组改为定长的在试试

    func main() {
    	var box [3]int = [3]int{0, 1, 2}
    
    	t(box)
    	fmt.Println(box)
    }
    
    func t(b [3]int) {
    	fmt.Println(b)
    	b[1] = 8
    }

    结果输出

    [0 1 2]
    [0 1 2]

    正常了,现在传递的是copy的副本

    在试试传引用,函数内存改变值

    func main() {
    	var box [3]int = [3]int{0, 1, 2}
    
    	t(&box)
    	fmt.Println(box)
    }
    
    func t(b *[3]int) {
    	fmt.Println(b)
    	b[1] = 8
    }
    输出
    &[0 1 2]
    [0 8 2]

    结论:

    传[]或[]int之类的不定长度空数组时,实际上就是传的引用地址,

    传递一个数组引用到函数里的时候,go会生成一个切片并传递切片进去。

     

     

    声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权

    golang在windows平台使用zmq

    Continue Read..

    zmq官方推荐的golang库,guthub地址是http://github.com\pebbe\zmq4

    测试代码就不发了,上面的地址有具体示例,

    前几天碰到的问题是在windows 7 64位系统环境下go get github.com\pebbe\zmq4的时候无法完成

    最开始可能是提示SOCKET未定义,

    查看这个包的代码可以发现这套库使用了cgo,这是需要gcc等一些环境支持了

     

    不推荐cygwin,因为我测试的时候,在这套环境下仍然无法编译成功

    这时需要安装mingw,注意系统是32还是64的,一定要安装对应的版本,否则无法编译成功

     

    环境装好后编译,再报错找不到zmq.h

    去zmq安装目录\include文件夹下复制.h头文件

    放到mingw64\lib\gcc\x86_64-w64-mingw32\4.9.1\include文件夹下,

    目录可能不同,只要在mingw安装目录搜索.h文件,查看目录就知道了

     

    再次编译报错,提示

    ld.exe cannot find -lzmq

    这是缺少zmq库的意思,去zmq安装目录/lib文件夹下

    复制libzmq-v120-mt-gd-4_0_4.lib到mingw64\x86_64-w64-mingw32\lib目录下

    改名为zmq.lib即可

    zmq安装目录lib文件夹下有好多个lib,具体使用哪一个zmq官方网站有说明.

    请见http://zeromq.org/distro:microsoft-windows

     

    再次编译,即可成功,

    在%GOPATH%\pkg\windows_amd64\github.com\pebbe目录下就能看到编译好的zmq4.a文件了

    声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权

    微软几个bing 的golang代码

    Continue Read..

    题目链接http://hero.csdn.net/Question/Details?ID=215&ExamID=210

    题目详情

        本届大赛由微软必应词典冠名,必应词典(http://cn.bing.com/dict/?form=BDVSP4&mkt=zh-CN&setlang=ZH)是微软推出的新一代英语学习引擎,里面收录了很多我们常见的单词。但现实生活中,我们也经常能看到一些毫无规则的字符串,导致词典无法正常收录,不过,我们是否可以从无规则的字符串中提取出正规的单词呢?

       例如有一个字符串"iinbinbing",截取不同位置的字符‘b’、‘i’、‘n’、‘g’组合成单词"bing"。若从1开始计数的话,则‘b’ ‘i’ ‘n’ ‘g’这4个字母出现的位置分别为(4,5,6,10) (4,5,9,10),(4,8,9,10)和(7,8,9,10),故总共可以组合成4个单词”bing“。

      咱们的问题是:现给定任意字符串,只包含小写‘b’ ‘i’ ‘n’ ‘g’这4种字母,请问一共能组合成多少个单词bing?

      字符串长度不超过10000,由于结果可能比较大,请输出对10^9 + 7取余数之后的结果。

    最常想到的就是4个循环的解法,但是效率不高

    代码如下

    package main
    
    import (
    	"fmt"
    	"math/rand"
    	"time"
    )
    
    const (
    	strlen int = 1000
    )
    
    func main() {
    	rand.Seed(time.Now().Unix())
    	bing := []string{"b", "i", "n", "g"}
    	var strAll [strlen]string
    	for i := 0; i < strlen; i++ {
    		strAll[i] = fmt.Sprintf("%s", bing[rand.Intn(len(bing))])
    	}
    	//strAll := [strlen]string{"i", "i", "n", "b", "i", "n", "b", "i", "n", "g", "g"}
    	fmt.Println(strAll)
    
    	var (
    		arr_b, arr_i, arr_n, arr_g []int
    		count                      int64 = 0
    	)
    
    	for i := 0; i < strlen; i++ {
    		if strAll[i] == "b" {
    			arr_b = append(arr_b, i)
    		} else if strAll[i] == "i" {
    			arr_i = append(arr_i, i)
    		} else if strAll[i] == "n" {
    			arr_n = append(arr_n, i)
    		} else if strAll[i] == "g" {
    			arr_g = append(arr_g, i)
    		}
    	}
    	//fmt.Println(arr_b, arr_i, arr_n, arr_g)
    
    	for i := 0; i < len(arr_b); i++ {
    		for j := 0; j < len(arr_i); j++ {
    			for k := 0; k < len(arr_n); k++ {
    				for h := 0; h < len(arr_g); h++ {
    					if arr_b[i] < arr_i[j] && arr_i[j] < arr_n[k] && arr_n[k] < arr_g[h] {
    						//fmt.Println(arr_b[i]+1, arr_i[j]+1, arr_n[k]+1, arr_g[h]+1)
    						count++
    					}
    				}
    			}
    		}
    	}
    	fmt.Println(count % 1000000007)
    }

    1000个的时候就要3-5秒了,太慢

    下面2个链接是别人的就讲解

    http://www.cnblogs.com/muzihai1988/p/3500383.html

    http://www.cnblogs.com/WhyEngine/p/3522309.html

    声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权

    golang hmac的sha1加密例子

    Continue Read..

    想要用go写btcchina平台的接口,api加密形式在php中是hash_hmac('sha1',$string,$key);

    go中的一样有hmac包,下面是代码

    package main
    
    import (
    	"crypto/hmac"
    	"crypto/sha1"
    	"fmt"
    	"io"
    )
    
    func main() {
    	//sha1
    	h := sha1.New()
    	io.WriteString(h, "aaaaaa")
    	fmt.Printf("%x\n", h.Sum(nil))
    
    	//hmac ,use sha1
    	key := []byte("123456")
    	mac := hmac.New(sha1.New, key)
    	mac.Write([]byte("aaaaaa"))
    	fmt.Printf("%x\n", mac.Sum(nil))
    }


    声明:此文系舞林cuznwww.wulinlw.org)原创稿件,转载请保留版权