這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。這個是我用Go寫的第一個東東,可能還存在些BUG沒有測試到。這裡主要是提供一個參考。各位可以改寫成自己的風格。
在命令列下輸入如下兩條命令,進行安裝
go get github.com/male110/SimpleDb go install github.com/male110/SimpleDb
Go語言的資料庫操作,只能用Rows.Scan來一次性讀取所有列。感覺很不習慣,我還是習慣按照列名來一列列的取資料。所以我自己封裝了一個資料結構MyRows,MyRows實現了一個函數,GetValue(name string, value interface{})可以按列名來取資料。如下所示:
err = rows.GetValue("IsBoy", &isBoy) if err != nil { fmt.Println(err) return }
為了操作方便,還定義了其它的結構體,如MyDb,其Query函數可以直接返回 MyRows。NewDb用來建立MyDb結構,其參數與sql.Open一至,怎麼傳取決於你所使用的驅動程式。
db, err := SimpleDb.NewDb("mysql", "root:123@tcp(127.0.0.1:3306)/test?charset=utf8") if err != nil { fmt.Println("開啟SQL時出錯:", err.Error()) return } var rows *SimpleDb.MyRows //從資料庫中取資料 rows, err = db.Query("select * from person") if err != nil { fmt.Println(err) return } //顯示資料 for rows.Next() { var id, age int var name string var isBoy bool //按欄位名取資料,也可以用rows.Scan(&id,&name,&age),來取 rows.GetValue("id", &id) rows.GetValue("name", &name) rows.GetValue("age", &age) //可以根據傳回值,判斷是否成功 err = rows.GetValue("IsBoy", &isBoy) if err != nil { fmt.Println(err) return } fmt.Println(id, "\t", name, "\t", age, "\t", isBoy) }
同時還時現了一個簡單的ORM,實現了最基本的插入資料,修改資料,刪除資料。 我一般使用ORM只用這麼幾個方法,其它的都是寫SQL語句。這裡只是一個參考,大家可以根據自己的需要,自己習慣,進行修改。改成自己需要的格式。資料結構的定義格式如下:
type Person struct { /*TableName類型只是用來設定表名。如果結構體名跟表名相同可以省略*/ TableName SimpleDb.TableName "person" /*name是表名,PK用來設定是否主鍵,true主鍵,false非主鍵*/ Id int `name:"id"PK:"true"Auto:"true"` Name string "name" //tag裡的name表是對應的欄位名 Age int "age" //tag裡的age表是對應的欄位名 IsBoy bool NotUse string "-" //-不會儲存到資料庫中}
上面的說明已經很詳細了, SimpleDb.TableName類型的欄位,只用來在tag中定義結構體對應的表名,如果沒有該欄位,認為表名就是結構體名相同。 PK:"true"表示是主鍵,Auto:"true"表示該欄位是自動成長的列,name:"id",來指定該欄位對應的資料表中的列名,如不指定認為 跟欄位名相同。當只需要指定列名時,可以直接寫在tag中,如:"name"、"age"。tag為"-"表示不對應資料表中的任何列。
// 插入資料p := &Person{Name: "張三丰", Age: 500, IsBoy: true}db.Insert(p)//修改資料db.Update(p)//刪除資料db.Delete(p)
下面來看一個完整的例子,首先他創表:
CREATE TABLE `person` ( `id` INT(50) NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) NULL DEFAULT NULL, `age` INT(50) NULL DEFAULT NULL, `IsBoy` SMALLINT(10) NULL, PRIMARY KEY (`id`))COLLATE='utf8_general_ci';insert into `person` (name,age,IsBoy) values('張三',20,0);insert into `person` (name,age,IsBoy) values('王五',19,1);
下面是完整的代碼
package mainimport ( "fmt" _ "github.com/go-sql-driver/mysql" "github.com/male110/SimpleDb")type Person struct { /*TableName類型只是用來設定表名。如果結構體名跟表名相同可以省略*/ TableName SimpleDb.TableName "person" /*name是表名,PK用來設定是否主鍵,true主鍵,false非主鍵*/ Id int `name:"id"PK:"true"Auto:"true"` Name string "name" //tag裡的name表是對應的欄位名 Age int "age" //tag裡的age表是對應的欄位名 IsBoy bool NotUse string "-" //-不會儲存到資料庫中}func main() { db, err := SimpleDb.NewDb("mysql", "root:123@tcp(127.0.0.1:3306)/test?charset=utf8") if err != nil { fmt.Println("開啟SQL時出錯:", err.Error()) return } defer db.Close() p := &Person{Name: "張三丰", Age: 500, IsBoy: true} //插入一條資料 err = db.Insert(p) if err != nil { fmt.Println(err) return } fmt.Println("新插入資料的ID:", p.Id) var rows *SimpleDb.MyRows //從資料庫中取資料 rows, err = db.Query("select * from person") if err != nil { fmt.Println(err) return } //顯示資料 for rows.Next() { var id, age int var name string var isBoy bool //按欄位名取資料,也可以用rows.Scan(&id,&name,&age),來取 rows.GetValue("id", &id) rows.GetValue("name", &name) rows.GetValue("age", &age) //可以根據傳回值,判斷是否成功 err = rows.GetValue("IsBoy", &isBoy) if err != nil { fmt.Println(err) return } fmt.Println(id, "\t", name, "\t", age, "\t", isBoy) } //輸出分割線 fmt.Println("==========割割割割割割割割============") p.Name = "彭祖" p.Age = 800 //修改資料 _, err = db.Update(p) if err != nil { fmt.Println(err, "xxxx") return } //QueryDataRows返回一個DataRow數組,DataRow中有一map來存允許存取中的資料 var arrRow []SimpleDb.DataRow arrRow, err = db.QueryDataRows("select * from person") if err != nil { fmt.Println(err, "zzzzz") return } for _, row := range arrRow { var id, age int var name string var isBoy bool //只能按欄位名取資料 row.GetValue("id", &id) row.GetValue("name", &name) row.GetValue("age", &age) //可以根據傳回值,判斷是否成功 err = rows.GetValue("IsBoy", &isBoy) if err != nil { fmt.Println(err) return } fmt.Println(id, "\t", name, "\t", age, isBoy) } var p2 Person p2.Id = p.Id //根據主鍵從資料庫中取單條資料 err = db.Load(&p2) if err != nil { fmt.Println(err) return } fmt.Println(p2) //根據主鍵刪除一條資料 db.Delete(p2)}