go语言 实现mysql协议_Go语言实现的简单TCP服务及使用MySql

本文介绍了如何使用Go语言实现一个简单的TCP服务器以及如何在Go中使用MySQL数据库。首先展示了两个Go语言实现的TCP服务示例,包括监听与接受连接,以及处理客户端消息。接着,文章讲解了如何安装和使用MySQL的Go语言驱动mymysql,并提供了查询用户信息的示例代码。此外,还探讨了Go的sql包与database/driver包在数据库操作中的作用,强调了它们之间的接口和职责分离。
摘要由CSDN通过智能技术生成

转自:http://www.sharejs.com/codes/go/5997

http://www.sharejs.com/codes/go/4363 1、GO语言实现的简单TCP服务代码

package main

import (

"net"

"fmt"

)

var ( maxRead = 1100

msgStop = []byte("cmdStop")

msgStart = []byte("cmdContinue")

)

func main() {

hostAndPort := "localhost:54321"

listener := initServer(hostAndPort)

for {

conn, err := listener.Accept()

checkError(err, "Accept: ")

go connectionHandler(conn)

}

}

func initServer(hostAndPort string) *net.TCPListener {

serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)

checkError(err, "Resolving address:port failed: '" + hostAndPort + "'")

listener, err := net.ListenTCP("tcp", serverAddr)

checkError(err, "ListenTCP: ")

println("Listening to: ", listener.Addr().String())

return listener

}

func connectionHandler(conn net.Conn) {

connFrom := conn.RemoteAddr().String()

println("Connection from: ", connFrom)

talktoclients(conn)

for {

var ibuf []byte = make([]byte, maxRead + 1)

length, err := conn.Read(ibuf[0:maxRead])

ibuf[maxRead] = 0 // to prevent overflow

switch err {

case nil:

handleMsg(length, err, ibuf)

default:

goto DISCONNECT

}

}

DISCONNECT:

err := conn.Close()

println("Closed connection:" , connFrom)

checkError(err, "Close:" )

}

func talktoclients(to net.Conn) {

wrote, err := to.Write(msgStart)

checkError(err, "Write: wrote " + string(wrote) + " bytes.")

}

func handleMsg(length int, err error, msg []byte) {

if length > 0 {

for i := 0; ; i++ {

if msg[i] == 0 {

break

}

}

fmt.Printf("Received data: %v", string(msg[0:length]))

fmt.Println(" length:",length)

}

}

func checkError(error error, info string) {

if error != nil {

panic("ERROR: " + info + " " + error.Error()) // terminate program

}

}

例2 、

下面先创建一个简单的Server端:

package main

import (

"net"

"fmt"

)

func main() {

if ln, err := net.Listen("tcp", ":8080"); err == nil {

defer ln.Close()

for{

ln.Accept()

fmt.Println("Receive a Message")

}

}

}

和脚本一样简单的写法。

先net.Listen(), 第一个参数是协议,tcp还是udp,第二个参数是ip地址,这里可以不填写IP只填写端口就是

使用defer 来Close,将close写在listen之后是个好习惯

然后再循环中使用Accept()接受消息

下面是一个可以进行压力测试的客户端程序

package main

import (

"net"

"fmt"

)

func main() {

currency := 20 //并发数,记住,一个连接数是打开一个端口号,window和linux的端口号都是有限制的

count := 10 //每条连接发送多少次连接

for i:=0;i

go func(){

for j:=0;j

sendMessage()

}

}()

}

select{}

}

func sendMessage() {

conn, err := net.Dial("tcp", "127.0.0.1:8080")

if(err != nil) {

panic("error")

}

header := "GET / HTTP/1.0\r\n\r\n"

fmt.Fprintf(conn, header)

}

2、Go语言中使用MySql

首先安装mysql的go语言驱动

go get github.com/ziutek/mymysql/godrv

演示代码

package users

import (

"database/sql"

"fmt"

_ "github.com/ziutek/mymysql/godrv"

)

const (

DB_NAME = "mysql_database_name"

DB_USER = "mysql_user"

DB_PASS = "mysql_password"

)

type User struct {

Id int `json:"id"`

Name string `json:"name"`

Alias string `json:"alias"`

}

