在上一章中,我们探索了在web应用中如何处理URLS和指引他们转到不同的页面.同时,我们通过net/http中的handle创建了动态的链接和动态的结果.
通过实现和扩展Gorilla toolkit的mux路由,我们通过正则表达式扩展了路由的能力,使其给予我们的应用更大的灵活性.
其实这是一些最流行的web服务器的特性.比如说Apache和Nginx都在路由中提供了方法去解析正则表达式.
但是这仅仅是构成web应用的基石.为了更加深入,我们需要去看看如何引入数据.
前一章的例子中静态文件服务依赖于硬编码,这显然是过时的且难以控制的.
但是幸运的是,从90年代末期开始,网站变得动态化,数据库开始统治世界.虽然APIs,微服务和NoSQL在某些领域替代了这些架构,但是这个架构在当今的Web开发中还是万金油的角色.
所以,事不宜迟,让我们开始获取一些动态数据
在这一章中,我们将学习以下几个主题
连接数据库 使用GUID美化URLs 处理404页面 连接一个数据库 为了连接数据库,Go的SQL接口提供了一个非常简单且可信赖的方式去连接拥有驱动的不同种类的数据库服务器.
目前,大部分流行的数据库都支持-MySQL,Postgres,SQLite,MSSQL和相当多的实现了Go提供的database/sql接口的数据库驱动.
Note:在本书中,我们将会把MySQL和Postgres数据库使用最好的实践运用在多个例子上.安装MySQL和Postgres在Nix,Windows,OS X 系统的机器上是相当基础的工作
创建MySQL数据库 你可以选择设计任何你想要的应用,但是在这些例子中,我们将着手一个非常的简单的博客.
我们的目标是尽可能地在数据库中创建一些博客的入口,最好可以使用GUID在数据库中直接地获取数据和展示,如果博客的入口不存在,将展示错误页面.
为了实现这个需求,我们将创建一个包含了我们的页面的MySQL数据库.这个数据库将包含一个整数型的,自动递增的ID,一个全局唯一的标识,或者GUID,还有一些博客的初始数据.
简单起见,我们创建一个叫存储标题的page_title字段,存储页面内容的page_content字段,还有一个使用Unix时间戳的字段page_date.
CREATETABLE `pages` ( `id` int(11) unsignedNOT NULL AUTO_INCREMENT, `page_guid` varchar(256)NOT NULLDEFAULT '', `page_title` varchar(256)DEFAULT NULL, `page_content` mediumtext, `page_date`timestampNOT NULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP, PRIMARYKEY (`id`), UNIQUEKEY `page_guid` (`page_guid`) )ENGINE=InnoDB AUTO_INCREMENT=2DEFAULTCHARSET=utf-8; 将page_guid标记为UNIQUE_KEY相当重要,如果我们允许出现重复的page_guid,在浏览某个网址的时候可能出现不准确的情况. 我们使用以下的语句插入一些blog数据
INSERTINTO `pages` (`id`, `page_guid`, `page_title`, `page_content`, `page_date`)VALUES (NULL, 'hello-world', 'Hello, World', 'I\'m so glad you found this page! It\'s been sitting patiently on the Internet for some time, just waiting for a visitor.',CURRENT_TIMESTAMP); 执行了上面的语句之后,我们就获得了初始数据 使用下面的代码来获得连接数据库的能力
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "log" ) 我们导入MySQL驱动包来完成需求.通常,这意味着驱动是另一个包的实现.你能注意到使用 符号来导入包.你可能已经熟悉这点,作为一种快速且脏的方式去忽略类的实例的返回值.比如说x, :=something() 允许你去忽略第二个返回值.这经常也被开发者用在计划去使用一个库,但是目前还没有用到的情况.通过这种方式准备包,它允许导入声明而不引起编译期报错.虽然这不是推荐的做法,但是在预载入方法中使用下划线_或者空白标识符,好处是这是很常见的做法也普遍被接受. 其实,这全部依赖于你怎样以及为何使用标识符.
const ( DBHost = "127.0.0.1" DBPort = ":3306" DBUser = "root" DBPass = "password!" DBDbase = "cms" ) 记得使用你自己的配置去替换以上值
...