Go 言語でデータベースを書き込むことはできますか?
Go 言語はデータベースを作成できます。 Go 言語と他の言語の違いは、Go はデータベース ドライバーを正式に提供していませんが、データベース ドライバーを開発するための標準インターフェイスを作成しており、開発者は定義されたインターフェイスに基づいて対応するデータベース ドライバーを開発できるという利点があります。標準インターフェイスに従って開発されたコードは、将来データベースを移行するときに変更を必要とせず、その後のアーキテクチャの調整が大幅に容易になります。
このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。
データベースは、データ構造に従ってデータを編成、保存、管理する倉庫です。他のストレージ方法と比較すると、ストレージはデータベースの機能の 1 つにすぎず、データの編成と管理がデータベースの中核です。
データベースと比較すると、データをファイルに保存する場合の欠点は次のとおりです。
- ファイルにはセキュリティの問題がある #ファイルはデータのクエリや管理に適さない
- ファイルに大量のデータを保存するのは簡単ではありません
- ファイルをプログラムで制御するのは簡単ではありません
1. MySQL の概要
MySQL は、スウェーデンの MySQL AB 社によって開発されたリレーショナル データベース管理システムであり、現在は Oracle に属しています。)その製品。 MySQL は最も人気のあるリレーショナル データベース管理システムの 1 つであり、Web アプリケーションの観点から見ると、MySQL は最高の RDBMS (リレーショナル データベース管理システム) アプリケーション ソフトウェアの 1 つです。##1.2 MySQL 共通コマンド> mysql -h主机地址 -u用户名 -p用户密码
> mysql -h192.168.1.1 -uroot -proot
mysql> exit/quit;
- 2.database/sql
の操作に進みます。これは、database/sql パッケージと、database/sql/driver インターフェイスを実装するサードパーティのデータベース ドライバー パッケージによって実現されます。 database/sql/driver のインターフェイス Conn および Stmt は、ドライバーを実装するために正式にサードパーティに引き渡されており、コルーチンにとって安全ではありません。公式に実装されたデータベース/SQL パッケージ内の DB および Stmt は、内部実装が接続プールであるため、コルーチンに対して安全です。
Go 言語と他の言語の違いは、Go ではデータベース ドライバーが公式に提供されていないことです。代わりに、データベース ドライバーを開発するための標準インターフェイスが記述されています。開発者は、定義されたインターフェイスに基づいて、対応するデータベース ドライバーを開発できます。 。この利点は、コードが標準インターフェイスに従って開発されている限り、将来データベースを移行するときに変更が必要ないため、後のアーキテクチャの調整が大幅に容易になることです。 サードパーティ開発者によって作成されたすべてのデータベース ドライバーでは、init 関数が実装され、init 関数内で Register と呼ばれるメソッドが呼び出されて、データベース ドライバーの登録が完了します。func Register(name string, driver driver.Driver)
func init() { sql.Register("mysql", &MySQLDriver{}) }
import ( "database/sql" _ "github.com/go-sql-driver/mysql" )
3. 基本的なデータベース操作
データベースの最も基本的な操作は、作成、読み取り、更新)、削除、参照です。 CRUDとして。データベースには、データベース、データ テーブル、レコード、フィールド、インデックス、クエリ、フィルター、およびビュー という 8 種類のオブジェクトがあります。
Go 言語では、SQL パッケージには、データベース接続。 func Open(driverName, dataSourceName string) (*DB, error)
func (db *DB) Ping() error
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" ) func main() { db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy") if err != nil { log.Fatal(err) } defer db.Close() //验证连接的可用性 err = db.Ping() if err != nil { log.Fatal("数据库连接失败:", err) } log.Println("数据库连接成功!") }
MySQL データ テーブルの作成テーブル名、テーブルフィールド名、フィールドタイプおよび制約の定義が必要です。データ テーブルを作成する構文構造は次のとおりです。 CREATE TABLE 表名 (
字段名1 数据类型 [列级别约束条件] [默认值],
字段名2 数据类型 [列级别约束条件] [默认值],
字段名3 数据类型 [列级别约束条件] [默认值],
... [表级别约束条件]
);
CREATE TABLE `user`( `uid` INT(10) NOT NULL AUTO_INCREMENT, `username` VARCHAR(64) NULL DEFAULT 1, `gender` TINYINT(1) NULL DEFAULT NULL, `password` VARCHAR(64) NULL DEFAULT NULL, `created` DATE NULL DEFAULT NULL, PRIMARY KEY (`uid`) );
使用Go语言创建数据表需要使用Exec函数。
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
Exec执行一次命令(包括查询、删除、更新、插入等),不返回任何执行结果。参数args表示query中的占位参数。
Exec的返回值为Result接口,Result的定义如下:
type Result interface { LastInsertId() (int64, error) RowsAffected() (int64, error) }
Result主要有两个方法。LastInsertId返回一个数据库生成的回应命令的整数,当插入新行时,返回由数据库执行插入操作得到的自增ID号。RowsAffected返回被update、insert或delete命令影响的行数。
MySQL中使用INSERT INTO语句来插入数据,插入的语法结构为:
INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...valueN );
如果需要同时插入多条数据,可以使用如下方式:
INSERT INTO table_name (field1, field2,...fieldN) VALUES (valueA1,valueA2,...valueAN),(valueB1,valueB2,...value BN)......;
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" "time" ) func checkErr(err error) { if err != nil { log.Fatal(err) } } func main() { db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy") checkErr(err) defer db.Close() //验证连接可用性 err = db.Ping() checkErr(err) log.Println("数据库连接成功") rs, err := db.Exec("insert into `user`(username,gender,password,created) values (?,?,?,?)", "tom", 1, "123456", time.Now()) checkErr(err) rowCount, err := rs.RowsAffected() checkErr(err) log.Printf("插入了 % d行", rowCount) }
SQL注入(SQLi)是一种注入攻击,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加、修改和删除数据库中的记录。
sql包还提供一种预编译的方式来执行SQL语句,通常在处理批量SQL语句时会用到这种方式,这种方式比手动拼接字符串SQL语句高效,还可以防止SQL注入攻击。
func (db *DB) Prepare(query string) (*Stmt, error)
Prepare创建一个准备好的状态用于之后的查询和命令。返回值可以同时执行多个查询和命令。
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" "time" ) func checkErr(err error) { if err != nil { log.Fatal(err) } } func main() { db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy") checkErr(err) defer db.Close() //验证连接可用性 err = db.Ping() checkErr(err) log.Println("数据库连接成功") //rs, err := db.Exec("insert into `user`(username,gender,password,created) values (?,?,?,?)", "tom", 1, "123456", time.Now()) stmt, err := db.Prepare("INSERT INTO `user`(username,gender,password,created) VALUES (?,?,?,?)") defer stmt.Close() rs, err := stmt.Exec("Ailsa", 0, "111111", time.Now()) checkErr(err) rowCount, err := rs.RowsAffected() checkErr(err) log.Printf("插入了 % d行", rowCount) }
MySQL数据库使用SELECT语句来查询数据。以下为在MySQL数据库中查询数据通用的SELECT语法:
SELECT column_name,column_name FROM <表 1>, <表 2>... JOIN<表3>on... [WHERE <表达式> [GROUP BY <group by definition> [HAVING <expression> [{<operator> <expression>}...]] [ORDER BY <order by definition>] [LIMIT[<offset>,] <row count>]
语法解释:
- SELECT之后是逗号分隔列或星号(*)的列表,表示要返回所有列。
- FROM指定要查询数据的表或视图。
- JOIN根据某些连接条件从其他表中获取数据。
- WHERE过滤结果集中的行。
- GROUP BY将一组行组合成小分组,并对每个小分组应用聚合函数。
- HAVING过滤器是基于GROUP BY子句定义的小分组。
- ORDER BY指定用于排序的列的列表。
- LIMIT限制返回行的数量。
在Go语言中,我们可以使用Query函数来查询数据:
func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
Query执行一次查询,返回多行结果(即Rows),一般用于执行SELECT命令。参数args表示
Query中的占位参数,Rows是查询的结果。它的游标指向结果集的第0行,使用Next方法来遍历各行结果。查询到数据后使用rows.Next获取一行结果,并使用Scan将查询到的结果赋值到目标变量中。
func (r *Row) Scan(dest ...interface{}) error
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" ) type User struct { Uid int Username string Gender bool Password string Created string } func checkErr(err error) { if err != nil { log.Fatal(err) } } func main() { db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy") checkErr(err) defer db.Close() //验证连接的可用性 err = db.Ping() checkErr(err) log.Println("数据库连接成功!") rows, err := db.Query("select * from `user` where username=?", "Tom") defer rows.Close() for rows.Next() { user := User{} err := rows.Scan(&user.Uid, &user.Username, &user.Gender, &user.Password, &user.Created) checkErr(err) log.Println(user) } }
如果需要修改或更新MySQL中的数据,我们可以使用UPDATE命令来操作。
UPDATE <表名> SET 字段 1=值 1 [,字段 2=值 2... ] [WHERE 子句 ] [ORDER BY 子句] [LIMIT 子句]
语法解释:
- <表名>:用于指定要更新的表名称。
- SET:用于指定表中要修改的列名及其列值。其中,每个指定的列值可以是表达式,也可
以是该列对应的默认值。如果指定的是默认值,可用关键字DEFAULT表示列值。 - WHERE:可选。用于限定表中要修改的行。若不指定,则修改表中所有的行。
- ORDER BY:可选。用于限定表中的行被修改的次序。
- LIMIT:可选。用于限定被修改的行数。
注意:修改一行数据的多个列值时,SET子句的每个值用逗号分开即可。
rs, err := db.Exec("update `user` set password=? where sername=?","123123","john") checkErr(err) rowCount, err := rs.RowsAffected() checkErr(err) if rowCount > 0 { log.Println("更新成功!") }
MySQL使用DELETE语句从单个表中删除数据,语法格式为:
DELETE FROM <表名> [WHERE 子句] [ORDER BY 子句] [LIMIT 子句]
语法解释:
- <表名>:指定要删除数据的表名。
- WHERE子句:可选项。表示为删除操作限定删除条件,若省略该子句,则代表删除该表中
的所有行。 - ORDER BY子句:可选项。表示删除时,表中各行将按照子句中指定的顺序进行删除。
- LIMIT子句:可选项。用于告知服务器在控制命令被返回到客户端前被删除行的最大值。
注意:在不使用WHERE条件的时候,将删除所有数据;数据库一旦删除数据,数据就会永远
消失。因此,在执行DELETE语句之前,应该先备份数据库,以防需要找回被删除的数据。
rs, err := db.Exec("delete from `user` where uid=?",3) checkErr(err) rowCount, err := rs.RowsAffected() checkErr(err) if rowCount > 0 { log.Println("删除成功!") }
MySQL数据库中的事务是用户一系列的数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。
事务具有四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这四个特性简称为ACID原则。
原子性
事务必须是原子工作单元,事务中的操作要么全部执行,要么全都不执行,不能只完成部分操作。原子性在数据库系统中由恢复机制来实现。
一致性
事务开始之前,数据库处于一致性的状态;事务结束后,数据库必须仍处于一致性状态。数
据库一致性的定义是由用户负责的。例如,在银行转账中,用户可以定义转账前后两个账户金额之和保持不变。隔离性
系统必须保证事务不受其他并发执行事务的影响,即当多个事务同时运行时,各事务之间相
互隔离,不可互相干扰。事务查看数据时数据所处的状态,要么是另一个并发事务修改它之前的状态,要么是另一个并发事务修改它之后的状态,事务不会查看中间状态的数据。隔离性通过系统的并发控制机制实现。持久性
一个已完成的事务对数据所做的任何变动在系统中是永久有效的,即使该事务产生的修改不
正确,错误也将一直保持。持久性通过恢复机制实现,发生故障时,可以通过日志等手段恢复数据库信息。
事务的ACID原则保证了一个事务或者成功提交,或者失败回滚,二者必居其一。因此,它对事务的修改具有可恢复性,即当事务失败时,它对数据的修改都会恢复到该事务执行前的状态。
简单来说,事务处理就两个过程,要么成功提交,要么失败回滚,在Go语言中使用Tx结构体来表示事务。
type Tx interface{ Commit() error Rollback() error }
Tx代表一个进行中的数据库事务。一次事务必须以对Commit或Rollback的调用结束。调用Commit或Rollback后,所有对事务的操作都会失败并返回错误值ErrTxDone。
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" ) func checkErr(err error) { if err != nil { log.Fatal(err) } } func checkErrWithTx(err error, tx *sql.Tx) { if err != nil { tx.Rollback() log.Fatal(err) } } func main() { db, err := sql.Open("mysql", "root:200039@tcp(127.0.0.1:3306)/gostudy") checkErr(err) defer db.Close() //验证连接的可用性 err = db.Ping() checkErr(err) log.Println("数据库连接成功!") var password string tx, err := db.Begin() checkErr(err) //查找Tom的密码,如果密码为123456就将密码改为111111,否则不执行任何操作 err = tx.QueryRow("select password from `user` where username=?", "Tom").Scan(&password) checkErrWithTx(err, tx) if password == "123456" { rs, err := tx.Exec("update `user` set password=? where username=?", "111111", "Tom") checkErrWithTx(err, tx) rowCount, err := rs.RowsAffected() checkErrWithTx(err, tx) if rowCount > 0 { log.Println("密码更新完成!") } } tx.Commit() log.Println("事务处理完成!") }
4、知识拓展
-
数据库(Database)
所谓“数据库”,是以一定方式存储在一起、能与多个用户共享、具有尽可能小的冗余度、
与应用程序彼此独立的数据集合。MySQL中使用的数据库是关系型数据库(Relational Database)。一个数据库由一个或一组数据表组成。每个数据库都以文件的形式存放在磁盘上,即对应于一个物理文件。不同的数据库与物理文件对应的方式也不一样。 -
数据表(Table)
数据表简称表,由一组数据记录组成,数据库中的数据是以表为单位进行组织的。一个表是
一组相关的按行排列的数据,每个表中都含有相同类型的信息。表实际上是一个二维表格,例如一个班所有学生的考试成绩可以存放在一个表中,表中的每一行对应一个学生,这一行包括学生的学号、姓名及各门课程成绩。 -
记录(Record)
表中的每一行称为一个记录,它由若干个字段组成。
-
字段(Field)
字段也称域。表中的每一列称为一个字段。每个字段都有相应的描述信息,如数据类型、数
据宽度等。 -
索引(Index)
データベースへのアクセス効率を向上させるために、データベースにインデックスを使用できます。大規模なデータベース内で指定されたレコード
を検索する場合、インデックスを使用する場合と使用しない場合では効率に大きな違いがあります。インデックスは、実際には、キー フィールドの値 (ユーザーが定義) と実際のレコードの場所へのポインターを含む特別なタイプのテーブルです。これらの値とポインターは、特定の順序で格納されます (これもユーザーが定義します)。 ) 特定の順序 (これもユーザーが定義) で保存できるため、必要なデータ レコードをより迅速に見つけることができます。 -
Query
Query は、1 つ以上のテーブルから指定されたレコードのセットを取得するために使用される SQL (構造化照会言語) コマンドです。または
指定された操作を実行します。テーブルの上。データベースからデータを読み取るとき、私たちは多くの場合、読み取ったデータが特定の条件を満たし、特定のフィールドでソートできることを望みます。 SQL を使用すると、この操作がより簡単かつ効率的になります。 SQL は非手続き型言語 (第 4 世代言語と呼ぶ人もいます) なので、SQL を使用して指定されたレコードを検索する場合、指示する必要があるのは、実行方法ではなく、実行内容だけです。それぞれのステートメントをクエリとみなすことができ、このクエリに従って必要なクエリ結果を取得することができます。 -
フィルター (フィルター)
フィルターはデータベースのコンポーネントです。インデックス作成と並べ替えを組み合わせて条件を設定し、指定された
条件付き出力に基づきます。必要なデータ。 -
View (ビュー)
データのビューとは、見つかった (または処理された) レコードの数と、これらのレコードが表示される (または処理される) 順序を指します。 )。一般に、これは実際には 2 次元のテーブルです。たとえば、クラス内のすべての生徒のテストのスコアをテーブルに保存できます。テーブルの各行は生徒に対応します。この行には生徒の生徒番号、名前が含まれますコースの結果。
以上がGo 言語でデータベースを書き込むことはできますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Go Crawler Collyのキュースレッドの問題は、Go言語でColly Crawler Libraryを使用する問題を調査します。 �...

大企業または有名なオープンソースプロジェクトによって開発されたGOのどのライブラリが開発されていますか? GOでプログラミングするとき、開発者はしばしばいくつかの一般的なニーズに遭遇します...

GO言語で構造を定義する2つの方法:VARとタイプのキーワードの違い。構造を定義するとき、GO言語はしばしば2つの異なる執筆方法を見ます:最初...

マルチプロセスのログライティングの並行性セキュリティの問題を効率的に処理します。複数のプロセスが同じログファイルを同時に書き込みます。並行性が安全で効率的であることを確認する方法は?これは...

redisstreamを使用してGo言語でメッセージキューを実装する問題は、GO言語とRedisを使用することです...

Go言語での文字列印刷の違い:printlnとstring()関数を使用する効果の違いはGOにあります...

VSCODEユーザーのGolang Generic Function Typeの制約の自動削除は、VSCODEを使用してGolangコードを書くときに奇妙な問題に遭遇する可能性があります。いつ...
