【Go】Go言語でDB接続 

<h1>【前提】</h1>
editor:VsCode

DB:data.sqlite3
機能:スキャナーへ入力してDMLが出来るように実装する。

//スキャナの生成の為のパッケージを作成します。
※ファイル名は拡張子をgoにする。→input.go等
```
package hello

import (
	"bufio"
	"fmt"
	"os"
)

func Input(msg string) string {
	scanner := bufio.NewScanner(os.Stdin)//入力を受け付けるスキャナ
	scanner.Scan()//入力を取得する
	return scanner.Text()//コンソールに出力
}
```
Go>src>の階層に上記ファイルを保存する。

<h1>【import】</h1>

※data.sqlite3のインストールの仕方については省きます。

```
package main

import (
	"database/sql"
	"fmt"
	"hello"
	"strconv"

	_ "github.com/mattn/go-sqlite3"
)

```

<h1>【構造体を作成】</h1>
レコードを保存する為の構造体を生成します。

```
type Mydata struct {
	ID   int
	Name string
	Mail string
	Age  int
}
```

<h1>【DBアクセス】</h1>


```
func main() {
    //ドライバ名:"sqlite3",データベース名:"data.sqlite3"
	con, er := sql.Open("sqlite3", "data.sqlite3")
	if er != nil {
		panic(er)
	}
	defer con.Close()　DBの開放処理

    //操作したDB操作を標準入力する
	flg := hello.Input("all or id or other or insert or update or delete ") 

    //上記標準入力に応じたメソッドが作動する。
	if flg == "all" {
		findAll(con) //全件検索
	} else if flg == "id" {
		findUserById(con) //ユーザID検索
	} else if flg == "other" {
		findUserByNameOrMail(con) //ユーザ名検索
	} else if flg == "insert" {
		insert(con) //ユーザ登録
	} else if flg == "update" {
		update(con) //ユーザ情報更新
	} else if flg == "delete" {
		delete(con) //ユーザ削除
	} else {
		fmt.Println("error") //エラー出力
		return
	}

}
```

<h1>【使用するクエリ文一覧】</h1>

```
var all string = "select * from mydata"
var qry string = "select * from mydata where id=?"
var qry2 string = "select * from mydata where name like ? or mail like ?"
var qry3 string = "insert into  mydata (name,mail,age) values(?,?,?)"
var qry4 string = "update mydata set name=?,mail=?,age=? where id=?"
var qry5 string = "delete from mydata where id=?"
```



<h1>【出力メソッド】</h1>

構造体の情報が「String型」で出力されるように調整します。
※strconv.Itoa()はint型をstring型に変換するメソッドです。
```
func (m *Mydata) Str() string {
	return "<\"" + strconv.Itoa(m.ID) + ":" + m.Name + "\"" + m.Mail + "," +
		strconv.Itoa(m.Age) + ">"
}
```

<h1>【レコード情報の取り出しメソッド】</h1>

ScanでMydata内の各変数に引数を設定する。
※Scanは現在のカーソルにあるレコードから情報を取り出します。
レコードかｒ赤くカラムの値を取り出し、それを引数に用意されている変数に代入します。
引数の&(アンパサンド)は参照値渡しになります。

```
func cursor(md *Mydata, rs *sql.Rows) *Mydata {
	er := rs.Scan(&md.ID, &md.Name, &md.Mail, &md.Age)
	if er != nil {
		panic(er)//取り込みに失敗したらエラーを返す
	}
	return md
}
```

<h1>【全件検索メソッド】</h1>

```
func findAll(con *sql.DB) {
    //変数rsはレコードの結果を格納する。
	rs, er := con.Query(all)
	if er != nil {
		panic(er)
	}
	for rs.Next() {
        //Nextメソッドはカーソルを次のレコードに移動させる。
		var md Mydata  //構造体を生成
		md = *cursor(&md, rs)  //cursorメソッドで構造にレコードを代入
		fmt.Println(md.Str()) //Str()でコンソールに構造体の情報を出力
	}

	fmt.Println("end")
}
```


<h1>【ユーザID検索】</h1>

```
func findUserById(con *sql.DB) {
	for true {
		s := hello.Input("id")
		if s == "" {
			break
		}
		n, er := strconv.Atoi(s)
		if er != nil {
			panic(er)
		}

		rs, er := con.Query(qry, n)
		if er != nil {
			panic(er)
		}
		for rs.Next() {
			var md Mydata
			md = *cursor(&md, rs)
			fmt.Println(md.Str())
		}

	}
	fmt.Println("end")
}
```

<h1>【名前またはメール検索】</h1>

```
func findUserByNameOrMail(con *sql.DB) {
	for true {
		s := hello.Input("findUserByNameOrMail")
		if s == "" {
			break
		}
		rs, er := con.Query(qry2, "%"+s+"%", "%"+s+"%")
		if er != nil {
			panic(er)
		}
		for rs.Next() {
			var md Mydata
			md = *cursor(&md, rs)
			fmt.Println(md.Str())
		}

		fmt.Println("end")
	}
}
```

<h1>【ユーザ登録】</h1>

```
func insert(con *sql.DB) {
	nm := hello.Input("name")
	ml := hello.Input("mail")
	age := hello.Input("age")
	ag, _ := strconv.Atoi(age)

	con.Exec(qry3, nm, ml, ag)
	fmt.Println("入力完了")
}

// 構造体の生成
func mydatafmRw(rs *sql.Row) *Mydata {
	var md Mydata
	er := rs.Scan(&md.ID, &md.Name, &md.Mail, &md.Age)
	if er != nil {
		panic(er)
	}
	return &md
}

```

<h1>【ユーザ情報変更】</h1>

```
func update(con *sql.DB) {
	ids := hello.Input("update ID")             //アップデートするIDを入力
	id, _ := strconv.Atoi(ids)                  //stringからintに変換
	rw := con.QueryRow(qry, id)                 //クエリの結果を格納
	tgt := mydatafmRw(rw)                       //クエリの結果から構造体を生成
	ae := strconv.Itoa(tgt.Age)                 //intからstringに変換
	nm := hello.Input("name(" + tgt.Name + ")") //変更後のユーザー名を入力
	ml := hello.Input("mail(" + tgt.Mail + ")") //変更後のメールアドレスを入力
	ge := hello.Input("age(" + ae + ")")        //変更後の年齢を入力
	ag, _ := strconv.Atoi(ge)

	//入力がなければ変更を加えない
	if nm == "" {
		nm = tgt.Name
	}
	if ml == "" {
		ml = tgt.Mail
	}
	if ge == "" {
		ag = tgt.Age
	}

	con.Exec(qry4, nm, ml, ag, id)
	fmt.Println("更新完了")

}
```

<h1>【ユーザ削除】</h1>

```
func delete(con *sql.DB) {
	idd := hello.Input("select id for deleting")
	id, er := strconv.Atoi(idd)
	if er != nil {
		panic(er)
	}

	con.Exec(qry5, id)
	fmt.Println("更新完了")
}
```

<h1>【実行】</h1>

```
all or id or other or insert or update or delete : all //DB操作を入力
//今回の場合であればユーザ一覧が表示される
<"1:Taro"taro@yamada,39> 
<"2:Hanako"hanako@flower,28>
<"3:Sachiko"sachiko@happy,17>
<"4:Jiro"jiro@change,6>
end
```