Skip to content

Latest commit

 

History

History
236 lines (165 loc) · 8.7 KB

File metadata and controls

236 lines (165 loc) · 8.7 KB

5.1 Base de datos interfaz sql

Go no proporcionar ningún controlador de base de datos oficial que hace PHP, pero tiene algunos estándares de interfaz de controlador de base de datos para desarrolladores que desarrollan drivers de bases de datos. Hay una ventaja que si el código ha sido desarrollado de acuerdo con estos estándares de interfaz, no cambia ningún código cuando su base de datos cambia. Vamos a ver lo que estos estándares de interfaz de base de datos son.

sql.Register

Esta función se encuentra en el paquete de base de database/sql para registrar los drivers de bases de datos al utilizar controladores de base de datos de terceros. Todos esos drivers, deben llamar a la función de registro (nombre de la cadena, driver driver.Driver) en init () función para registrar sus conductores.

Vamos a echar un vistazo a el código correspondiente en los conductores de mymysql y sqlite3:

	//https://github.com/mattn/go-sqlite3 driver
	func init() {
	    sql.Register("sqlite3", &SQLiteDriver{})
	}
	
	//https://github.com/mikespook/mymysql driver
	// Driver automatically registered in database/sql
	var d = Driver{proto: "tcp", raddr: "127.0.0.1:3306"}
	func init() {
	    Register("SET NAMES utf8")
	    sql.Register("mymysql", &d)
	}

Vemos que todos los controladores de bases de datos de terceras partes implementan esta función a fin de registrarse, y Go utiliza un mapa para guardar los conductores de usuario dentro de databse/sql.

	var drivers = make(map[string]driver.Driver)
	
	drivers[name] = driver

Por lo tanto, esta función de registro puede registrar los drivers tantos como desee, con nombre diferente.

Siempre vemos siguiente código cuando utilizamos controladores de terceros:

    import (
        "database/sql"
        _ "github.com/mattn/go-sqlite3"
    )

Aquí el guion bajo _ es bastante confuso para muchos principiantes, y esto es un gran diseño en Go. Sabemos este identificador es para descartar los valores de retorno de la función, y usted tiene que utilizar todos los paquetes importados en el código en Go. Así que cuando se utiliza la importación se necesita para ejecutar la función init () de ese paquete sin usarla directamente, para el registro de controlador de base de datos.

driver.Driver

Driver es una interfaz que tiene un método Open(name string) que devuelve una interfaz de Conn .

	type Driver interface {
	    Open(name string) (Conn, error)
	}

Esto se hace una sola vez Conn, lo que significa que se puede utilizar sólo una vez en una goroutine. En el siguiente código se producirá errores:

...
go goroutineA (Conn)  // query
go goroutineB (Conn)  // insert
...

Debido a que Go no tiene ni idea sobre qué goroutine se hace la operación, por lo que la operación de consulta se puede obtener el resultado de la inserción, viceversa.

Todos los controladores de otros fabricantes deben tener esta función para analizar el nombre de Conn y devolver correctamente los resultados.

driver.Conn

Se trata de una interfaz de conexión de base de datos con algunos métodos, y como he dicho anteriormente, solo se puede utilizar Conn en una goroutine.

	type Conn interface {
	    Prepare(query string) (Stmt, error)
	    Close() error
	    Begin() (Tx, error)
	}
  • Prepare prepara el estado de comandos SQL correspondiente para consultar y borrar, etc
  • Close cierra la conexión actual y recursos limpios. La mayoría de los controladores de terceros utilizan algunos tipos de agrupación de conexiones, por lo que no es necesario para almacenar en caché las conexiones a menos que usted desee tener errores inesperados.
  • Begin devuelve un Tx que representa un identificador que se puede utilizar para consultar, actualizar o retroceder etc

driver.Stmt

Este es un estado de listo y se corresponde con Conn, por lo que sólo se puede utilizar en una goroutine como Conn

	type Stmt interface {
	    Close() error
	    NumInput() int
	    Exec(args []Value) (Result, error)
	    Query(args []Value) (Rows, error)
	}
  • Close cierra la conexión actual, pero sigue devolviendo datos de filas si se está haciendo operación de consulta.
  • NumInput devuelve el número de argumentos obligados, los controladores de bases de datos deben comprobar los argumentos de llamantes cuando el resultado es mayor que 0, y se devuelve -1 cuando los conductores de bases de datos no conocen ningún argumento obligado.
  • Exec ejecuta comandos SQL de update/insert que se prepara en Prepare , devuelve Result .
  • Query ejecuta comandos SQL deselect que se preparan en Prepare , devuelve datos filas.

