added translation to chapter 5, thanks to @carlochess for corrections

This commit is contained in:
ma0
2016-12-26 00:27:59 -05:00
parent db61f795b7
commit 3ba339a2c4
6 changed files with 777 additions and 0 deletions

125
es/05.2.md Normal file
View File

@@ -0,0 +1,125 @@
# 5.2 MySQL
La pila LAMP ha sido muy popular en internet los últimos años. La M en LAMP significa MySQL. MySQL es famoso porque es de código abierto y fácil de usar. También porque viene como base de datos por defecto en el backend de muchos sitios web.
## Manejadores MySQL
Existen varios manejadores que soportan MySQL en Go. Algunos de ellos implementan la interfaz `database/sql`, y otros usan sus propias interfaces estándares.
- [https://github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) soporta `database/sql`, está escrita en Go puro.
- [https://github.com/ziutek/mymysql](https://github.com/ziutek/mymysql) soporta `database/sql` e interfaces definidas por el usuario, está escrita en Go puro.
Usaré el primer manejador en los siguientes ejemplos (uso este en mis proyectos personales también) y también lo recomiendo por las siguientes razones:
- Es un manejador de bases de datos nuevo y suporta muchas características
- Soporta completamente la interfaz `database/sql`
- Soporta el keep-alive, conexiones largas con seguridad entre hilos
## Ejemplos
En las siguientes secciones usaré las misma estructura de tablas para diferentes bases de datos, luego crear la base de datos de la siguiente manera:
```
CREATE TABLE `userinfo` (
`uid` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) NULL DEFAULT NULL,
`departname` VARCHAR(64) NULL DEFAULT NULL,
`created` DATE NULL DEFAULT NULL,
PRIMARY KEY (`uid`)
);
```
El siguiente ejemplo muestra como operar en bases de datos con los estándares de `database/sql`.
```
package main
import (
_ "github.com/go-sql-driver/mysql"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("mysql", "astaxie:astaxie@/test?charset=utf8")
checkErr(err)
// insertar
stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")
checkErr(err)
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
// actualizar
stmt, err = db.Prepare("update userinfo set username=? where uid=?")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect)
// consultar
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created string
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
// eliminar
stmt, err = db.Prepare("delete from userinfo where uid=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
Permítanme explicar algunas de las funciones importantes aquí:
- `sql.Open()` abre un manejador de bases de datos registrado. Go-MySQL-Driver registra el manejador de MySQL aquí. El segundo argumento es el DSN (Data Source Name) que define la información para realizar la conexión con la base de datos. Soporta los siguientes formatos:
```
user@unix(/path/to/socket)/dbname?charset=utf8
user:password@tcp(localhost:5555)/dbname?charset=utf8
user:password@/dbname
user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname
```
- `db.Prepare()` retorna la operación que va a ser ejecutada. También reetorna el estado de ejecución después de ejecutar el SQL.
- `db.Query()` ejecuta el SQL y retorna el resultado en Rows
- `stmt.Exec()` ejecuta el SQL que ha sido preparado y almacenado en un Stmt
Note que usamos el formato `=?` para pasar argumentos. Esto es necesario para prevenir ataques de inyección SQL.
## Enlaces
- [Índice](preface.md)
- Sección previa: [Interfaz database/sql](05.1.md)
- Siguiente sección: [SQLite](05.3.md)

149
es/05.3.md Normal file
View File

@@ -0,0 +1,149 @@
# 5.3 SQLite
SQLite es una base de datos embebida de código abierto. Es una base de datos contenida en si misma, tiene 0 configuracieon y soporta transacciones. Es altamente portable, fácil de usar, compacta, eficiente y confiable. En la mayoría de los casos solamente se necesita crear una archivo de base de datos para crear conectarse y operar en una base de datos. Si estás buscando una solución embebida, SQLite es una opción para considerar. Se puede decir que SQLite es una versión de código abierto de Access.
## Manejadores SQLite
Existen muchos manejadores de bases de datos para SQLite en Go, pero muchos de ellos no soportan los estándares de la interfaz `database/sql`.
- [https://github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) soporta `database/sql`, basado en cgo
- [https://github.com/feyeleanor/gosqlite3](https://github.com/feyeleanor/gosqlite3) no soporta `database/sql`, basado en cgo.
- [https://github.com/phf/go-sqlite3](https://github.com/phf/go-sqlite3) no soporta `database/sql`, basado en cgo.
El primer manejador es el único que soporta los estándares de la interfaz `database/sql`, por esto lo uso en mis proyectos, ya que será mas fácil migrar el código en el futuro si lo necesito.
## Ejemplos
Crearemos el siguiente SQL:
```
CREATE TABLE `userinfo` (
`uid` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` VARCHAR(64) NULL,
`departname` VARCHAR(64) NULL,
`created` DATE NULL
);
```
Un ejemplo:
```
package main
import (
"database/sql"
"fmt"
"time"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", "./foo.db")
checkErr(err)
// insertar
stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) values(?,?,?)")
checkErr(err)
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
// actualizar
stmt, err = db.Prepare("update userinfo set username=? where uid=?")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect)
// consultar
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
var uid int
var username string
var department string
var created time.Time
for rows.Next() {
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
rows.Close() // Buen hábito cerrar
// eliminar
stmt, err = db.Prepare("delete from userinfo where uid=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
Puedes notar que el código es casi el mismo que en la sección pasada, y es porque solamente cambiamos el nombre del manejador de bases de datos registrado llamando a `sql.Open` para conectarnos a SQLite de una manera diferente.
Nota que algunas veces no puedes usar la sentencia `for` porque no tienes mas de una fila, entonces puedes usar la sentencia `if`:
```
if rows.Next() {
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
```
También tienes que ahcer un `rows.Next()` sin usar eso que no puedes obtener en la función `Scan`.
Transacciones
=============
El ejemplo de arriba muestra como puedes obtener datos de una base de datos, pero cuando quieres escribir aplicaciones web, no solo vas a consultar información de la base de datos sino que también quieres escribir en ella. Para este propósito tu puedes usar transacciones, porque puedes tener múltiples rutinas que accesan a la base de datos, y la base de datos se podría bloquear. Esto no es deseable en una aplicación web y el uso de transacciones es efectivo asegurando que las operaciones sean exitosas en total o fallen completamente, dependiendo de las circunstancias. Es claro que el uso de transacciones puede prevenir un montón de problemas que pueden ocurrir en una aplicación web.
```
trashSQL, err := database.Prepare("update task set is_deleted='Y',last_modified_at=datetime() where id=?")
if err != nil {
fmt.Println(err)
}
tx, err := database.Begin()
if err != nil {
fmt.Println(err)
}
_, err = tx.Stmt(trashSQL).Exec(id)
if err != nil {
fmt.Println("doing rollback")
tx.Rollback()
} else {
tx.Commit()
}
```
Como es claro en el código de arribam primero debes prepara un Statement, después debes ejecutarlo, dependiendo de la salida de esa ejecución, puedes volver atrás o mantenerlo.
Como última nota de esta sección, aquí está una herramienta de mantenimiento para SQLite: [http://sqlitebrowser.org](http://sqlitebrowser.org)
## Enlaces
- [Índice](preface.md)
- Sección anterior: [MySQL](05.2.md)
- Siguiente sección: [PostgreSQL](05.4.md)

123
es/05.4.md Normal file
View File

@@ -0,0 +1,123 @@
# 5.4 PostgreSQL
PostgreSQL es una base de datos relacional y de objetos disponible en muchas plataformas incluyendo Linux, FreeBSD, Solaris, Microsoft Windows y Mac OS X. Fue liberada bajo la licencia MIT y por eso es gratuita y de código abierto. Es más grande que MySQL porque está diseñada para uso empresarial y es una alternativa a Oracle. PostgreSQL es una buena elección para proyectos empresariales.
## Manejadores PostgreSQL
Existen muchos manejadores de bases de datos para PostgreSQL. Aquí hay algunos ejemplos de ellos:
- [https://github.com/bmizerany/pq](https://github.com/lib/pq) soporta `database/sql`, escrita en Go puro.
- [https://github.com/jbarham/gopgsqldriver](https://github.com/jbarham/gopgsqldriver) soporta `database/sql`, escrita en Go puro
- [https://github.com/lxn/go-pgsql](https://github.com/lxn/go-pgsql) soporta `database/sql`, escrita en Go puro
Usaré el primer ejemplo para explicar lo que sigue.
## Ejemplos
Crearemos el siguiente SQL:
```
CREATE TABLE userinfo
(
uid serial NOT NULL,
username character varying(100) NOT NULL,
departname character varying(500) NOT NULL,
Created date,
CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
)
WITH (OIDS=FALSE);
```
Un ejemplo:
```
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
"time"
)
const (
DB_USER = "postgres"
DB_PASSWORD = "postgres"
DB_NAME = "test"
)
func main() {
dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable",
DB_USER, DB_PASSWORD, DB_NAME)
db, err := sql.Open("postgres", dbinfo)
checkErr(err)
defer db.Close()
fmt.Println("# Inserting values")
var lastInsertId int
err = db.QueryRow("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) returning uid;", "astaxie", "研发部门", "2012-12-09").Scan(&lastInsertId)
checkErr(err)
fmt.Println("last inserted id =", lastInsertId)
fmt.Println("# Updating")
stmt, err := db.Prepare("update userinfo set username=$1 where uid=$2")
checkErr(err)
res, err := stmt.Exec("astaxieupdate", lastInsertId)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect, "rows changed")
fmt.Println("# Querying")
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created time.Time
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println("uid | username | department | created ")
fmt.Printf("%3v | %8v | %6v | %6v\n", uid, username, department, created)
}
fmt.Println("# Deleting")
stmt, err = db.Prepare("delete from userinfo where uid=$1")
checkErr(err)
res, err = stmt.Exec(lastInsertId)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect, "rows changed")
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
Nota que PostgreSQL usa el formato `$1, $2` en vez del `?` de MySQL, y tiene un formato distinto de DSN en el `sql.Open`
Otra cosa es que el manejador de PostgreSQL no soporta el `sql.Result.LastInsertId()`.
Entonces en lugar de
```
stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3);")
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
fmt.Println(res.LastInsertId())
```
usa `db.QueryRow()` y `.Scan()` para obtener el último valor insertado.
```
err = db.QueryRow("INSERT INTO TABLE_NAME values($1) returning uid;", VALUE1").Scan(&lastInsertId)
fmt.Println(lastInsertId)
```
## Enlaces
- [Índice](preface.md)
- Sección anterior : [SQLite](05.3.md)
- Siguiente sección: [Desarrollo de un ORM basado en beedb](05.5.md)

