- 投稿日:2020-07-13T19:49:49+09:00
Golangでプログレスバーを表示するためのパッケージ3選
Golangで処理を書いている時、特に時間がかかる処理の場合、進捗がどのくらい進んでいるのかを知りたい時がありますよね。そんな時使うのがプログレスバーだったりするわけですが、いい感じで利用できるパッケージがないか探してみると思いの外見つかったので3つリストアップしてみました!
リストアップするだけだと味気ないのでfor文を回す処理を利用してそれぞれ出力してみました。
マルチプログレスバーについての記事も書いているので興味のある方はこちらも是非!
Golangでマルチプログレスバーを表示したい!!pb
今回紹介する3つの中でスター数が2.7kと一番多い人気のパッケージです。人気なだけあって柔軟性が高そうな印象を受けました。
以下のコマンドでインストールできます。
terminalgo get github.com/cheggaaa/pb/v3
pbをインストールして以下のサンプルを実行してみました。
main.gopackage main import ( "time" "github.com/cheggaaa/pb/v3" ) func main() { count := 100 bar := pb.Simple.Start(count) bar.SetMaxWidth(80) for i := 0; i < count; i++ { bar.Increment() time.Sleep(time.Millisecond * 30) } bar.Finish() }動かした結果がこれ。
uiprogress
同時に複数の進行状況バーをレンダリングでき、また、新しく処理が追加された場合でも追加の進行状況バーを追加できるようです。
以下のコマンドでインストールできます。
terminalgo get -v github.com/gosuri/uiprogress
uiprogressをインストールして以下のサンプルを使って実行してみました。
main.gopackage main import ( "time" "github.com/gosuri/uiprogress" ) func main() { count := 100 uiprogress.Start() bar := uiprogress.AddBar(count) bar.AppendCompleted() bar.PrependElapsed() for bar.Incr() { time.Sleep(time.Millisecond * 20) } }実行結果がこれ。
progressbar
OSに依存せず利用できる、非常にシンプルなスレッドセーフなプログレスバーと言う謳い文句で案内されています。
以下のコマンドでインストールできます。
terminalgo get -u github.com/schollz/progressbar
progressbarをインストールして以下のサンプルを使って実行してみました。
main.gopackage main import ( "time" "github.com/schollz/progressbar" ) func main() { count := 100 count64 := int64(count) bar := progressbar.Default(count64) for i := 0; i < count; i++ { bar.Add(1) time.Sleep(40 * time.Millisecond) } }実行するとこんな感じ
まとめ
個人的に、使い心地と見た目でpbが好みでした。
これ採用して早速実装してみます!
- 投稿日:2020-07-13T16:25:33+09:00
Goでのswitchを用いた条件分岐
背景
Javaで散々苦しんだswitch文、Goにも出てきたのでまとめます
環境
go version go1.14.4
windows10まとめ
JavaとGoのswitch文の大きな違い
Java
条件に合致した際に次の処理を実施しないようにするにはbreakが必要
Go
条件に合致したら次の処理は実施されない。
実施したい場合はfallthroughを入れる必要がある
※型でのswitchの場合は使用できないソースと実行例
main.gopackage main import ( "fmt" ) // 型アサーションを用いたスイッチの使用例 func main() { // 変数aをすべての型を取れるinterface{}型として定義し、999.999を入れる var a interface{} = 999.999 // aの型でswitchする // [変数名].(type)で型が取得できる switch a.(type) { case bool: fmt.Printf("bool") case int, uint: fmt.Printf("int or uint") case string: fmt.Printf("string") case float64: fmt.Printf("float") case rune: fmt.Printf("rune") default: fmt.Println("don't know") } }実行例
C:\go>go run main.go float999.999はfloat64の型に入るのでその出力。
後の実装のrune, defaultは実行されない。
- 投稿日:2020-07-13T15:05:04+09:00
golangでミニマムなREST APIを作る
この記事は何?
注) golang初学者の私が初学者のために書いています。
https://tutorialedge.net/golang/creating-restful-api-with-golang/ のチュートリアル(英語だったが平易な文章で書かれてる。本当に)の内容をベースにして、challengeにあるupdate機能の追加の問題とMySQLを導入してみたという掛け算的内容です。
なので、上記チュートリアルが終了した段階からスタートするため悪しからず。チュートリアル中のコードで参考になったこと。
https://qiita.com/ngplus6655/items/a38660313383d3ff2136環境
ubuntu18.04LTS
go1.12.17 linux/amd64github.com/gorilla/mux
github.com/jinzhu/gormupdateArticleを追加
まずはチュートリアル中のchallengeの内容を説いてみた
func updateArticle(w http.ResponseWriter, r *http.Request){ vars := mux.Vars(r) id := vars["id"] reqBody, _ := ioutil.ReadAll(r.Body) var updateArticle Article json.Unmarshal(reqBody, &updateArticle) for index, article := range Articles { if article.Id == id { updateArticle.Id = id Articles[index] = updateArticle } } }returnSingleArticleと同様urlのidパラメータから編集するarticleを特定し、直接Articlesスライスの要素に代入しています。
直前にupdateArticle.Id = idとしているのは、パラメータidと送られたjsonデータのidが不一致だとArticleに対してIDがユニークではなくなるため。マルチプレクサにupdateArticleを登録
myRouter.HandleFunc("/article/{id}", updateArticle).Methods("PUT")curlしてみる
curl -X PUT -H "Content-Type: application/json" -d '{"id": "1", "Title": "Updated Post", "desc": "the description for my updated post", "content": "my articles content"}' http://localhost:10000/article/1 curl -X GET http://localhost:10000/all [{"Id":"1","Title":"Updated Post","desc":"the description for my updated post","content":"my articles content"}, {"Id":"2","Title":"Hello 2","desc":"Article Description","content":"Article Content"}, {"Id":"3","Title":"Hello 3","desc":"Article Description","content":"Article Content"}]意図したとおりにidが1の要素を更新できました。
mysqlの導入
完成形
main.gopackage main import ( "fmt" "log" "net/http" "encoding/json" "io/ioutil" "strconv" "github.com/gorilla/mux" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) type Article struct { gorm.Model Title string `json:"Title"` Desc string `json:"desc"` Content string `json:"content"` } type Articles []Article func connectDB() (*gorm.DB, error) { db, err := gorm.Open("mysql", "ユーザ名:パスワード@/test?charset=utf8&parseTime=True&loc=Local") return db, err } func initDb() *gorm.DB { db, err := connectDB() if err != nil { log.Fatalln("データベースの接続に失敗しました。") } return db } func idParamToUint(r *http.Request) uint { vars := mux.Vars(r) id, _ := strconv.Atoi(vars["id"]) var uid uint = uint(id) return uid } func ParseJsonArticle(w http.ResponseWriter ,r *http.Request) Article { reqBody, _ := ioutil.ReadAll(r.Body) var article Article json.Unmarshal(reqBody, &article) json.NewEncoder(w).Encode(article) return article } func homePage(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "Welcome to the HomePage!") fmt.Println("Endpoint Hit: homePage") } func returnAllArticles(w http.ResponseWriter, r *http.Request){ fmt.Println("Endpoint Hit: returnAllArticles") db := initDb() var articles Articles db.Find(&articles) json.NewEncoder(w).Encode(articles) } func returnSingleArticle(w http.ResponseWriter, r *http.Request){ fmt.Println("called returnSingleArticle") uid := idParamToUint(r) db := initDb() var article Article db.Where("id = ?", uid).First(&article) json.NewEncoder(w).Encode(article) } func createNewArticle(w http.ResponseWriter, r *http.Request) { fmt.Println("called createNewArticle") db := initDb() article := ParseJsonArticle(w, r) db.Create(&article) if db.NewRecord(article) { log.Println("新規articleの保存に失敗しました。") } } func updateArticle(w http.ResponseWriter, r *http.Request){ fmt.Println("called updateAtricle") uid := idParamToUint(r) db := initDb() updatedArticle := ParseJsonArticle(w, r) var article Article db.Where("id = ?", uid).First(&article) article.Title = updatedArticle.Title article.Desc = updatedArticle.Desc article.Content = updatedArticle.Content db.Save(&article) } func deleteArticle(w http.ResponseWriter, r *http.Request) { fmt.Println("called deleteAtricle") uid := idParamToUint(r) db := initDb() db.Delete(Article{}, "id = ?", uid) } func handleRequests() { myRouter := mux.NewRouter().StrictSlash(true) myRouter.HandleFunc("/", homePage) myRouter.HandleFunc("/all", returnAllArticles) myRouter.HandleFunc("/article/{id}", returnSingleArticle).Methods("GET") myRouter.HandleFunc("/article", createNewArticle).Methods("POST") myRouter.HandleFunc("/article/{id}", updateArticle).Methods("PUT") myRouter.HandleFunc("/article/{id}", deleteArticle).Methods("DELETE") log.Fatal(http.ListenAndServe(":10000", myRouter)) } func main() { fmt.Println("Rest API v2.0 - Mux Routers") db, err := connectDB() if err != nil { log.Fatalln("データベースの接続に失敗しました。") } defer db.Close() db.AutoMigrate(&Article{}) handleRequests() }MySQLのインストール
$ sudo apt install mysql-server mysql-client $ mysql --version mysql Ver 14.14 Distrib 5.7.30, for Linux (x86_64) using EditLine wrapper起動
$ sudo service mysql start初期設定->データベース作成->ユーザ追加
参考 https://qiita.com/houtarou/items/a44ce783d09201fc28f5
$ sudo mysql_secure_installation $ sudo mysql -u root -p mysql> CREATE DATABASE test; mysql> set global validate_password_policy=LOW; mysql> CREATE USER '名前'@'localhost' IDENTIFIED BY 'パスワード'; mysql> grant all on test.* to ユーザ名@localhost;Article構造体の再定義
type Article struct { gorm.Model Title string `json:"Title"` Desc string `json:"desc"` Content string `json:"content"` } type Articles []ArticleIDやらタイムスタンプをGORMのモデル構造体に切り替えます。
スライスのArticlesはもう使いませんが一括で扱うところが出てくるので型として定義します。データベース接続
func connectDB() (*gorm.DB, error) { db, err := gorm.Open("mysql", "ユーザ名:パスワード@/テーブル名?charset=utf8&parseTime=True&loc=Local") return db, err } func initDb() *gorm.DB { db, err := connectDB() if err != nil { log.Fatalln("データベースの接続に失敗しました。") } return db }/all
func returnAllArticles(w http.ResponseWriter, r *http.Request){ db := initDb() var articles Articles db.Find(&articles) json.NewEncoder(w).Encode(articles) }先に定義した構造体をインスタンス化し、db.find関数ですべての行のデータを格納します。
/article/{id} GET
func idParamToUint(r *http.Request) uint { vars := mux.Vars(r) id, _ := strconv.Atoi(vars["id"]) var uid uint = uint(id) return uid } func returnSingleArticle(w http.ResponseWriter, r *http.Request){ uid := idParamToUint(r) db := initDb() var article Article db.Where("id = ?", uid).First(&article) json.NewEncoder(w).Encode(article) }urlパラメータのidはstring型ですが、MySQLに登録されているidはuint型です。そのためstring型をuint型に型変換する関数の定義をしています。
strconvパッケージのstringToUintは、uint64型がreturnされてしまうため使わず、いったんint型にしています。
それから、GORMのdb.Where関数つかってidが一致するarticleを一つだけ取り出します。/article POST
func ParseJsonArticle(w http.ResponseWriter ,r *http.Request) Article { reqBody, _ := ioutil.ReadAll(r.Body) var article Article json.Unmarshal(reqBody, &article) json.NewEncoder(w).Encode(article) return article } func createNewArticle(w http.ResponseWriter, r *http.Request) { fmt.Println("called createNewArticle") db := initDb() article := ParseJsonArticle(w, r) db.Create(&article) if db.NewRecord(article) { log.Println("新規articleの保存に失敗しました。") } }まずは、関数として(updateでも再利用するため)リクエストボディで送られてくるJSONをパースし、構造体として扱えるようにします。
GORMのCreate関数でMySqlにあたらしい行を追加します。※ 編集しました(2020/7/16)
log.Fatalln -> log.Printlnに変更しました。
データの保存に失敗したときにプログラムを終了させる必要はないと考えるからです。/article/{id} PUT
func updateArticle(w http.ResponseWriter, r *http.Request){ uid := idParamToUint(r) db := initDb() updatedArticle := ParseJsonArticle(w, r) var article Article db.Where("id = ?", uid).First(&article) article.Title = updatedArticle.Title article.Desc = updatedArticle.Desc article.Content = updatedArticle.Content db.Save(&article) }CRUDで最も複雑なupdateですが、今までの組み合わせで実現できました。ここでは、Article構造体を二つインスタンス化させています。
一つはMySQLから引っ張ってきたデータ用、もう一つはリクエストボディから更新後のデータとして入ってくるupdatedArticleで、一つ目のArticleに二つ目のupdatedArticleを代入後Save関数を呼び出しています。/article/{id} DELETE
func deleteArticle(w http.ResponseWriter, r *http.Request) { uid := idParamToUint(r) db := initDb() db.Delete(Article{}, "id = ?", uid) }GORMのDelete関数によって簡単に実装できました
handleRequests関数
func handleRequests() { myRouter := mux.NewRouter().StrictSlash(true) myRouter.HandleFunc("/", homePage) myRouter.HandleFunc("/all", returnAllArticles) myRouter.HandleFunc("/article/{id}", returnSingleArticle).Methods("GET") myRouter.HandleFunc("/article", createNewArticle).Methods("POST") myRouter.HandleFunc("/article/{id}", updateArticle).Methods("PUT") myRouter.HandleFunc("/article/{id}", deleteArticle).Methods("DELETE") log.Fatal(http.ListenAndServe(":10000", myRouter)) }ポイントは、"article/{id}" の.Methods("GET")省略していないところです。
仮に省略してしまうとPUTやDELETEをつけてcurlしても、すべてGETメソッドのreturnSingleArticle関数にルーティングされてしまいます。まとめ
GORMとGorilla/muxパッケージでいい感じにRestAPIを作れた。
特にGORMに関しては、公式ページが日本語化されていて楽だった。
急いでクライアント側も作らなくては!
- 投稿日:2020-07-13T11:33:51+09:00
Go製インタプリタに見る動的値型まとめ
Go言語でインタプリタを作っているのだが、動的値型の宣言の仕方でぜんぜん実行速度が変わってくるので、メンテナンス性と実行速度いろいろ検討してみる。
構造体に全部の型を詰め込むパターン
動的値型を作る上で最も直感的に使えるのが全部の型を構造体に詰め込むパターン。あまり考えなくても使えるがメモリ効率はよくない。
struct.gotype Value struct { TypeNo int IntValue int StrValue string } // 必要な時に変換関数を呼ぶ func (v *Value) ToInt() int { if TypeNo==TypeInt { return v.IntVaue } if TypeNo==TypeStr { return StrToInt(v.StrValue) } } func (v *Value) ToString() string { ... }全てをinterface{}で表現するパターン
動的値型をinterface{}で表す方法。必要に応じて、任意の型にキャストして使う。キャストが面倒なので使い勝手は良くない上に間違えると落ちる。しかし、Go言語の機能を使うため動作速度は比較的早い。メモリも必要最小限。
if1.gotype Value interface{} // switchで型を分けて使う func ToInt(v Value) int { switch v := v.(type) { case int: return v.(int) case string: return StrToInt(v.(string)) default: return 0 } } func ToString(v Value) string { ... }
- (参考) go-lua > types.go
- (参考) DCLua > value.go
Goの型を利用しつつinterfaceで変換メソッドを用意
Goの型を利用しつつもメソッドを追加して共通型として利用する。メモリ効率もよくinterfaceの良さを活かしつつ、それなりに安全に運用できる。Gopher-luaの作者の型はこの部分が動作ネックになっているとブログに書かれていたが、Go製のLuaの中ではGopher-luaは速い方。
if2.gotype Value interface { ValueType() int ToInt() int ToString() string } type MyInt int func (p MyInt) ToInt() { return p } func (p MyInt) ToString() { return IntToStr(p) } type MyStr string func (p MyStr) ToInt() { return StrToInt(p) } func (p MyStr) ToString() { return p }interface{}を利用しつつも構造体に閉じ込める
内部的には、interface{}を利用しつつも、構造体とそのメソッドと安全に動的値型を操作できる。ただし、動的値型を生成する際に、一枚皮を被せているので、インタプリタ実装時大きなオーバーヘッドが必要となる。この記事執筆時点なでしこGo版では、この方式を採用しているが、値型の生成がとにかく遅い。
structif.gostruct Value { ValueType int value interface{} } func (v *Value) ToInt() int { switch value.(type) { case int: return v.value.(int) case string: return StrToInt(v.value.(string)) } }
- (参考) なでしこ3Go > value.go
なお、筆者が作っている日本語プログラミング言語「なでしこ」のGo言語実装版はこちら。
その他
その他、参考になりそうな点
- 投稿日:2020-07-13T10:03:31+09:00
【Go】SQLBoilerの使い方【ORM】
SQLBoiler とは
タイトル通り、Go言語のORMです。とりあえず一次ソース貼っておくので一緒に見ましょう。一次ソースです
GoのORMはGORMしか使用経験がありませんが、サクッと自分の思ったことをまとめました。
SQLBoilerを使用したソースコードはこちら。特徴
- DBを作成してマンドを打つと構造体を自動で生成してくれて、InsertやQueryなどができるようになる
- (メリット)他のORMよりパフォーマンスが良い(README参照)
- (メリット)Goのstructとしても活用しやすい
- (デメリット)ソースが少ない
実装手順
- DB作成
- DB接続
- 導入
- tomlファイル作成
- SQL文記述
- データのやりとり
開発環境
Mac OS Catalina 10.15.5
Go 1.14
MySQL 8.0.191.DB作成
(この記事にたどり着くような人は1と2は見なくてもサクッとできそうですが、、わかるわ。と思ったら手順3まで飛ばしてください。)
今回はMySQLを使用します。
をしてください。この手順にある処理はググったらいっぱい出てくると思うので詳しくは書きません。mysqlに入っていろいろするだけです。僕は結構優しいのでリンクは一応貼ってます。
権限付与はデータベースレベルで
grant all on DB名.* to 'ユーザー名' with grant option;
とかでいけると思います。2. DB接続
次に、DBに接続します。
main.gofunc New() *sql.DB { db, err := sql.Open("mysql", "ユーザー名:パスワード@/DB名?charset=utf8mb4&parseTime=true") if err != nil { panic(err) } return db }3.導入
ターミナルgo get -u github.com/volatiletech/sqlboiler go get github.com/volatiletech/sqlboiler/drivers/sqlboiler-mysql4.tomlファイル作成
ルートディレクトリにtomlファイルを作ります。
ターミナルtouch sqlboiler.toml必要事項を記述します。
- pkgname...作成したいパッケージ名を指定
- output...ルートディレクトリから見て、ファイルを生成したいディレクトリの場所
- dbname, user, pass ...DB名、ユーザー名、パスワード
- [mysql]は使用しているデータベースの種類を指定しています
sqlboiler.tomlpkgname="entity" output="domain/entity" [mysql] dbname = "exampledb" host = "localhost" port = 3306 user = "root" pass = "password" sslmode= "false"5.SQL文記述
SQLの文法をもとに下のようなファイルを作成しました。記事も後半になって僕が優しくなくなってきたので解説はしません。
関係は user:review が1:多で、CONSTRAINT..の部分で外部キー接続もしています。schema.sqlCREATE TABLE `users` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `deleted_at` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `reviews` ( `id` bigint NOT NULL AUTO_INCREMENT, `text` text NOT NULL, `user_id` bigint NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `deleted_at` datetime DEFAULT NULL, PRIMARY KEY (`id`), CONSTRAINT `user_reviews_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;ユーザー名、パスワード、DB名を入れてスキーマを作成し、
ターミナル$ mysqldef -uroot -ppassword exampledb < schema.sql実行します。
$ sqlboiler mysql上記2つのコマンドはSQLに変更を加えるときに使うので、Makefileとかのタスクランナー で自動化しておくと良いと思います。
自分の指定したディレクトリ以下に大量のファイルが生成されたら成功です。自分の作成したテーブルのファイルを見てるとこんなんがあると思います。
users.go// 省略 type User struct { ID int64 `boil:"id" json:"id" toml:"id" yaml:"id"` Name string `boil:"name" json:"name" toml:"name" yaml:"name"` CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` UpdatedAt time.Time `boil:"updated_at" json:"updated_at" toml:"updated_at" yaml:"updated_at"` DeletedAt null.Time `boil:"deleted_at" json:"deleted_at,omitempty" toml:"deleted_at" yaml:"deleted_at,omitempty"` R *userR `boil:"-" json:"-" toml:"-" yaml:"-"` L userL `boil:"-" json:"-" toml:"-" yaml:"-"` } // 省略6. データのやり取り
ファイルの生成ができたら、いよいよデータのやりとりを行います。
INSERTもできますが今回はSELECTを扱います。事前にデータを入れているReviewsテーブルの(削除されていない)id=1のデータを取ってきます。
(ルーティングの記述は省略しています。)main.gofunc handler(w http.ResponseWriter, r *http.Request) { conn := db.New() ctx := r.Context() var id int64 = 1 review, err := entity.Reviews( // entityパッケージのReviewsテーブルからIDカラムを条件にidと等しいデータをSELECT entity.ReviewWhere.ID.EQ(id), entity.ReviewWhere.DeletedAt.IsNull(), ).One(ctx, conn) if err != nil { fmt.println(err) return } fmt.Println("----------review----------") fmt.Println(review) return }詳しい文法については一次ソースを参照してもらえるとわかるのではないかと思います。(上の例はQueryBuildingあたりに書いてる)
あとは実行すると、Reviewがprintされるはずです。
ターミナル$ go run main go手順としては終了ですが、最後に外部キーの例だけ載せておきます。
上記例でDBで外部キーで紐づけている前提で、main.goreview, err := entity.Reviews( entity.ReviewWhere.ID.EQ(id), entity.ReviewWhere.DeletedAt.IsNull(), qm.Load("User") ).One(ctx, conn) fmt.Println(review.R.User)とすると、UsersテーブルのUserをEagerLoadingで取ってくることができます。(has_manyの関係なら複数形にする)
以上になります。間違い誤字脱字等あればご指摘いただけると幸いです?♂️
- 投稿日:2020-07-13T09:50:03+09:00
GoでGORMとTwitterAPIを使ったミニミニアプリ作ってみた
プログラミング歴3ヶ月目に突入しました!
GoでGORMとTwitterAPIを使ったアプリと言っていいのかすらわからないアプリを作りました!
GitHubに置いてあるのでよかったら見てください!(https://github.com/souhub/buzz_tweet)
そんなミニミニミニアプリですが、Railsでツイッター風アプリを作ったぶりの達成感とワクワクを感じることができました。
TwitterAPIを使って任意のユーザーの直近100件のツイート(リプとRTを含む)を取得して、GORMでデータベース操作していいねやRTが多い順や少ない順に並び替えるアプリです。こんな感じ
これがホーム画面でここでツイートを並べ替えたい人のユーザーIDを入力し、何順に並びかえるか選択します。
ここでは例として安倍首相のツイートをリツイートが多い順に並び替えるを選択しました。
そして検索ボタンを押すとこのように並び替えられたページに移動します。
写真なのでこの下が全く見えないですが、スクロールするとズラーっと並んでいます。
反省点
- 並び替える直近100件をその人がツイートしたもののみ(リプ、リツイートしたものを含まない)にしたかったができなかった点。
- 一度検索してホーム画面に戻ったらデータベースを削除するようにしたかったが、アプリを落とさない限りデータベースを削除できなかった点。
- CSSファイルを別ファイルに書いて読み込もうとしたができなかった点。笑
感想
初めてAPIを使ったアプリを作成したが本当に時間を忘れるくらい楽しかったです。
自分の思い通りに作成できなかった点がいくつかあり悔しかったのでもっと勉強して使いこなせるようになりたいです。参考
- 投稿日:2020-07-13T07:44:35+09:00
go修行19日目 データベース
データベース作成
INSERT
package main import ( "database/sql" "log" _ "github.com/mattn/go-sqLite3" ) var DbConnection *sql.DB func main() { DbConnection, _ := sql.Open("sqlite3", "./example.sql") defer DbConnection.Close() // テーブル作成 cmd := `CREATE TABLE IF NOT EXISTS person( name STRING, age INT)` _, err := DbConnection.Exec(cmd) // エラーハンドリング if err != nil { log.Fatalln(err) } // レコードINSERT cmd = "INSERT INTO person (name, age) VALUES (?, ?)" _, err = DbConnection.Exec(cmd, "Nancy", 20) if err != nil { log.Fatalln(err) } }PS C:\Users\yuta\go\src\semaphore> sqlite3 .\example.sql SQLite version 3.32.3 2020-06-18 14:00:33 Enter ".help" for usage hints. sqlite> .table person sqlite> sqlite> select * from person; Nancy|20SELECT
package main import ( "database/sql" "fmt" "log" _ "github.com/mattn/go-sqLite3" ) var DbConnection *sql.DB type Person struct { Name string Age int } func main() { DbConnection, _ := sql.Open("sqlite3", "./example.sql") defer DbConnection.Close() // テーブル作成 cmd := `CREATE TABLE IF NOT EXISTS person( name STRING, age INT)` _, err := DbConnection.Exec(cmd) // エラーハンドリング if err != nil { log.Fatalln(err) } // レコードINSERT cmd = "SELECT * FROM person where age = ?" row := DbConnection.QueryRow(cmd, 20) var p Person err = row.Scan(&p.Name, &p.Age) if err != nil { if err == sql.ErrNoRows { log.Println("No row") } else { log.Println(err) } } fmt.Println(p.Name, p.Age) }Nancy 20
```DELETE
package main import ( "database/sql" "log" _ "github.com/mattn/go-sqLite3" ) var DbConnection *sql.DB type Person struct { Name string Age int } func main() { DbConnection, _ := sql.Open("sqlite3", "./example.sql") defer DbConnection.Close() // テーブル作成 cmd := `CREATE TABLE IF NOT EXISTS person( name STRING, age INT)` _, err := DbConnection.Exec(cmd) // エラーハンドリング if err != nil { log.Fatalln(err) } // レコードDELETE cmd = "DELETE FROM person WHERE name = ?" _, err = DbConnection.Exec(cmd, "Nancy") if err != nil { log.Fatalln(err) } }教材
https://www.udemy.com/course/go-fintech/learn/lecture/12088980
- 投稿日:2020-07-13T07:44:35+09:00
go修行20日目 データベース
データベース作成
INSERT
package main import ( "database/sql" "log" _ "github.com/mattn/go-sqLite3" ) var DbConnection *sql.DB func main() { DbConnection, _ := sql.Open("sqlite3", "./example.sql") defer DbConnection.Close() // テーブル作成 cmd := `CREATE TABLE IF NOT EXISTS person( name STRING, age INT)` _, err := DbConnection.Exec(cmd) // エラーハンドリング if err != nil { log.Fatalln(err) } // レコードINSERT cmd = "INSERT INTO person (name, age) VALUES (?, ?)" _, err = DbConnection.Exec(cmd, "Nancy", 20) if err != nil { log.Fatalln(err) } }PS C:\Users\yuta\go\src\semaphore> sqlite3 .\example.sql SQLite version 3.32.3 2020-06-18 14:00:33 Enter ".help" for usage hints. sqlite> .table person sqlite> sqlite> select * from person; Nancy|20SELECT
package main import ( "database/sql" "fmt" "log" _ "github.com/mattn/go-sqLite3" ) var DbConnection *sql.DB type Person struct { Name string Age int } func main() { DbConnection, _ := sql.Open("sqlite3", "./example.sql") defer DbConnection.Close() // テーブル作成 cmd := `CREATE TABLE IF NOT EXISTS person( name STRING, age INT)` _, err := DbConnection.Exec(cmd) // エラーハンドリング if err != nil { log.Fatalln(err) } // レコードINSERT cmd = "SELECT * FROM person where age = ?" row := DbConnection.QueryRow(cmd, 20) var p Person err = row.Scan(&p.Name, &p.Age) if err != nil { if err == sql.ErrNoRows { log.Println("No row") } else { log.Println(err) } } fmt.Println(p.Name, p.Age) }Nancy 20
```DELETE
package main import ( "database/sql" "log" _ "github.com/mattn/go-sqLite3" ) var DbConnection *sql.DB type Person struct { Name string Age int } func main() { DbConnection, _ := sql.Open("sqlite3", "./example.sql") defer DbConnection.Close() // テーブル作成 cmd := `CREATE TABLE IF NOT EXISTS person( name STRING, age INT)` _, err := DbConnection.Exec(cmd) // エラーハンドリング if err != nil { log.Fatalln(err) } // レコードDELETE cmd = "DELETE FROM person WHERE name = ?" _, err = DbConnection.Exec(cmd, "Nancy") if err != nil { log.Fatalln(err) } }教材
https://www.udemy.com/course/go-fintech/learn/lecture/12088980