driver.Tx

Generally, affair handle only have submit or roll back, and database drivers only need to implement these two methods.

	type Tx interface {
	    Commit() error
	    Rollback() error
	}

driver.Execer

Esta es una interfaz opcional.

	type Execer interface {
	    Exec(query string, args []Value) (Result, error)
	}

Si el conductor no implementa esta interfaz, a continuación, cuando usted llama DB.Exec, llama automáticamente Prepare y devuelve Stmt, luego ejecuta Exec de Stmt, a continuación, cierra Stmt.

driver.Result

Esta es la interfaz para el resultado de la operacion update/insert.

	type Result interface {
	    LastInsertId() (int64, error)
	    RowsAffected() (int64, error)
	}
  • LastInsertId devuelve el número de Identificación de incremento automático después de la operación de inserción de la base de datos.
  • RowsAffected devuelve filas que afectaron después de operación de consulta.

driver.Rows

Esta es la interfaz de conjunto de resultados de la operación de consulta.

	type Rows interface {
	    Columns() []string
	    Close() error
	    Next(dest []Value) error
	}
  • Columns devuelve los campos de información de las tablas de base de datos, el corte es uno-a-uno con campo de consulta SQL, no todos los campos de esa tabla de base de datos.
  • Close cierra iterator de filas.
  • Next datos siguientes y asigna a dest, toda cadena deben convertirse en matriz de bytes, y obtiene el error io.EOF si no hay más datos disponibles.

diriver.RowsAffected

Este es un alias de int64, pero implementa la interfaz de resultados.

	type RowsAffected int64
	
	func (RowsAffected) LastInsertId() (int64, error)
	
	func (v RowsAffected) RowsAffected() (int64, error)

driver.Value

Esta es una interfaz de vacío que puede contener cualquier tipo de datos.

	type Value interface{}

El valor debe ser algo que los drivers pueden operar o anular, por lo que debe ser uno de los siguientes tipos:

int64
float64
bool
[]byte
string   [*] Except Rows.Next which cannot return string
time.Time

driver.ValueConverter

Esto define una interfaz para la conversión de los valores normales para driver.Value.

	type ValueConverter interface {
	    ConvertValue(v interface{}) (Value, error)
	}

Esto es comúnmente utilizado en los controladores de base de datos y tiene muchas buenas características

  • Convertir driver.Value al correspondiente tipo de campo de base de datos, por ejemplo, convertir a int64 Uint16.
  • Convertir los resultados de consultas de bases de datos para driver.Value.
  • Convert Convertir driver.Value al usuario el valor definido en scan función.

driver.Valuer

Esto define una interfaz para el retorno de driver.Value.

	type Valuer interface {
	    Value() (Value, error)
	}

Muchos tipos implementan esta interfaz para la conversión entre driver.Value y ella misma.

En este punto, usted debe tener conceptos acerca de cómo desarrollar un controlador de base de datos. Una vez implementada sobre interfaces para operaciones como añadir, eliminar, actualizar, etc No sólo dejó problemas sobre la comunicación con la base de datos específica.

database/sql

databse/sql define métodos más alto nivel por encima de database/sql/driver para un manejo más cómodo con las bases de datos, y le sugiere implementar un grupo de conexiones.

	type DB struct {
	    driver   driver.Driver
	    dsn      string
	    mu       sync.Mutex // protects freeConn and closed
	    freeConn []driver.Conn
	    closed   bool
	}	

Como puede ver, la función Abrir devuelve un DB que tiene un freeConn, y este es el grupo de conexión simple. Su implementación es muy simple , utiliza defer db.putConn(ci, err) en función Db.prepare poner la conexión en la agrupación de conexiones. Cada vez que se llama a la función Conn, comprueba la longitud de freeCoon, si es mayor que 0 significa que hay una conexión directa reutilizable y vuelve, de lo contrario crea y retorna una nueva.

Enlaces