func OpenDB() *sql.DB {

db, err := sql.Open("mymysql", fmt.Sprintf("%s/%s/%s", DB_NAME, DB_USER, DB_PASS))

if err != nil {

panic(err)

}

return db

}

func UserById(id int) User {

db := OpenDB()

defer db.Close()

row := db.QueryRow("SELECT `id`, `name`,`alias` FROM `users` WHERE id=?", id)

user := new(User)

row.Scan(&user.Id, &user.Name, &user.Alias)

return user

}

例2:

go的sql包是在pkg/database中,里面的两个包sql和sql/driver可以一起看。建议看这个两个包之前可以先看看sql文件夹下的doc.txt。这个文档说了几点比较重要的:

1 这两个包是真正Go风格的包。

2 这使用这两个包就不需要关于并发处理了,也不需要维护自己的数据库连接池了,一旦建立了一个连接,这个连接是可以在各个goroutine之间共用的。

3 sql/driver提供的是数据库的接口,具体的实现还需要自己实现。

一、先看database/driver包

第一个用到的方法是Register

这个方法将实现了driver.Driver的驱动注册到变量drivers中,当写完一个驱动之后,就需要将驱动注册到sql中才能使用sql包中的这些接口。这个实现了driver.Driver的必须实现了Open方法.

driver.Open返回的是driver.Conn,它的三个方法

Prepare : 参数绑定

Close : 关闭连接

Begin : 支持事务

先看Prepare,这个和php mysql pdo一样的用法

Conn.Prepare("select * from test where a=?")

返回的Stmt结构:

Close : 关闭这个statement

NumInput : 返回有多少个可以绑定的参数

Exec : Insert或者update等无返回的使用

Query :select等查询操作使用

Exec是绑定变量,然后返回Result结构

Query是绑定变量,然后返回Rows结果集

看Result里面的方法:

LastInsertId()  : Insert操作之后获取到的主键id

RowsAffect() : 影响到的行数

Rows:

Columns() : 返回的数据有哪些列,其实就是返回的表列名

Close() : 关闭Rows,调用之后不能再进行任何操作

Next() : 将下一行的数据取到des[] Value中。这里的Value接口可以是int64,float64,bool,[]byte,string,time.Time

下面回到Begin,返回了Tx

开始事务之后除了查询之外,就两种行为:Commit和Rollback,这两种行为都是Tx接口的方法

drvier中的结构全是接口性质的,它需要你来实现并注册到Register中。

二、驱动的具体使用是在database/sql中

首先将几个sql的结构看一遍

首先sql中的结构都是对driver中的结构进行了一层封装,比如像Rows,有个内部属性是rowsi driver.Rows。

对sql的实际操作都是使用driver.Rows里面的接口进行操作的,实际也就是使用你自己实现的driver进行操作。

driver和sql就像插头和一个充满插头的汽车一样,你实现了driver,即实现了这些插头的配置,你就可使用sql这个汽车了。

Result : 和driver中的Result一致,即你如果实现了driver.Result,那你自然就实现了sql.Result。它是个接口,其实没有什么特殊的用处,如果sql包中的所有Result都换成driver.Result也是行的,估计是作者希望返回值不要引用到其他包去,就使用这种方法。

Rows :  基于了driver.Rows, 还在上面扩展了几个其他的方法。拥有方法:

Close

Cloumns

Err

Next

Scan

Stmt :基于driver.Stmt。拥有方法

Close

Exec

Query

QueryRow

Tx:基于driver.Tx。拥有方法:

Commit

Exec

Prepare

Query

QueryRow

Rollback

Stmt

从sql.Open开始

返回了sql.DB结构,这个结构是实现了driver.Conn结构,除了Conn已有的Prepare,Begin,Close之外,还直接多了几个查询方法:

Driver() : 返回当前驱动

Exec() : 直接进行操作

Query() : 进行查询,返回Rows

QueryRow() : 预期返回单行,返回Row

不管Rows还是Row都有个很好用的方法Scan来将数据放到制定的变量中去。

比如下面就是典型的Rows用法

rows, err := db.Query("SELECT ...")

...

for rows.Next() {

var id int

var name string

err = rows.Scan(&id, &name)

...

}

Prepare返回Stmt结构

Exec返回Result结构

至于这几个结构也有各自的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值