如何使用Go连接到MySQL?

5
我一直在尝试使用go连接mysql,但似乎没有成功。我只是想从表中获取一个值,将其设置为变量并打印出来。我可能缺少的只是一些显而易见的东西。
这是来自名为bankdata的数据库的内容。
mysql> select * from accounts ;
+----+----------+-----------------+----------+---------+
| id | username | email           | facebook | twitter |
+----+----------+-----------------+----------+---------+
|  1 | user1    | email1@mail.com | userfb1  | NULL    |
|  2 | user2    | email2@mail.com | NULL     | NULL    |
|  3 | user3    | email3@mail.com | NULL     | NULL    |
+----+----------+-----------------+----------+---------+

我使用了两个驱动程序,但似乎都有问题。

其中一个是使用go-sql-driver

package main

import (
    "database/sql"
    _ "github.com/Go-SQL-Driver/MySQL"
    "log"
)

const (
    DB_HOST = "tcp(127.0.0.1:3306)"
    DB_NAME = "bankdata"
    DB_USER = /*"root"*/ "bankadmin"
    DB_PASS = /*""*/ "1234"
)

func main() {
    dsn := DB_USER + ":" + DB_PASS + "@" + DB_HOST + "/" + DB_NAME + "?charset=utf8"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    var str string
    q := "select username from bankadmin.accounts where id = 1"
    err = db.QueryRow(q).Scan(&str)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(str)
}

这将返回

D:\_>go run dbtest.go
2013/03/29 13:14:11 Error 1045: Access denied for user 'bankadmin'@'localhost'
(using password: YES)
exit status 1

实际上,无论是root用户还是bankadmin用户,密码都是正确的,并且mysql运行在3306端口。但是,如果我将DB_HOST更改为"tcp(127.0.0.1:3000)"或将127.0.0.1更改为localhost,它仍然会给我相同的错误。

使用mymysql驱动程序

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/ziutek/mymysql/godrv"
    "log"
    "strconv"
)

const (
    DB_HOST = "tcp(127.0.0.1:3306)"
    DB_NAME = "bankdata"
    DB_USER = "bankadmin"
    DB_PASS = "1234"
)

type User struct {
    Id       int    
    Username string 
    Email    string 
    Facebook string
}

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)
        log.Fatal(err)
    }
    return db
}

func UserById(id int) *User {
    db := OpenDB()
    defer db.Close()
    row := db.QueryRow("SELECT id, username, email FROM accounts WHERE id=?", id)
    user := new(User)
    row.Scan(&user.Id, &user.Username, &user.Email, &user.Facebook)
    return user
}

func main() {
    db := OpenDB()
    defer db.Close()
    row := db.QueryRow("SELECT id, username, email, facebook FROM accounts WHERE id=2")
    user := new(User)
    row.Scan(&user.Id, &user.Username, &user.Email, &user.Facebook)
    fmt.Println("id    : " + strconv.Itoa(user.Id) + "\nname  : " + user.Username + "\nemail : \n" + user.Email)

}

这会返回:

D:\_>go run dbtest.go
id    : 0
name  :
email :

看起来id和字符串都是空的,就像从row.Scan函数中没有接收到任何值一样。我不知道如何确保它们连接,即使它们没有给我与之前的驱动程序相同的错误。

哦,我正在使用Windows 7,带有WAMP的MySQL 5.5.8。

如果我在这篇文章中犯了任何错误,请原谅我。这是我的第一篇文章。


请确保您的用户名为bankadmin,密码为1234。 - hodl
以下是MySQL命令行中的内容:mysql> drop database if exists bankdata; 查询 OK,受影响的行数为1(用时1.28秒)mysql> create database bankdata; 查询 OK,受影响的行数为1(用时0.00秒)mysql> grant all privileges on bankdata.* to 'bankadmin'@'localhost' identified by '1234'; 查询 OK,受影响的行数为0(用时0.09秒)mysql> flush privileges; 查询 OK,受影响的行数为0(用时0.12秒)mysql> use bankdata; 已切换到数据库 bankdata - Joni Atif
Go-MySQL-Driver 是否是最新版本? 可能是这个 bug:https://github.com/go-sql-driver/mysql/issues/35 否则,就像 Baron Schwartz 所说: “这是 MySQL 通常存在的一个问题。驱动程序出现问题的概率可能只有 0.01%。请参阅 http://dev.mysql.com/doc/refman/5.1/en/access-denied.html,特别是查看讨论默认权限表中默认权限发生的情况的部分。在您的情况下,您可能在权限表中为用户定义的主机名和用于身份验证的主机名之间存在不匹配。” - Julien Schmidt
请注意,包路径已更改为github.com/go-sql-driver/mysql(全部小写) - Julien Schmidt
2个回答

2

问题不在于您的Go代码,而在于您的MySQL配置。您可能拥有正确的用户名和密码,但很可能没有授权该用户使用TCP连接到数据库。


如何进行配置? - Joni Atif
http://dev.mysql.com/doc/refman/5.1/en/access-denied.html 包含了这个问题的许多可能原因。 - Jeremy Wall

1

enter image description here

正如 @Jeremy wall 提到的那样,问题出在连接字符串上。我使用的用户名是错误的。要配置设置, 1. 转到 "服务器" 选项 2. 选择 "管理服务器连接" 3. 选择 "连接" 部分 4. 在密码部分中单击 "存储密钥链" 按钮并输入新密码

现在您已经完成了。现在尝试测试连接按钮。当我尝试从GO程序访问数据库时,它对我有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接