256
es/05.5.md Normal file
View File

@@ -0,0 +1,256 @@
# 5.5 Desarrollo de un ORM basado en beedb
( ***El proyecto beedb no está mantenido actualmente, pero el código sigue ahí*** )
( ***Project beedb is no longer maintained, but the code s still there*** )
beedb es un ORM ( object relational mapper ) desarrollado en Go, por mi.
Usa el lenguaje ideomático de Go para operar con las bases de datos, implementando un mapeo de estructura a base de datos que actua como un Framework ORM liviano de Go. El propósito de desarrollar este ORM no es solamente ayudar a la gente a aprender como implementar un ORM, sino también encontrar un buen balance entre funcionalidad y desempeño en lo que respecta a persistencia de datos.
beedb es un proyecto de código abierto que soporta la funcionalidad básica de un ORM, pero no soporta las consultas asociativas.
Como beedb soporta los estándares de la interfaz `database/sql` cualquier manejador que implemente esta interfaz podrá ser usado con beedb. Yo lo he probado con los siguientes manejadores:
Mysql: [github.com/ziutek/mymysql/godrv](github.com/ziutek/mymysql/godrv)
Mysql: [code.google.com/p/go-mysql-driver](code.google.com/p/go-mysql-driver)
PostgreSQL: [github.com/bmizerany/pq](github.com/bmizerany/pq)
SQLite: [github.com/mattn/go-sqlite3](github.com/mattn/go-sqlite3)
MS ADODB: [github.com/mattn/go-adodb](github.com/mattn/go-adodb)
ODBC: [bitbucket.org/miquella/mgodbc](bitbucket.org/miquella/mgodbc)
## Instalación
Puedes usar el comando `go get` para instalar beedb localmente.
```
go get github.com/astaxie/beedb
```
## Inicialización
Primero debes importar los paquetes necesarios:
```
import (
"database/sql"
"github.com/astaxie/beedb"
_ "github.com/ziutek/mymysql/godrv"
)
```
Luego necesitas abrir la conexión a la base de datos y crear un objeto beedb (MySQL en este ejemplo):
```
db, err := sql.Open("mymysql", "test/xiemengjun/123456")
if err != nil {
panic(err)
}
orm := beedb.New(db)
```
`beedb.New()` actualmente toma dos argumentos. El primero es el objeto de la base de datos y el segundo es para indicar que motor de base de datos estás usando. Si estás usando MySQL o SQLite puedes omitir el segundo argumento.
De otra manera, este argumento debe ser incluido, por ejemplo en el caso de SQLServer:
```
orm = beedb.New(db, "mssql")
```
PostgreSQL:
```
orm = beedb.New(db, "pg")
```
beedb soporta depuración. Usa el siguiente código para habilitarla:
```
beedb.OnDebug=true
```
Después debemos tener una estructura para la tabla `Userinfo` que hemos usado en las secciones anteriores.
```
type Userinfo struct {
Uid int `PK` // Si la llave primaria no es id, necesitas añadir la etiqueta `PK` para una llave primaria personalizada.
Username string
Departname string
Created time.Time
}
```
Se conciente que beedb autoconvierte la notación de camello a notación de guiones bajos. Por ejemplo, si tenemos `UserInfo` como el nombre de la estructura, beedb lo convertirá a `user_info` en la base de datos. La misma regla se aplica para los nombres de campos de la estructura.
## Insertar datos
El siguiente ejemplo muestra como usar beedb a guardar una estructura en vez de usar comandos planos de SQL. Usamos el método `Save` de beedb para aplicar el cambio.
```
var saveone Userinfo
saveone.Username = "Test Add User"
saveone.Departname = "Test Add Departname"
saveone.Created = time.Now()
orm.Save(&saveone)
```
Puedes verificar el campo `saveone.Uid` después de que este registro es insertado; su valor es un identificador autoincrementado por el que el método `Save` se ocupa por ti.
beedb provee otra manera de insertar datos, usando el estilo de mapas de Go.
```
add := make(map[string]interface{})
add["username"] = "astaxie"
add["departname"] = "cloud develop"
add["created"] = "2012-12-02"
orm.SetTable("userinfo").Insert(add)
```
Insertando varios datos:
```
addslice := make([]map[string]interface{}, 10)
add:=make(map[string]interface{})
add2:=make(map[string]interface{})
add["username"] = "astaxie"
add["departname"] = "cloud develop"
add["created"] = "2012-12-02"
add2["username"] = "astaxie2"
add2["departname"] = "cloud develop2"
add2["created"] = "2012-12-02"
addslice = append(addslice, add, add2)
orm.SetTable("userinfo").InsertBatch(addslice)
```
El método mostrado arriba es similar a una consulta encadenada, la cual te podría ser familiar si has usado jQuery. Retorna el objeto del ORM después de la llamada, entonces continua haciendo otros trabajos.
El método `SetTable` le dice al ORM que queremos insertar nuestra data en la tabla `userinfo`.
## Actualizar datos
Continuemos trabajando con el ejemplo de arriba, para ver como actualizar los datos. Ahora que tenemos la llave primeria de `saveone(Uid)`, beedb ejecuta una operación de actualizacieon en lugar de insertar un nuevo registro.
```
saveone.Username = "Update Username"
saveone.Departname = "Update Departname"
saveone.Created = time.Now()
orm.Save(&saveone) // update
```
Como antes, también puedes usar un mapa para actualizar los datos:
```
t := make(map[string]interface{})
t["username"] = "astaxie"
orm.SetTable("userinfo").SetPK("uid").Where(2).Update(t)
```
Permíteme explicar algunos de los métodos usados arriba:
- `.SetPK()` le dice al ORM que `uid` es la llave primaria del registro en la tabla `userinfo`
- `.Where()` define condiciones y suporta múltiples argumentos. Si el primer arguento es un entero, es una manera de acortar `Where("<llave primaria>=?", <valor>)`.
- `.Update()` acepta un mapa y actualiza la base de datos.
## Consultado datos
Las consultas con la interface beedb son muy fleibles. Veamos algunos ejemplos:
Ejemplo 1: Consultando por llaves primarias:
```
var user Userinfo
// Where acepta dos argumentos, el segundo entero
orm.Where("uid=?", 27).Find(&user)
```
Ejemplo 2:
```
var user2 Userinfo
orm.Where(3).Find(&user2) // Forma corta que omite el nombre de la llave primaria
```
Ejemplo 3, otras condiciones de consulta
```
var user3 Userinfo
// Where acepta dos argumentos, el segundo cadena
orm.Where("name = ?", "john").Find(&user3)
```
Ejemplo 4, condiciones mas complicadas:
```
var user4 Userinfo
// Where con tres argumentos aceptados
orm.Where("name = ? and age < ?", "john", 88).Find(&user4)
```
Ejemplos para obtener múltiples registros
Ejemplo 1, Obtiene 10 registros donde `id>3` Que comienzan en la posición 20
```
var allusers []Userinfo
err := orm.Where("id > ?", "3").Limit(10,20).FindAll(&allusers)
```
Ejemplo 2, omite el segundo argumento de límite, entonces comienza en 0 y obtiene 10 registros:
```
var tenusers []Userinfo
err := orm.Where("id > ?", "3").Limit(10).FindAll(&tenusers)
```
Ejemplo 3, obtener todos los recursos:
```
var everyone []Userinfo
err := orm.OrderBy("uid desc,username asc").FindAll(&everyone)
```
Como puedes ver, el método límite es para limitar el número de resultados.
- `.Limit()` suporta dos argumentos: el número de resultados comenzando en la posición. 0 es el valor por defecto de posición inicial.
- `.OrderBy()` es para ordenar resultados. El argumento es la condición de orden.
Todos los ejemplos aquí simplemente mapean registros a estructuras. También puedes colocar data en un mapa como sigue:
```
a, _ := orm.SetTable("userinfo").SetPK("uid").Where(2).Select("uid,username").FindMap()
```
- `.Select()` le dice a beedb cuantos campos quieres obtener desde la tabla de la base de datos. Si no es especifica, todos los registros son retornados por defecto.
- `.FindMap()` retorna el tipo `[]map[String][]byte`, entonces puedes convertir a otros tipos tu mismo.
## Eliminar datos
beedb provee métodos amplios para eliminar datos.
Ejemplo 1, eliminar un único registro
```
// saveone es el mismo del ejemplo anterior.
orm.Delete(&saveone)
```
Ejemplo 2, elimintar todos los usuarios
```
// alluser es un segmento que tiene múltiples usuarios
orm.DeleteAll(&alluser)
```
Ejemplo 3, Eliminar registros con SQL
```
orm.SetTable("userinfo").Where("uid>?", 3).DeleteRow()
```
## Consultas de asociación
beedb no soportar uniones entre asociaciones.
Sin embargo, desde que algunas aplicaciones necesitan esta caractarísticas, aquí está una implementación:
```
a, _ := orm.SetTable("userinfo").Join("LEFT", "userdetail", "userinfo.uid=userdetail.uid")
.Where("userinfo.uid=?", 1).Select("userinfo.uid,userinfo.username,userdetail.profile").FindMap()
```
Nosotros vemos un método llamado `.Join()` que toma tres argumentos
- El primer argumento: Tipo del Join; INNER, LEFT, OUTER, CROSS, etc.
- El segundo argumento: la tabla con la que quieres hacer la unión
- El tercer argumento: la condición de Join
## Group By y Having
beedb también tiene una implementación de `group by` y `having`.
```
a, _ := orm.SetTable("userinfo").GroupBy("username").Having("username='astaxie'").FindMap()
```
- `.GroupBy()` indica el campo con el que se va a agrupar.
- `.Having()` indica la condición del `having`.
## Futuro
He recibido un montón de retroalimentación de beedb de muchas personas al rededor del mundo y estoy pensando en reconfigurar los siguientes aspectos:
- Implementar una interfaz similar a `database/sql/driver` en orden de facilitar las operaciones CRUD
- Implementar asociaciones de bases de datos relacionales como uno a uno, muchos a uno y muchos a muchos.
Aquí hay un ejemplo:
```
type Profile struct {
Nickname string
Mobile string
}
type Userinfo struct {
Uid int
PK_Username string
Departname string
Created time.Time
Profile HasOne
}
```
- Auto crear tablas e indices.
- Implementar una piscina de conexiones usando rutinas.
## Enlaces
- [Índice](preface.md)
- Sección previa: [PostgreSQL](05.4.md)
- Siguiente sección section: [Bases de Datos NoSQL](05.6.md)

