Skip to content

Commit 47b4115

Browse files
authored
Merge pull request astaxie#841 from vCaesar/u13-pr
Fix some md error and Add en syntax highlighting
2 parents 939ddcb + dd12767 commit 47b4115

File tree

8 files changed

+109
-108
lines changed

8 files changed

+109
-108
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ QQ群:148647580
2222

2323
BBS:[http://golanghome.com/](http://gocn.io/)
2424

25-
##Contributors
25+
## Contributors
2626

2727
- See [contributors page](https://github.com/astaxie/build-web-application-with-golang/graphs/contributors) for full list of contributors.
2828

en/05.1.md

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Go doesn't provide any official database drivers, unlike other languages like PH
77
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.
88

99
Let's take a look at the corresponding mymysql and sqlite3 driver code:
10-
10+
```Go
1111
//https://github.com/mattn/go-sqlite3 driver
1212
func init() {
1313
sql.Register("sqlite3", &SQLiteDriver{})
@@ -20,68 +20,68 @@ Let's take a look at the corresponding mymysql and sqlite3 driver code:
2020
Register("SET NAMES utf8")
2121
sql.Register("mymysql", &d)
2222
}
23-
23+
```
2424
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
2626
var drivers = make(map[string]driver.Driver)
2727

2828
drivers[name] = driver
29-
29+
```
3030
Therefore, this registration function can register as many drivers as you may require, each with different names.
3131

3232
We always see the following code when we use third-party drivers:
33-
33+
```Go
3434
import (
3535
"database/sql"
3636
_ "github.com/mattn/go-sqlite3"
3737
)
38-
38+
```
3939
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.
4040

4141
## driver.Driver
4242

4343
`Driver` is an interface containing an `Open(name string)` method that returns a `Conn` interface.
44-
44+
```Go
4545
type Driver interface {
4646
Open(name string) (Conn, error)
4747
}
48-
48+
```
4949
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
5151
...
5252
go goroutineA (Conn) // query
5353
go goroutineB (Conn) // insert
5454
...
55-
55+
```
5656
Because Go has no idea which goroutine does which operation, the query operation may get the result of the insert operation, and vice-versa.
5757

5858
All third-party drivers should have this function to parse the name of Conn and return the correct results.
5959

6060
## driver.Conn
6161

6262
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
6464
type Conn interface {
6565
Prepare(query string) (Stmt, error)
6666
Close() error
6767
Begin() (Tx, error)
6868
}
69-
69+
```
7070
- `Prepare` returns the prepare status of corresponding SQL commands for querying and deleting, etc.
7171
- `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.
7272
- `Begin` returns a Tx that represents a transaction handle. You can use it for querying, updating, rolling back transactions, etc.
7373

7474
## driver.Stmt
7575

7676
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
7878
type Stmt interface {
7979
Close() error
8080
NumInput() int
8181
Exec(args []Value) (Result, error)
8282
Query(args []Value) (Rows, error)
8383
}
84-
84+
```
8585
- `Close` closes the current connection but still returns row data if it is executing a query operation.
8686
- `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.
8787
- `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
9090
## driver.Tx
9191

9292
Generally, transaction handles only have submit or rollback methods, and database drivers only need to implement these two methods.
93-
93+
```Go
9494
type Tx interface {
9595
Commit() error
9696
Rollback() error
9797
}
98-
98+
```
9999
## driver.Execer
100100

101101
This is an optional interface.
102-
102+
```Go
103103
type Execer interface {
104104
Exec(query string, args []Value) (Result, error)
105105
}
106-
106+
```
107107
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.
108108

109109
## driver.Result
110110

111111
This is the interface for results of `update/insert` operations.
112-
112+
```Go
113113
type Result interface {
114114
LastInsertId() (int64, error)
115115
RowsAffected() (int64, error)
116116
}
117-
117+
```
118118
- `LastInsertId` returns auto-increment Id number after a database insert operation.
119119
- `RowsAffected` returns rows that were affected by query operations.
120120

121121
## driver.Rows
122122

123123
This is the interface for the result of a query operation.
124-
124+
```Go
125125
type Rows interface {
126126
Columns() []string
127127
Close() error
128128
Next(dest []Value) error
129129
}
130-
130+
```
131131
- `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.
132132
- `Close` closes Rows iterator.
133133
- `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.
134134

135135
## driver.RowsAffected
136136

137137
This is an alias of int64, but it implements the Result interface.
138-
138+
```Go
139139
type RowsAffected int64
140140

141141
func (RowsAffected) LastInsertId() (int64, error)
142142

143143
func (v RowsAffected) RowsAffected() (int64, error)
144-
144+
```
145145
## driver.Value
146146

147147
This is an empty interface that can contain any kind of data.
148-
148+
```Go
149149
type Value interface{}
150-
150+
```
151151
The Value must be something that drivers can operate on or nil, so it should be one of the following types:
152-
152+
```Go
153153
int64
154154
float64
155155
bool
156156
[]byte
157157
string [*] Except Rows.Next which cannot return string
158158
time.Time
159-
159+
```
160160
## driver.ValueConverter
161161

162162
This defines an interface for converting normal values to driver.Value.
163-
163+
```Go
164164
type ValueConverter interface {
165165
ConvertValue(v interface{}) (Value, error)
166166
}
167-
167+
```
168168
This interface is commonly used in database drivers and has many useful features:
169169

170170
- 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
174174
## driver.Valuer
175175

176176
This defines an interface for returning driver.Value.
177-
177+
```Go
178178
type Valuer interface {
179179
Value() (Value, error)
180180
}
181-
181+
```
182182
Many types implement this interface for conversion between driver.Value and itself.
183183

184184
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.
185185

186186
## database/sql
187187

188188
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
190190
type DB struct {
191191
driver driver.Driver
192192
dsn string
193193
mu sync.Mutex // protects freeConn and closed
194194
freeConn []driver.Conn
195195
closed bool
196196
}
197-
197+
```
198198
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.
199199

200200
## Links

en/05.2.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ I'll use the first driver in the following examples (I use this one in my person
1818
## Samples
1919

2020
In the following sections, I'll use the same database table structure for different databases, then create SQL as follows:
21-
21+
```sql
2222
CREATE TABLE `userinfo` (
2323
`uid` INT(10) NOT NULL AUTO_INCREMENT,
2424
`username` VARCHAR(64) NULL DEFAULT NULL,
2525
`departname` VARCHAR(64) NULL DEFAULT NULL,
2626
`created` DATE NULL DEFAULT NULL,
2727
PRIMARY KEY (`uid`)
2828
);
29-
29+
```
3030
The following example shows how to operate on a database based on the `database/sql` interface standards.
31-
31+
```Go
3232
package main
3333

3434
import (
@@ -102,7 +102,7 @@ The following example shows how to operate on a database based on the `database/
102102
panic(err)
103103
}
104104
}
105-
105+
```
106106
Let me explain a few of the important functions here:
107107

108108
- `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:

