zoukankan      html  css  js  c++  java
  • go-mysql

    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<currency;i++ {
            go func(){
                for j:=0;j<count;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
    
    "
        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中,里面的两个包sqlsql/driver可以一起看。建议看这个两个包之前可以先看看sql文件夹下的doc.txt。这个文档说了几点比较重要的:

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

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

    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结构

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

  • 相关阅读:
    Scala进阶之路-idea下进行spark编程
    Scala进阶之路-Spark本地模式搭建
    Scala进阶之路-Scala高级语法之隐式(implicit)详解
    Scala进阶之路-Spark底层通信小案例
    Scala进阶之路-并发编程模型Akka入门篇
    Scala进阶之路-统计商家id的标签数以及TopN示例案例分析
    Scala进阶之路-Scala中的泛型介绍
    Scala进阶之路-尾递归优化
    Scala进阶之路-Scala特征类与unapply反向抽取
    Java基础-爬虫实战之爬去校花网网站内容
  • 原文地址:https://www.cnblogs.com/zhangym/p/5583221.html
Copyright © 2011-2022 走看看