MIT6.5830 Lab0-Go tutorial实验记录(二) – WhiteNight's Site
在将数据库的数据转换为图表前,我们需要先测试是否能正常访问数据库文件。
写者注
为什么要怎么做?因为这块 非常容易出问题。在handlers中需要我们连接至数据库,并将数据转换为图片呈现在前端的html页面上。
问题在于这里各种报错原因都有,而且在lab0原本的代码上进行调试非常折磨,断点经常要打上一堆。但是由于我是先做完实验,再写的实验报告,所以实验过程中有很多图没截下来。这里只能提供一个大致思路理解了。
实验步骤
新建go项目以测试链接
新建一个go项目,只需要有一个main.go即可。
打开main.go。现在我们需要先试着访问数据库文件。
自己编写也可以,这里我选择用lab0中sqlite_ridership_db中的SQL来做测试。SQL语句很显眼,所以还是不难找的。
先把SQL语句写好,其他的功能待会再补齐。
package main
import (
_ "github.com/mattn/go-sqlite3"
)
func main() {
query := `
SELECT SUM(total_ons)
FROM rail_ridership
WHERE season = 'Fall 2017'
AND time_period_id NOT IN ('time_period_10', 'time_period_11')
AND line_id = ?
GROUP BY time_period_id
ORDER BY time_period_id;
`
}
“github.com/mattn/go-sqlite3”这东西是一个数据库驱动的包,导入它之后就可以通过GO对sqlite数据库进行操作了。
db, err := sql.Open("sqlite3", "建议使用数据库文件的绝对路径")
if err != nil {
log.Fatal(err)
}
defer db.Close()
//要养成打开数据库后关闭链接的习惯
此时你的main.go代码应该如下
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", "c:/Users/LENOVO/Desktop/template/testgo/mbta.sqlite")
if err != nil {
log.Fatal(err)
}
defer db.Close()
query := `
SELECT SUM(total_ons)
FROM rail_ridership
WHERE season = 'Fall 2017'
AND time_period_id NOT IN ('time_period_10', 'time_period_11')
AND line_id = ?
GROUP BY time_period_id
ORDER BY time_period_id;
`
}
接下来对db执行些操作才能知道到底有没有成功连接,我们先看看原本在lab0中这个SQL起什么作用。
可以看到,在lab0中Query传入了两个参数。前者我我们要执行的SELECT查询SQL语句。后者则为一个string类型的字符串。
而这个lineId会作为参数传入SQL语句中的”AND line_id =? “中,相当于是”AND line_id=lineId“.
但我们测试总不能也直接用lineId,我们得自己指定lineId=xxxxx。不过这个lineId…没说明是什么,只知道它可能是xx线路的id。但是这个id到底是什么格式,没打注释。那只能翻翻代码看看是啥意思。我们先看看它的定义
还是没说lineId是什么,但我们从这个函数大概能推断出:GetRidership( )接收string类型的 lineId,并返回一个int类型的切片和error。
我们在文件中搜索lineId试试。此时在ridersihp_db_test中我们找到了lineIds
还是没说它是干什么的,但我们知道了lineId应该和这四种颜色有关。我们推测lineId应该就是xxx地铁线路所代表的颜色。
实验步骤
navicat打开数据库文件mbta.sqlite
为了验证lineId和颜色有关,我们查看一下数据库结构。这里使用navicat打开mbta.sqlite。
看到有个lines,还有个rail_ridership,那么会不会lineId表示的是不同地铁线路所表示的颜色呢?但咱对波士顿也没什么了解,波士顿的地铁有几号线,不知道;xx号线用什么颜色表示,不知道。不过不知道也不重要,我们打开lines看看
很明显了,line_id就应该表示的是xx号线,即“x号线的id”。
写者注
做这步只是为了更好的了解自己这次实验到底是在干什么,方便我们后面编写Handlers的具体函数。
实验步骤
补全测试代码
那我们直接假设要查询“red line”这条线路的乘客量。那么把lab0中代码复制过来,再把lineId改成“red”试试,能获取到数据就说明连接是成功的。
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", "c:/Users/LENOVO/Desktop/template/testgo/mbta.sqlite")
if err != nil {
log.Fatal(err)
}
defer db.Close()
query := `
SELECT SUM(total_ons)
FROM rail_ridership
WHERE season = 'Fall 2017'
AND time_period_id NOT IN ('time_period_10', 'time_period_11')
AND line_id = ?
GROUP BY time_period_id
ORDER BY time_period_id;
`
rows, err := db.Query(query, "green")
defer rows.Close() //别忘了关闭连接
fmt.Print(rows)
}
在fmt.Print(rows)那打个断点,方便我们查看变量的情况。调试一下,得到变量信息
error为nil,说明连接过程没出现报错。rows也不为nil,说明rows确实获取到了数据库的数据。
附录
报错原因
在Lab0“连接至数据库”前,你需要确保以下几点:
- 你电脑有安装gcc,cmd输入gcc -v能显示版本信息。
- 这是因为sqlite本身的源代码是c编写的。所以要和go一起用的话需要本地有c语言的编译环境。
- mbta.sqlite有读写权限。
- 由于mbta.sqlite这个文件是你自己下载下来的。如果你用的是linux,该文件很有可能默认没有读写权限,建议给mbta.sqlite所在的文件夹直接chmod加上权限。如果用的是windows,右键mbta.sqlite打开属性,你大概率会发现该文件提示已被锁定。解除锁定即可。
- 对于windows,上面这个操作如果最后还是拿不到数据库的数据,cmd输入
cacls c:/xxx/database /e /t /g everyone:F 。将数据库所在的文件夹设置为所有人可写。应该就能解决问题了。
在测试用的main.go调试的时候,起码err必须是nil。rows之类的得根据你自己编写的SQL语句来看,如果是按Lab0给的实验代码,最后rows不能是nil。如果rows是nil的话只能根据error的信息自己慢慢查报错原因了。
写者注
多打断点多调试,理解代码后在几个go文件里找可能会出错的地方打上断点。我自己光是连接数据库这块打断点+调试就花了一个下午。