en/05.3.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ The first driver is the only one that supports the `database/sql` interface stan
1515
## Samples
1616

1717
We create the following SQL:
18-
18+
```sql
1919
CREATE TABLE `userinfo` (
2020
`uid` INTEGER PRIMARY KEY AUTOINCREMENT,
2121
`username` VARCHAR(64) NULL,
2222
`departname` VARCHAR(64) NULL,
2323
`created` DATE NULL
2424
);
25-
25+
```
2626
An example:
27-
27+
```Go
2828
package main
2929

3030
import (
@@ -101,11 +101,11 @@ An example:
101101
panic(err)
102102
}
103103
}
104-
104+
```
105105
You may have noticed that the code is almost the same as in the previous section, and that we only changed the name of the registered driver and called `sql.Open` to connect to SQLite in a different way.
106106

107107
Note that sometimes you can't use the `for` statement because you don't have more than one row, then you can use the `if` statement
108-
108+
```Go
109109
if rows.Next() {
110110
err = rows.Scan(&uid, &username, &department, &created)
111111
checkErr(err)
@@ -114,14 +114,14 @@ Note that sometimes you can't use the `for` statement because you don't have mor
114114
fmt.Println(department)
115115
fmt.Println(created)
116116
}
117-
117+
```
118118
Also you have to do a `rows.Next()`, without using that you can't fetch data in the `Scan` function.
119119

120120
Transactions
121121
===============
122122

123123
The above example shows how you fetch data from the database, but when you want to write a web application then it will not only be necessary to fetch data from the db but it will also be required to write data into it. For that purpose, you should use transactions because for various reasons, such as having multiple go routines which access the database, the database might get locked. This is undesirable in your web application and the use of transactions is effective in ensuring your database activities either pass or fail completely depending on circumstances. It is clear that using transactions can prevent a lot of things from going wrong with the web app.
124-
124+
```Go
125125
trashSQL, err := database.Prepare("update task set is_deleted='Y',last_modified_at=datetime() where id=?")
126126
if err != nil {
127127
fmt.Println(err)
@@ -137,7 +137,7 @@ The above example shows how you fetch data from the database, but when you want
137137
} else {
138138
tx.Commit()
139139
}
140-
140+
```
141141
As it is clear from the above block of code, you first prepare a statement, after which you execute it, depending on the output of that execution then you either roll it back or commit it.
142142

143143

en/05.4.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ I will use the first one in the examples that follow.
1515
## Samples
1616

1717
We create the following SQL:
18-
18+
```sql
1919
CREATE TABLE userinfo
2020
(
2121
uid serial NOT NULL,
@@ -25,9 +25,9 @@ We create the following SQL:
2525
CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
2626
)
2727
WITH (OIDS=FALSE);
28-
28+
```
2929
An example:
30-
30+
```Go
3131
package main
3232

3333
import (
@@ -102,20 +102,20 @@ An example:
102102
panic(err)
103103
}
104104
}
105-
105+
```
106106
Note that PostgreSQL uses the `$1, $2` format instead of the `?` that MySQL uses, and it has a different DSN format in `sql.Open`.
107107
Another thing is that the PostgreSQL driver does not support `sql.Result.LastInsertId()`.
108108
So instead of this,
109-
109+
```Go
110110
stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3);")
111111
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
112112
fmt.Println(res.LastInsertId())
113-
113+
```
114114
use `db.QueryRow()` and `.Scan()` to get the value for the last inserted id.
115-
115+
```Go
116116
err = db.QueryRow("INSERT INTO TABLE_NAME values($1) returning uid;", VALUE1").Scan(&lastInsertId)
117117
fmt.Println(lastInsertId)
118-
118+
```
119119
## Links
120120
121121
- [Directory](preface.md)

0 commit comments

Comments
 (0)