pagetakaBlog

最近リフォームと鳥取県日南町の記事多め。写真、PC、ネット等の話題も

Go言語:爺の暴走…SQLiteつくるより既設MySQL利用が簡便じゃん…自暴自帰…?

【Go言語:データベース接続を、ポインタでうけとる関数(第21行)】
【Go言語:データベース接続を、ポインタでうけとる関数(第21行)】

Go言語で、自分が暴れ、気がついたら自分がやり始めたところへ帰着しそう、という頓珍漢な耄碌爺のお話です。

非力なPCをいたわる優しい爺…のようなふるまい。

これまでPythonを使い東京証券取引所日報をMySQLへ溜めてきました。今回、Go言語で、PythonでできたCSVを再利用しSQLiteへため込もうという目論見でした。しかし、新たにSQLite作るより、現状Pythonで使っているMySQLがあるじゃん、ということに気づいたわけです。似たようなデータを二つのデータベースに保管しなくても良くね?という流れです。

SQLiteこれまで使ったことなかったので、昨日までの流れ、Microsoft:Copilotに助けられ、勉強になりました。一晩して考えてみたら、横着の道が見えた…という次第です。
さっそく、Copilotの助けを借りながら、MySQLへの接続、読み出し、のスクリプトを書きました。どうやらできたみたい(な雰囲気、気配)なので、忘れぬうちに書き留めておきます。

昨日もどかしかった データベース接続例を今回は具体的に書くことができました。

golang:MySQLからデータ読み出し。サンプルスクリプト、途中だけど…。

すでにMySQLにデータがあるという前提です。それを、Go言語で読みに行く流れです。今回のスクリプトは、読み込んだデータを表示する手前までです、悪しからず。その代わりと言ってははばかられますが、昨日、実例を書いてなかったデータベースの接続を、渡す側関数が準備したあと、受取側関数がポインタでうけとる例を、実例でご紹介しています。そんなこと知ってるよ~という方は、読み飛ばしのほど。
また、掲載スクリプトをコピペしても期待通りには動かないと思います。悪しからず。絵に描いた餅は食えない…的な…。

package main

import(
	"fmt"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
)

func main(){
	fmt.Println("to use MySQL.")
	mysqlRoot := "root:@tcp(127.0.0.1:3306)/db_name"  // パスワード使ってない場合
	// mysqlRoot := "root:your_password@tcp(127.0.0.1:3306)/db_name"  // パスワード使ってる場合
	db, err := sql.Open("mysql", mysqlRoot)
	if err != nil {panic(err.Error())}
	defer db.Close()

	fmt.Println("using MySQL")
	err = readRDB(db)
	fmt.Println(err)
}

func readRDB(db *sql.DB) error{
	query := "SELECT * FROM `table_name` WHERE cd = ? ORDER BY date;"
	rows , err := db.Query(query, "9204")
	if err != nil { return err }
	fmt.Println("after reading MySQL / table_name")
	defer rows.Close()
	n := 0
	for rows.Next() {		
		n = n+1
		fmt.Printf( "now inside roop on %v   \r", n )
		// 本来ここは読込み済みデータを行毎に処理
	}
	fmt.Println()
return nil
}

main()側からreadRDB()側へデータベース接続の受け渡し。

main内の「db, err := sql.Open("mysql", mysqlRoot)」に「db」が初めて登場しています。その中身は一行上で、mysqlRootに格納した内容です。

このdbは、四行ほど下で「err = readRDB(db)」【先頭画像:第17行】と再利用されてます。dbの内容を「readRDB」関数に持って行ってね~的な意味かと思います。で、注目ポイントが、受取側の関数「func readRDB(db *sql.DB) 」【先頭画像:第21行】です。確かにdbを受け取っていますが、型が「*sql.DB」になっていて、普通の変数とかではないです。送り側・受取側の型が合致するのが普通かと思うのですが、Go言語ではこういうものだそうです。中身は、XXにあるから自分で拾ってきて~的な意味でしょうか…(怪)。

ふ~これで昨日の書ききれなかったストレスが飛びました。え?読んでるみなさんにストレスが移っただけ…。

Copilotに尋ねました:実際にデータを読み取っているのはどの部分?

readRDB内の「for rows.Next(){}」で何行あるかをnで数え表示したら、えらく速かったです。それで、Copilotに、MySQLから実際にデータを読みだしているのはどのスクリプトのどの部分か尋ねました。答えは、「rows , err := db.Query(query, "9204")」だそうです。これで読み込んだデータを、行毎に処理しているのが続くfor文になります。
読み込んだデータをそれぞれの項目に分け、構造体に格納し、スライスに収める、などの作業を行ってないので、より早く思えたのかもしれません。

「fmt.Printf( "now inside roop on %v \r", n )」のnで表される行数表示の数字、結局、終わった最後の数字しか見えませんでした…耄碌爺の目はそんなものです…(悲)。

Copilotは「並行処理」のことも教えてくれました。「MySQLから読み出す処理」と「読み込んだデータを整理格納」の作業を並行処理することは可能だそうです。どちらかの処理が遅れてもそれを調整する機能もある、との旨を教えてくれました。

少ないデータで試しても意味は無さそうな「並行処理」です。爺が現在保持するMySQLのデータは、14項目・3700行・700日分を超えました。約3,600万件の項目数です。これを一気に処理することがあるかどうか現在不明ですが、機会があれば「並行処理」を試してみたいと妄想中です。

耄碌爺の備忘録、齟齬などありましたら、優し目にご教示のほど。