You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: en/05.1.md
+34-34
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ Go doesn't provide any official database drivers, unlike other languages like PH
7
7
This function is in the `database/sql` package for registering database drivers when you use third-party database drivers. All of these should call the `Register(name string, driver driver.Driver)` function in `init()` in order to register themselves.
8
8
9
9
Let's take a look at the corresponding mymysql and sqlite3 driver code:
10
-
10
+
```Go
11
11
//https://github.com/mattn/go-sqlite3 driver
12
12
funcinit() {
13
13
sql.Register("sqlite3", &SQLiteDriver{})
@@ -20,68 +20,68 @@ Let's take a look at the corresponding mymysql and sqlite3 driver code:
20
20
Register("SET NAMES utf8")
21
21
sql.Register("mymysql", &d)
22
22
}
23
-
23
+
```
24
24
We see that all third-party database drivers implement this function to register themselves, and Go uses a map to save user drivers inside of `database/sql`.
25
-
25
+
```Go
26
26
vardrivers = make(map[string]driver.Driver)
27
27
28
28
drivers[name] = driver
29
-
29
+
```
30
30
Therefore, this registration function can register as many drivers as you may require, each with different names.
31
31
32
32
We always see the following code when we use third-party drivers:
33
-
33
+
```Go
34
34
import (
35
35
"database/sql"
36
36
_ "github.com/mattn/go-sqlite3"
37
37
)
38
-
38
+
```
39
39
Here, the underscore (also known as a 'blank') `_` can be quite confusing for many beginners, but this is a great feature in Go. We already know that this underscore identifier is used for discarding values from function returns, and also that you must use all packages that you've imported in your code in Go. So when the blank is used with import, it means that you need to execute the init() function of that package without directly using it, which is a perfect fit for the use-case of registering database drivers.
40
40
41
41
## driver.Driver
42
42
43
43
`Driver` is an interface containing an `Open(name string)` method that returns a `Conn` interface.
44
-
44
+
```Go
45
45
typeDriverinterface {
46
46
Open(name string) (Conn, error)
47
47
}
48
-
48
+
```
49
49
This is a one-time Conn, which means it can only be used once per goroutine. The following code will cause errors to occur:
50
-
50
+
```Go
51
51
...
52
52
gogoroutineA (Conn) // query
53
53
gogoroutineB (Conn) // insert
54
54
...
55
-
55
+
```
56
56
Because Go has no idea which goroutine does which operation, the query operation may get the result of the insert operation, and vice-versa.
57
57
58
58
All third-party drivers should have this function to parse the name of Conn and return the correct results.
59
59
60
60
## driver.Conn
61
61
62
62
This is a database connection interface with some methods, and as i've said above, the same Conn can only be used once per goroutine.
63
-
63
+
```Go
64
64
typeConninterface {
65
65
Prepare(query string) (Stmt, error)
66
66
Close() error
67
67
Begin() (Tx, error)
68
68
}
69
-
69
+
```
70
70
-`Prepare` returns the prepare status of corresponding SQL commands for querying and deleting, etc.
71
71
-`Close` closes the current connection and cleans resources. Most third-party drivers implement some kind of connection pool, so you don't need to cache connections which can cause unexpected errors.
72
72
-`Begin` returns a Tx that represents a transaction handle. You can use it for querying, updating, rolling back transactions, etc.
73
73
74
74
## driver.Stmt
75
75
76
76
This is a ready status that corresponds with Conn, so it can only be used once per goroutine (as is the case with Conn).
77
-
77
+
```Go
78
78
typeStmtinterface {
79
79
Close() error
80
80
NumInput() int
81
81
Exec(args []Value) (Result, error)
82
82
Query(args []Value) (Rows, error)
83
83
}
84
-
84
+
```
85
85
-`Close` closes the current connection but still returns row data if it is executing a query operation.
86
86
-`NumInput` returns the number of obligate arguments. Database drivers should check their caller's arguments when the result is greater than 0, and it returns -1 when database drivers don't know any obligate argument.
87
87
-`Exec` executes the `update/insert` SQL commands prepared in `Prepare`, returns `Result`.
@@ -90,81 +90,81 @@ This is a ready status that corresponds with Conn, so it can only be used once p
90
90
## driver.Tx
91
91
92
92
Generally, transaction handles only have submit or rollback methods, and database drivers only need to implement these two methods.
93
-
93
+
```Go
94
94
typeTxinterface {
95
95
Commit() error
96
96
Rollback() error
97
97
}
98
-
98
+
```
99
99
## driver.Execer
100
100
101
101
This is an optional interface.
102
-
102
+
```Go
103
103
typeExecerinterface {
104
104
Exec(query string, args []Value) (Result, error)
105
105
}
106
-
106
+
```
107
107
If the driver doesn't implement this interface, when you call DB.Exec, it will automatically call Prepare, then return Stmt. After that it executes the Exec method of Stmt, then closes Stmt.
108
108
109
109
## driver.Result
110
110
111
111
This is the interface for results of `update/insert` operations.
112
-
112
+
```Go
113
113
typeResultinterface {
114
114
LastInsertId() (int64, error)
115
115
RowsAffected() (int64, error)
116
116
}
117
-
117
+
```
118
118
-`LastInsertId` returns auto-increment Id number after a database insert operation.
119
119
-`RowsAffected` returns rows that were affected by query operations.
120
120
121
121
## driver.Rows
122
122
123
123
This is the interface for the result of a query operation.
124
-
124
+
```Go
125
125
typeRowsinterface {
126
126
Columns() []string
127
127
Close() error
128
128
Next(dest []Value) error
129
129
}
130
-
130
+
```
131
131
-`Columns` returns field information of database tables. The slice has a one-to-one correspondence with SQL query fields only, and does not return all fields of that database table.
132
132
-`Close` closes Rows iterator.
133
133
-`Next` returns next data and assigns to dest, converting all strings into byte arrays, and gets io.EOF error if no more data is available.
134
134
135
135
## driver.RowsAffected
136
136
137
137
This is an alias of int64, but it implements the Result interface.
138
-
138
+
```Go
139
139
typeRowsAffectedint64
140
140
141
141
func (RowsAffected) LastInsertId() (int64, error)
142
142
143
143
func (v RowsAffected) RowsAffected() (int64, error)
144
-
144
+
```
145
145
## driver.Value
146
146
147
147
This is an empty interface that can contain any kind of data.
148
-
148
+
```Go
149
149
type Value interface{}
150
-
150
+
```
151
151
The Value must be something that drivers can operate on or nil, so it should be one of the following types:
152
-
152
+
```Go
153
153
int64
154
154
float64
155
155
bool
156
156
[]byte
157
157
string [*] ExceptRows.Next which cannot returnstring
158
158
time.Time
159
-
159
+
```
160
160
## driver.ValueConverter
161
161
162
162
This defines an interface for converting normal values to driver.Value.
163
-
163
+
```Go
164
164
typeValueConverterinterface {
165
165
ConvertValue(v interface{}) (Value, error)
166
166
}
167
-
167
+
```
168
168
This interface is commonly used in database drivers and has many useful features:
169
169
170
170
- Converts driver.Value to a corresponding database field type, for example converts int64 to uint16.
@@ -174,27 +174,27 @@ This interface is commonly used in database drivers and has many useful features
174
174
## driver.Valuer
175
175
176
176
This defines an interface for returning driver.Value.
177
-
177
+
```Go
178
178
typeValuerinterface {
179
179
Value() (Value, error)
180
180
}
181
-
181
+
```
182
182
Many types implement this interface for conversion between driver.Value and itself.
183
183
184
184
At this point, you should know a bit about developing database drivers in Go. Once you can implement interfaces for operations like add, delete, update, etc., there are only a few problems left related to communicating with specific databases.
185
185
186
186
## database/sql
187
187
188
188
database/sql defines even more high-level methods on top of database/sql/driver for more convenient database operations, and it suggests that you implement a connection pool.
189
-
189
+
```Go
190
190
typeDBstruct {
191
191
driver driver.Driver
192
192
dsn string
193
193
mu sync.Mutex// protects freeConn and closed
194
194
freeConn []driver.Conn
195
195
closed bool
196
196
}
197
-
197
+
```
198
198
As you can see, the `Open` function returns a DB that has a freeConn, and this is a simple connection pool. Its implementation is very simple and ugly. It uses `defer db.putConn(ci, err)` in the Db.prepare function to put a connection into the connection pool. Everytime you call the Conn function, it checks the length of freeConn. If it's greater than 0, that means there is a reusable connection and it directly returns to you. Otherwise it creates a new connection and returns.
Copy file name to clipboardexpand all lines: en/05.2.md
+4-4
Original file line number
Diff line number
Diff line change
@@ -18,17 +18,17 @@ I'll use the first driver in the following examples (I use this one in my person
18
18
## Samples
19
19
20
20
In the following sections, I'll use the same database table structure for different databases, then create SQL as follows:
21
-
21
+
```sql
22
22
CREATETABLE `userinfo` (
23
23
`uid`INT(10) NOT NULL AUTO_INCREMENT,
24
24
`username`VARCHAR(64) NULL DEFAULT NULL,
25
25
`departname`VARCHAR(64) NULL DEFAULT NULL,
26
26
`created`DATENULL DEFAULT NULL,
27
27
PRIMARY KEY (`uid`)
28
28
);
29
-
29
+
```
30
30
The following example shows how to operate on a database based on the `database/sql` interface standards.
31
-
31
+
```Go
32
32
package main
33
33
34
34
import (
@@ -102,7 +102,7 @@ The following example shows how to operate on a database based on the `database/
102
102
panic(err)
103
103
}
104
104
}
105
-
105
+
```
106
106
Let me explain a few of the important functions here:
107
107
108
108
-`sql.Open()` opens a registered database driver. The Go-MySQL-Driver registered the mysql driver here. The second argument is the DSN (Data Source Name) that defines information pertaining to the database connection. It supports following formats:
0 commit comments