go语言连接云服务器上的mysql

最近学golang不久,跟着b站学gin框架,需要使用mysql,B站的教程里是装在本地的,然而我把mysql装在云服务器上了。于是我就有了一个小需求:通过go连接我在阿里云服务器上mysql,

本来以为只是一个简单的小功能,没想到花了一天,找了很多资料,踩了很多坑,费老大劲才找到方法。

在csdn、博客园、知乎等中文网站找了大半天,一方面是go相对比较新兴,资料比较少,二是有跟我一样需求的人好像不多,三是中文互联网环境简直就是垃圾桶了,你抄我我抄你,找半天没点靠谱的答案。

然后用英文搜索,发现好像国外的文章也不多。。。。

最后还是在github找到了答案。

github连接(需要特殊方式上网):Using MySQL / MariaDB via SSH in Golang

希望这文章能帮到后来者。

本来发在其它地方的,结果被锁了,就暂且发在csdn了。


进入正题

一、整体思路

首先,你无法直接连接到远程服务器上的mysql,而是需要使用ssh登录到远程服务器上,然后再登录MySQL进行操作。

二、go实现ssh登录

go使用ssh包的教程在中文环境下还是能找到很多的,百度一搜就一大堆,本文也不是专门讲ssh包的教程。

首先需要import ssh包:(没有下载的话去百度一下下载方式吧)


import "golang.org/x/crypto/ssh"

ssh.Dial 函数原型如下:

func Dial(network string, addr string, config *ClientConfig) (*Client, error)

传入参数:

network: 网络协议,这里使用tcp
addr: IP地址+端口号。Ip就是你远程服务器的IP,因为是ssh远程登录,所以端口号是22
config: 登录需要的信息,如用户名、密码、验证等。

返回的是一个Client对象的指针

编写代码:

	// 一个ClientConfig指针,指向的对象需要包含ssh登录的信息
	config := &ssh.ClientConfig{
		User: "你的用户名", //我使用的是root用户,就写"root"
		Auth: []ssh.AuthMethod{
			ssh.Password("你的密码"),//用户的密码
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),//这个我也不太清楚,大概是做服务端验证的,按这么写就行
	}

	client,err:=ssh.Dial("tcp", "xxx.xxx.xxx.xxx:22",config) //xxx那段替换为你服务器的的IP地址
	if err != nil {
		panic("连接失败")//抛出异常
	}

三、操作mysql

我这里先使用 github.com/go-sql-driver/mysql 的mysql驱动包,

import "github.com/go-sql-driver/mysql"
import "database/sql"

如果没有安装的话,可以使用go get命令安装

go get github.com/go-sql-driver/mysql
重点步骤

定义一个结构体:包含一个 ssh.Client 指针,以及一个成员函数Dial

import "context"
import "net"

type ViaSSHDialer struct {
	client *ssh.Client
}
func (self *ViaSSHDialer) Dial(context context.Context, addr string) (net.Conn, error) {
	return self.client.Dial("tcp", addr)
}

现在我们用ssh连接(即client指针)作为参数注册ViaSSHDialer

mysql.RegisterDialContext("mysql+tcp", (&ViaSSHDialer{client}).Dial)

现在,就可以通过SSH连接使用常规的mysql命令

现在需要使用sql.Open连接mysql

函数原型:

func Open(driverName string, dataSourceName string) (*DB, error)

第一个参数driverName填写为"mysql"即可,

第二个参数是DSN,它是一个字符串,可以简单理解为连接数据库所需的参数,如用户名、密码、端口、数据库名等信息,参考格式如下:

dsn:="用户名:密码@mysql+tcp(127.0.0.1:3306)/数据库名?charset=utf8&parseTime=True"
用户名、密码、数据库名替换为你自己的。
127.0.0.1也可以替换为localhost,3306就是mysql的默认端口号,charset是设置字符集

比如我的数据库叫myDB,使用root登录,可以写成如下:

dsn:="root:password@mysql+tcp(127.0.0.1:3306)/myDB?charset=utf8&parseTime=True"

db,err:=sql.Open("mysql", dsn);
if err!=nil{
	panic("连接失败")
}
fmt.Println("成功连接到mysql")

我的myDB数据库中有以下表:
image.png
其中book的内容如下:
image.png

使用sql语句查询book表、并打印

