エンジニア採用担当がプログラミング頑張る話【25日目/2ヶ月間】
こんにちは、@hiroki_maekawaです。
今日の目標は下記です。
・AtCoderの問題1時間チャレンジ
・API経由でUPDATE/DELETEを行う
1. AtCoderの問題1時間チャレンジ
今日のATCoderの1問目の問題はこれです。
与えられた2つの文字をScanして、掛けて、2で割って余りが0ならEven、余りが1ならOddというコードが書ければ実現できそう!(な気がする)
掛け算と割り算の余りを実現できる記号をググり、途中でelseが使えるなと思い、下記コードを書きました。
package main
import "fmt"
func main() {
var a, b int
fmt.Scan(&a, &b)
if a*b%2 == 0 {
fmt.Println("Even")
} else {
fmt.Println("Odd")
}
}
そのまま提出したところ、Acceptされました。
簡単なものですが、初めて0から何も見ずにコード書くことができました!
続いて2問目。
N個分の全ての数字を2で割って、1つでも余りが1の数字があれば0と出力、余りが全て0なら何回2で割れるか求めるコードを書けば良いのでは?と考えました。
ただ、最後の「何回2で割れるか求める」コードをどのように書くのかのアイデアが出てきません。。とりあえず書けるところまで書いてみることにしました。
N個分の数字を管理するには配列使えば良いのか・・?と思い、書いて見たところ、non-constant array bound Nと言われてしまい、Goの配列はconstantな値でしか要素数を設定できない(配列では要素数は変更できない)そうなのでスライスを使うことにしました。
package main
import "fmt"
func main() {
var N int
fmt.Scan(&N)
a := make([]int, N)
for _, v := range a {
if v%2 != 0 {
fmt.Println(0)
}
}
}
0を出力するところまでは書いたところで、模範解答をチラ見しました。
すると、/=を使って、2でスライスの要素を割れる回数をカウントしていることが分かりました。
また、fmt.Println(0)を使わずに、v%2 != 0 であったらbreakしてしまってカウントを0にするという方法もなるほど、、!と思いました。
package main
import "fmt"
func main() {
var N int
fmt.Scan(&N)
//N個の要素を持つaというスライスを作る
A := make([]int, N)
//試しに値を入力してみる
N = 3
A = []int{8, 12, 40}
//インデックスiにaというスライスを代入
for i := range A {
fmt.Scan(A[i])
//fmt.Println(i) -> インデックス(添字)が出力される0, 1, 2
//fmt.Println(a[i]) -> 値が出力される8, 12, 40
}
ans := 0
for {
ok := true
for _, v := range A {
if v%2 != 0 {
ok = false
}
}
//もしokがtrueじゃなかったらここで中断
if !ok {
break
}
//A[i]というとして、スライスの要素全てを2で割りたいから、iを表示させるためにループ処理を行なっている
for i := range A {
A[i] /= 2
}
ans++
}
fmt.Println(ans)
}
この模範解答を理解したことで、iはインデックス(添字)であること、 また、A[i]として、スライスの要素全てを2で割りたいから、iを表示させるためにループ処理を行なっていることが分かり、スライスに関する理解を深めることができました。
これを自分で0から書けるよう、明日また復習したいと思います。
2. API経由でデータを更新する
データの内容を変更したい時、下記のようなupdate文を使って更新するそうです。
UPDATE table_reference
SET col_name1 = value1 [, col_name2 = value2, ...]
[WHERE where_condition]
mysql> Select * from gomysql;
+------+--------+-------+
| id | name | price |
+------+--------+-------+
| 1 | Apple | 300 |
| 2 | Orange | 200 |
| 3 | Grape | 500 |
| 4 | Banana | 100 |
+------+--------+-------+
4 rows in set (0.01 sec)
mysql>
現在データベースには4つの果物の値が入っているため、昨日追加したBananaのPriceを100から150に更新してみたいと思います。
ただここで一点、update文をupdate gomysql set price=100 where name=‘Banana’とし、Bananaをバッククォートで囲ってしまっていたためエラーが出てしまいました。MySQLからはシングルクォート、ダブルクォートなどで囲まないとBananaという文字が列名と誤解されてしまうそうです。
また、Goファイルに書く時にupdate gomysql set price=100 where name="Banana"のまま入れてしまうとダブルクォートが2重になってしまうのでどちらかをシングルクォートに直す必要がありました。
package main
import (
"database/sql"
"fmt"
"net/http"
_ "github.com/go-sql-driver/mysql"
"github.com/labstack/echo"
)
//Fruit 構造体
type Fruit struct {
ID int `json:"id"`
Name string `json:"name"`
Price int `json:"price"`
}
func main() {
//Echo立ち上げる
e := echo.New()
//GETリクエスト(ルーティング)
e.GET("/show", show)
//サーバー起動
e.Start(":9009")
}
func show(c echo.Context) error {
//接続
db, err := sql.Open("mysql", "root:password@/gomysql")
if err != nil {
fmt.Println(err)
}
defer db.Close()
//update文
_, err = db.Query("update gomysql set price=150 where name='Banana'")
if err != nil {
fmt.Println(err)
}
defer db.Close()
//複数レコードをselect -> ループ処理
rows, err := db.Query("select id, name, price from gomysql")
if err != nil {
fmt.Println(err)
}
fruits := make([]Fruit, 0)
//ループ処理 + Next関数
for i := 0; i < 4; i++ {
f := Fruit{}
rows.Next()
err = rows.Scan(&f.ID, &f.Name, &f.Price)
if err != nil {
fmt.Println(err)
}
fruits = append(fruits, f)
}
return c.JSON(http.StatusOK, fruits)
}
ちゃんと出力されました!
3. API経由でデータを削除する
次はDELETEです。Bananaを消したいと思います。
DELETE FROM tbl_name [WHERE where_condition]
MySQLの書式は上記なので、今回はidを使って値を消したいと思います。
DELETE FROM gomysql WHERE id = 4;
下記、delete文を入れて、ループ処理の条件を変えるだけです。
package main
import (
"database/sql"
"fmt"
"net/http"
_ "github.com/go-sql-driver/mysql"
"github.com/labstack/echo"
)
//Fruit 構造体
type Fruit struct {
ID int `json:"id"`
Name string `json:"name"`
Price int `json:"price"`
}
func main() {
//Echo立ち上げる
e := echo.New()
//GETリクエスト(ルーティング)
e.GET("/show", show)
//サーバー起動
e.Start(":9009")
}
func show(c echo.Context) error {
//接続
db, err := sql.Open("mysql", "root:password@/gomysql")
if err != nil {
fmt.Println(err)
}
defer db.Close()
//update文
_, err = db.Query("DELETE FROM gomysql WHERE id = 4")
if err != nil {
fmt.Println(err)
}
defer db.Close()
//複数レコードをselect -> ループ処理
rows, err := db.Query("select id, name, price from gomysql")
if err != nil {
fmt.Println(err)
}
fruits := make([]Fruit, 0)
//ループ処理 + Next関数
for i := 0; i < 3; i++ {
f := Fruit{}
rows.Next()
err = rows.Scan(&f.ID, &f.Name, &f.Price)
if err != nil {
fmt.Println(err)
}
fruits = append(fruits, f)
}
return c.JSON(http.StatusOK, fruits)
}
Bananaが削除された状態で出力されてます。
今日できるようになったこと
・API経由でMySQLのデータを更新
・API経由でMySQLのデータを削除
さいごに
AtCoderの問題を解くことで、基礎知識が深まっていくのを感じます。少しずつですが、自分で考えて0からコードが書けるように頑張っていきたいと思います。
あと、ブログに使う画像ネタがもうGopherのレパートリーしかないなぁと思い始めている状況です(笑)
それではまた!