113
es/05.6.md Normal file
View File

@@ -0,0 +1,113 @@
# 5.6 Bases de Datos NoSQL
Una base de datos NoSQL provee un mecanismo para el almacenamiento y el retorno de información que usa modelos de consistencia menores que bases de datos relacionales en orden de alcanzar escalabilidad horizontal y mayor disponibilidad. Alguns autores se refieren a ellas como "No solamente SQL" para enfatizar que algunos sistemas NoSQL permiten consultas similares a SQL.
Al ser el lenguaje C del siglo XXI, Go tiene soporte para bases de datos NoSQL, incluyendo populares como redis, mongoDB, Cassandra y Membase.
## redis
redis es un sistema de almacenamiento llave valor como Memcached, que soporta los tipos de cadenas, listas conjuntos y conjuntos ordenados.
Aquí están algunos de los manejadores de bases de datos para redis:
- [https://github.com/alphazero/Go-Redis](https://github.com/alphazero/Go-Redis)
- [http://code.google.com/p/tideland-rdc/](http://code.google.com/p/tideland-rdc/)
- [https://github.com/simonz05/godis](https://github.com/simonz05/godis)
- [https://github.com/hoisie/redis.go](https://github.com/hoisie/redis.go)
Realicé una bifurcación de el último de estos paquetes, arreglé algunos servicios y lo usé en mi sistema de acortado de urls (2 millones de peticiones por día).
- [https://github.com/astaxie/goredis](https://github.com/astaxie/goredis)
Veamos como usar el manejador que bifurqué para operar con la base de datos:
```
package main
import (
"github.com/astaxie/goredis"
"fmt"
)
func main() {
var client goredis.Client
// Definir el puerto por defecto de redis
client.Addr = "127.0.0.1:6379"
// Manipulación de cadenas
client.Set("a", []byte("hello"))
val, _ := client.Get("a")
fmt.Println(string(val))
client.Del("a")
// Operaciones con listas
vals := []string{"a", "b", "c", "d", "e"}
for _, v := range vals {
client.Rpush("l", []byte(v))
}
dbvals,_ := client.Lrange("l", 0, 4)
for i, v := range dbvals {
println(i,":",string(v))
}
client.Del("l")
}
```
Como podemos ver es muy sencillo operar redis en Go, y como tiene un alto rendimiento. Los comandos de este cliente son casi lo mismo que los comandos que vienen con redis.
## mongoDB
mongoDB (de "humongous" (enorme)) es una bases de datos orientada a documentos de código abierto desarrollado y mantenida por 10gen. Hace parte de la familia de bases de datos NoSQL. En lugar de almacenar la información en tablas como es hecho en bases de datos relacionales 'clasicas', MongoDB guarda la información en estructurada en documentos al estilo JSON con esquemas dinámicos (MongoDB llama el formato BSON) haciendo que la integración de los datos en cierto tipo de aplicaciones sea mas fácil y rápido.
![](images/5.6.mongodb.png?raw=true)
Figura 5.1 MongoDB comparada con Mysql
El mejor manejador para mongoDB es llamado `mgo`, y es posible que se incluya en la librería estándar en el futuro.
Aquí está un ejemplo
```
package main
import (
"fmt"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
)
type Person struct {
Name string
Phone string
}
func main() {
session, err := mgo.Dial("server1.example.com,server2.example.com")
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("people")
err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
panic(err)
}
result := Person{}
err = c.Find(bson.M{"name": "Ale"}).One(&result)
if err != nil {
panic(err)
}
fmt.Println("Phone:", result.Phone)
}
```
Como podemos ver no hay muchas diferencias en lo que respecta a operar con mgo o bases de datos beedb; ambas son basadas en estructuras. Esta es la manera en que Go hace las cosas.
## Enlaces
- [Índice](preface.md)
- Sección previa: [Desarrollo de un ORM basado en beedb](05.5.md)
- Siguiente sección: [Resumen](05.7.md)

11
es/05.7.md Normal file
View File

@@ -0,0 +1,11 @@
# 5.7 Resumen
En este capítulo, primero aprendiste sobre el diseño de la interfaz `database/sql` y varios manejadores de bases de datos para varios tipos de bases de datos. Luego introducimos beedb, un ORM para bases de datos relacionales. También mostramos algunos ejemplos de operaciones con bases de datos. Al final, hablamos sobre algunas bases de datos NoSQL. Vimos como Go provee soporte para estas bases de datos NoSQL.
Después de leer este capítulo, espero que hayas entendido un poco mas como funcionan las bases de datos en Go. Esta es la parte mas importante del desarrollo web, por eso es importante que entiendas bien los conceptos de la interfaz `database/sql`.
## Enlaces
- [Índice](preface.md)
- Sección anterior: [Bases de Datos NoSQL ](05.6.md)
- Siguiente capítulo: [Almacenamiento de datos y sesiones](06.0.md)