if rows, err := db.Query("SELECT id, name FROM book"); err == nil {
  // 使用循环,打印出查询的内容
	for rows.Next() {
		var id int64
		var name string
		rows.Scan(&id, &name)
		fmt.Printf("ID: %d  Name: %s\n", id, name)
	}
	rows.Close()
} else {
	fmt.Printf("查询失败: %s", err.Error())
}

db.Close()

运行结果:(当时那个感动啊)
image.png

完整的参考代码:

package main

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/go-sql-driver/mysql"
	"golang.org/x/crypto/ssh"
	"net"
)

type ViaSSHDialer struct {
	client *ssh.Client
}
func (self *ViaSSHDialer) Dial(context context.Context, addr string) (net.Conn, error) {
	return self.client.Dial("tcp", addr)
}
func main() {
	// 一个ClientConfig指针,指向的对象需要包含ssh登录的信息
	config := &ssh.ClientConfig{
		User: "你的用户名", //我使用的是root用户,就写"root"
		Auth: []ssh.AuthMethod{
			ssh.Password("你的密码"),//用户的密码
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),//这个我也不太清楚,大概是做服务端验证的,按这么写就行
	}

	client,err:=ssh.Dial("tcp", "xxx.xxx.xxx.xxx:22",config) //xxx那段替换为你服务器的的IP地址
	if err != nil {
		panic("连接失败")//抛出异常
	}
	defer client.Close()


	mysql.RegisterDialContext("mysql+tcp", (&ViaSSHDialer{client}).Dial)
	dsn:="用户名:密码@mysql+tcp(127.0.0.1:3306)/数据库名?charset=utf8&parseTime=True"

	db,err:=sql.Open("mysql", dsn);
	if err!=nil{
		panic("连接失败")
	}
	fmt.Println("成功连接到mysql")


	// 查询数据库中的一个表 book
	if rows, err := db.Query("SELECT id, name FROM book"); err == nil {
		// 使用循环,打印出查询的内容
		for rows.Next() {
			var id int64
			var name string
			rows.Scan(&id, &name)
			fmt.Printf("ID: %d  Name: %s\n", id, name)
		}
		rows.Close()
	} else {
		fmt.Printf("查询失败: %s", err.Error())
	}

	db.Close()
}

四、使用gorm操作数据库

除了上述的sql驱动包,还可以使用gorm来连接,也是很简单

前面的步骤一样,说以下不同处:
如果你的表叫做 book,使用gorm 查询时,你需要自定义一个同名(首字母可以忽略大小写的影响)的结构体book,并且该结构体的结构必须和表结构一样。

type Book struct {
    ID   int `gorm:"primary_key" json:"id"`
    Name string `json:"name"`
}

gorm 提供了很多函数进行查询,如查询所有记录:

// 相当于 select *  from books
db.Find(book*)  // book* 是book类型的指针

使用如下:
var results []book  //使用数组存储结果
db.Find(&results)

你可能也注意到
db.Find(book*) 相当于select * from books
而不是 select * from book
所以这里有一个坑,gorm在增删查改时默认会给结构体名加个s,作为表名,导致你操作失败(表不存在)。这一点上gorm的官方文档写的真烂。
解决方法是:

db.SingularTable(true)
import "github.com/jinzhu/gorm"

//需要定义一个结构体,其名字与你要操作的表的名称一样,表结构也必须一样
type Book struct {
	ID   int `gorm:"primary_key" json:"id"`
	Name string `json:"name"`
}

func main(){
  //... 前面相同的代码省略
  dsn:="用户名:密码@mysql+tcp(127.0.0.1:3306)/数据库名?charset=utf8&parseTime=True"
  db,err:= gorm.Open("mysql", dsn)

	//  gorm会自动在表名后面加个s,如你的结构体名是book,它就把你变成books
	// 使用下面这个函数可以屏蔽自动加s的功能
	db.SingularTable(true)

	if err != nil {
		panic("连接失败")
	}

// 使用数组存储查询结果
	var Books []Book
	//相当于 select * from book
	db.Find(&Books)

	for _,book:=range Books{
		fmt.Printf("ID: %d  Name: %s\n", book.ID, book.Name)
	}

    // 增加一条记录
	//var b1=book{110,"j"}
	//db.Create(&b1)
	db.Close()
}

运行结果:
image.png

还有其它的增删改等操作也是类似的,百度一下即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值