- 1. go言語 time.Format() time.Round() の挙動に注意
- 2. 動かして覚える!Goでデータベースの基本的な接続方法とCRUD操作
- 3. GoでLinebotとLIFFを使ってGoogleDriveとMoneyForwardに領収書をアップロードしてみる
- 4. koanfの罠:空文字をスライスにUnmarshalしても空スライスにならない
- 5. Laravelのようなmake controllerコマンドをGoで作成
- 6. Golangでrubyライクな配列処理をしたい!
- 7. Goでコマンド作成
- 8. GoでCORSの設定
- 9. GoのWebサービスでJSONを構造体に変換し、構造体をJsonに戻す
- 10. GoのWebサービスでhtmlを返す
- 11. Goでリクエストのたびに認証を行う
- 12. Goで毎回のリクエスト毎にログを出力
- 13. Goで静的ファイルを設置
- 14. Goでサーバーを立ち上げる
- 15. dockerコンテナで引数としてホスト上のファイルを指定する
- 16. goで画像の反転処理を行う
- 17. 動かして覚えるGoのWorkspaceモードの使い方
- 18. Go On windows
- 19. Go,postgresql-13 On Ubuntu 18.04 etc
- 20. 【Go-sqlx】INSERT、UPDATEなどでプレースフォルダを使う時に、構造体に`db:***`タグを打てばそのまま使える
go言語 time.Format() time.Round() の挙動に注意
# まとめ
– `time.Round(time.Second)`を使うと、時刻は四捨五入的に処理される(真ん中で切り分ける)
– `time.Format(“2006-01-02 15:04:05”)`を使うと、秒未満は切り捨てられる# 場面
SQLiteを使っていて、秒単位の時刻を記録していた。その際に想定外の値のズレが発生したため、調査していた。上記の仕様を確認した。# コード
“`golang
a := time.Date(2000, 1, 1, 1, 1, 1, 300_000_000, time.UTC)
b := time.Date(2000, 1, 1, 1, 1, 1, 700_000_000, time.UTC)fmt.Printf(“round a %v\n”, a.Round(time.Second))//round a 2000-01-01 01:01:01 +0000 UTC
fmt.Printf(“round b %v\n”, b.Round(time.Second))//round b 2000-01-01 01:01:02 +00
動かして覚える!Goでデータベースの基本的な接続方法とCRUD操作
# なぜ「動かして覚える!」なのか
自分はどんな技術でも初めて勉強する時、文字を読んだり説明だけされても正直理解できず、実際に自分で書いてみて動きを見てから出ないとなかなか理解しにくいと感じました。
なのでこの記事は、自分のような「文字や説明だけじゃ分からん!」って人向けに実際にコードを書いて動かすことをメインに説明してみました。
データベースはよく使われているMySQLに接続してデータを操作していきます。
Dockerなどのコンテナを利用するか、GoとMySQLが同じPCにインストールされていれば同じように出来るので、良かったらこの記事を見ながらご自身の環境で試してみてください!
この記事の一番最後に丁寧に書かれているMySQLのインストール方法の記事があったので載せておきます。
# この記事の対象者
– **Goの勉強を始めた人**
– **文字や説明だけでは理解しにくいと感じる人**
– **GoでDBをいじってみたい人**
– **基本的なSQLを理解している人**# 実行環境
– M1 Macbook Air
– macOS Monterey 12.4
–
GoでLinebotとLIFFを使ってGoogleDriveとMoneyForwardに領収書をアップロードしてみる
# 概要
これまで自分は、経費管理のために様々なレシートを保存してきた。
しかし、レシートの保管やアップロードのために使う工数がばかにならないので、**無料**で簡単にGoogleDriveとMoneyForwardに画像アップロードする方法がないか探したところ表題のシステムを実装するに至った。**LINEで画像とタイトルを入力して送信すると、GoogleDriveとMoneyForwardにアップロードされる**というシンプルなもの。
公式docsでも書いていないことがあったり、結合して動かした時とかログが途中で禿げてたりしてよくわからないことも多かったので個人的な詰まりポイントをメモした。(拙い内容です)
# できたこと
**1.LIFFでフォームを表示して、ファイル名・経費申請者・画像ファイル を入力し送信・アップロードすること**iPhoneで撮ったレシートの写真を1枚選び、現在時刻をファイル名としてGoogleDriveの該当月フォルダにアップロードし、その後入力フォームにあるファイル名と経費申請者、画像ファイルを元として、マネーフォワードに経費明細をアップロー
koanfの罠:空文字をスライスにUnmarshalしても空スライスにならない
# はじめに
[koanf](https://github.com/knadh/koanf) で環境変数を読み込む際、`ProviderWithValue` を使うことでスライスに設定を流し込むことができます。
“`go:readmeより一部改変
// 設定オブジェクト。環境変数を読み込んでここにセット
type config struct {
Vals []string
}func main() {
k := koanf.New(“.”)k.Load(env.ProviderWithValue(“MYVAR_”, “.”, func(s string, v string) (string, interface{}) {
key := strings.Replace(strings.ToLower(strings.TrimPrefix(s, “MYVAR_”)), “_”, “.”, -1)// 値にスペースがあれば、値をスペース区切りでスライス化
if strings.Contains(v, ” “) {
return key, string
Laravelのようなmake controllerコマンドをGoで作成
# 引数を取得
まずはコマンドの引数を取得。
“`go:main.go
package main
import (
“flag”
cmd “backend/commands”
)func main() {
flag.Parse()
cmd.CMD()
}
“`
“`go:command.go
package commandsimport (
“bufio”
“flag”
“fmt”
“os”
)var verb string
var object string
var name stringfunc CMD() {
nArgs := flag.NArg()
if nArgs > 3 { //引数が3以上あったらコマンドエラー
errMessage := fmt.Sprintf(`no command “go run main.go %v”`, CreateArgsText())
fmt.Println(errMessage)
return
}
// 引数の値を取得
verb = flag.Arg(0)
objec
Golangでrubyライクな配列処理をしたい!
# TL;DR
golangでrubyライクに配列操作ができるライブラリを書いたので、興味があったら使ってみてね!
https://github.com/ppmasa8/rbarr## なぜ作ったか
rubyを普段使っている僕が、golangを使ったときに配列操作のやりにくさにキレそうになったので、作ってしまいました。
結果的に作っていく段階でgolangの配列操作に慣れてしまったので、なんとも言えませんが。## 実装したメソッド
https://github.com/ppmasa8/rbarr#index
“`
[]intの場合
pop
shift
push
unshift
delete
sum
max
min
size
uniq
include
first
last
combination
reverse
empty
sort[]stringの場合
pop
shift
push
unshift
delete
size
uniq
include
first
last
combination
reverse
empty
sort“`
## 使い方
https://
Goでコマンド作成
# コマンドを配列で取得
“`go:main.gopackage main
import (
“flag”
cmd “backend/commands”
)func main() {
flag.Parse()
args := flag.Args()
fmt.Println(args)
}“`
これでだけでコマンドの引数を取得できる。“`bash:terminal
$ go run main.go hello world
# [hello world]
“`# コマンドの一部分を取得
“`go:main.gopackage main
import (
“flag”
cmd “backend/commands”
)func main() {
flag.Parse()
secondArg := flag.Arg(1)
fmt.Println(secondArg)
}“`
“`bash:terminal
$ go run main.go hello world
# world
“`
指定した場所の
GoでCORSの設定
# オリジン間リソース共有
オリジン間リソース共有 (Cross-Origin Resource Sharing, CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組み。
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS意外とはまったのでメモ。
今回はSPAの認証にCookieを使用。
# Access-Control-Allow
“`go:middleware.go
// セッションの確認
func CORS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// クロスオリジン用にセット
w.Header().Set(“Access-Control-Allow-Origin”, “https://hoge.c
GoのWebサービスでJSONを構造体に変換し、構造体をJsonに戻す
SPAのためにJSON APIを作成。
# JSONを変換
“`go:controller/home_controller.go
type User struct {
ID int `gorm:”AUTO_INCREMENT”json:”id”`
Name string `json:”name”`
Age int `json:”age”`
Sex string `json:”sex”`
Email string `json:”email”`
Address string `json:”address”`
Password string `json:”-“`
}type Home struct{}
func (_ *Home) Show(w http.ResponseWriter, r *http.Request) {
var user User
// リクエストボディのJSONをデコード
err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
fmt.Pr
GoのWebサービスでhtmlを返す
今回はhttpリクエストの処理をcontrollerに記述しhtmlを返す方法をメモ。
# フォルダ構成
“`
root/
├ routes/
├ └ web.go/
├ controller/
│ └ home_controller.go/
└ templates/index.html
“`
laravelのような構成で作成。# コントローラー
“`go:controller/home_controller.go
package controllerimport (
“helloworld/models”
“log”
“net/http”
)// Home画面の構造体を作成
type Home struct {}func (h *Home)Index(w http.ResponseWriter, r *http.Request) {
// ここに処理を書いていく
}
“`今回はページ毎にコントローラーを分割しRESTapiを作成したかったので、構造体Homeのメソッドを作成。別のコントローラーにはまた違う構造体のメソッドを作成し
Goでリクエストのたびに認証を行う
特定のリクエストURLで毎回認証を行う。
# wrapを作成する
“`go:middleware.go
package routesimport (
“backend/modules/session”
“encoding/json”
“net/http”
)// セッションの確認
func Auth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ここに処理を書く
next.ServeHTTP(w, r)
})
}“`
こんな感じのラップを作成し、HandlerFuncを引数にとる。# クッキーを取得し、セッションを確認
“`go:middleware.go
func Auth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Req
Goで毎回のリクエスト毎にログを出力
処理の内容としては、毎回リクエストのたびに何かの処理をするというイメージ。
# muxのwrap作成
“`go:middleware.go
package routesimport (
“net/http”
“time”
)//Logger is a middleware handler that does request logging
type Logger struct {
handler http.Handler
}
//NewLogger constructs a new Logger middleware handler
func NewLogger(handlerToWrap http.Handler) *Logger {
return &Logger{handlerToWrap}
}“`
“`go:web.go
package routesimport (
“backend/config”
“backend/controller”
“net/http”
)var home controller.Home
func Routes
Goで静的ファイルを設置
今回Nuxt.jsを使ったSPAの作成だけではなく、初心に帰りSSGのアプリも作成。staticファイルの使い方をメモ。
# muxにハンドラーを登録
“`go:web.go
package routesimport (
“backend/config”
“backend/controller”
“net/http”
)var home controller.Home
func Routes() http.Handler{
mux := http.NewServeMux()// static
staticFiles := http.FileServer(http.Dir(“public”)) // publicフォルダ
uploadFiles := http.FileServer(http.Dir(“upload”)) // uploadフォルダ
mux.Handle(“/static/”, http.StripPrefix(“/static/”, staticFiles))
mux.Handle(“/media/”, http.StripPrefix
Goでサーバーを立ち上げる
アプリを一通り作り終えたので、Goで学んだことをまとめる。
# サーバーの立ち上げ
“`go:main.gopackage main
import (
“fmt”
“net/http”
)func main() {
fmt.Println(“starting server…”)
server := http.Server{
Addr: “0.0.0.0:8080”, // or :8080
Handler: routes(), //
}
fmt.Print(“run server!!”)
server.ListenAndServe()
}“`
Serverの構造体にあるHandlerフィールドは指定する必要はない。
ただし書き方が変わってくるので注意。
Addrはローカルの場合0.0.0.0:8080でも:8080でも立ち上がるが、前者はCloud Runにデプロイした場合起動してくれない。:8080の場合毎回ブラウザの権限許可みたいなのが出てくるので、ローカルは前者を指定、本番環境では後者を指定している。# ルーティング
“`
dockerコンテナで引数としてホスト上のファイルを指定する
# はじめに
こんにちは、icemint0828です。
今回はdockerコンテナで引数としてホスト上のファイルを指定する方法を紹介します。
※自作パッケージをdockerイメージとして公開する際にハマりました。## 動作環境
dockerが動作する環境## やりたいこと
ホスト上では以下のように実行していたコマンドをdockerコンテナにシングルバイナリとして持たせて実行したい時があります。
“`shell
$ imgedit reverse srcImage.png
“`dockerコンテナ上で以下のように実行したいです。
“`dockerfile:Dockerfile
# scratchはシングルバイナリを扱うためのベースイメージです。
FROM scratch
ADD imgedit /usr/bin/imgedit
ENTRYPOINT [“imgedit”]
“`“`shell
$ docker run ghcr.io/icemint0828/imgedit:latest reverse srcImage.png
“`このコマ
goで画像の反転処理を行う
# はじめに
こんにちは、icemint0828です。
今回は自作パッケージの紹介も兼ねて、goでの画像の反転処理の方法を紹介します。## 動作環境
go 1.18.3## 使用パッケージ
* icemint0828/imgedit
画像の反転処理に使用しています。
画像ファイルの拡張子の変換にも使用しています。https://github.com/icemint0828/imgedit
## インストール
“`shell
$ go get github.com/icemint0828/imgedit@v1.5.0
“`# 画像の反転処理
“`main.go
package mainimport (
“github.com/icemint0828/imgedit”
)func main() {
// 反転方向の指定
isHorizon := true// FileConverter
fc, _, err := imgedit.NewFileConverter(“srcImage.png”)
if err != nil {
動かして覚えるGoのWorkspaceモードの使い方
今までのモジュール管理方法はこちらをご覧ください。
https://qiita.com/Rqixy/items/b906fcb54cf162427775
# 実行環境
– M1 Macbook Air
– macOS Monterey 12.4
– Go 1.18WindowsでもGoがちゃんとインストールされていれば大丈夫です。
# workspaceモードとは
複数のモジュールを一つのgo.workというファイルで管理し、モジュール間の行き来をスムーズにすると言うものです。
“`go.work
go 1.18use (
./module1
./module2
)
“`このような感じでmoduleを複数管理することができます。
## workspaceのコマンド
いくつかコマンドがあるのですが、よく使うinitとuseコマンドを紹介します。
### initgo.workファイルを初期化する時に使います。
“`terminal
% go work init
“`initの後ろに既に作成しているモジュールを追加することができます。
“`t
Go On windows
## Go vscode 拡張機能
コマンドパレットで
“`cmd
Go: Install/Update tools
“`“`text
command go.tools.install not found
“`“`bash
$ echo %GOPATH%
D:/opt/GoLang/1.16.15/GOPATH
$ echo %GOENV_ROOT%
D:/opt/GoLang/1.16.15/go
“`“`bash
go install github.com/ramya-rao-a/go-outline@latest
go install github.com/cweill/gotests/gotests@latest
go install github.com/fatih/gomodifytags@latest
go install github.com/josharian/impl@latest
go install github.com/haya14busa/goplay/cmd/goplay@latest
go install honnef.co
Go,postgresql-13 On Ubuntu 18.04 etc
## Firewall
“`bash
sudo ufw status
sudo timedatectl set-timezone Asia/Tokyo
“`## goenv
[install](https://github.com/syndbg/goenv/blob/master/INSTALL.md)
“`bash
git clone https://github.com/syndbg/goenv.git ~/.goenv
echo ‘# ADD’ >> ~/.bashrc
echo ‘export GOENV_ROOT=”$HOME/.goenv”‘ >> ~/.bashrc
echo ‘export PATH=”$GOENV_ROOT/bin:$PATH”‘ >> ~/.bashrc
echo ‘eval “$(goenv init -)”‘ >> ~/.bashrc
echo ‘export PATH=”$GOROOT/bin:$PATH”‘ >> ~/.bashrc
echo ‘export PATH=”$PATH:$GOPATH/bin”‘ >> ~/.ba
【Go-sqlx】INSERT、UPDATEなどでプレースフォルダを使う時に、構造体に`db:***`タグを打てばそのまま使える
[前回の記事](https://qiita.com/rikimaru-odd-person/items/4151b6c94c0f48882e9c)では、sqlxライブラリでプレースフォルダを使ったINSERTする際に、
`map[string]interface{}`
を使ってましたが、職場の人から「構造体でもできる」ということを教わりました。今回はそのメモです。
### まずはおことわり
– 「使えればいい」レベルでの内容ですので、セキュリティやコード品質は無視しております。ご了承ください。### 結論から
– INSERT,UPDATEに使用するための構造体を用意する。
– 構造体に`db:”カラム名”`タグを明記しておく。
– SQL側でのプレースフォルダの変数名は構造体タグ`db:”カラム名”`の「カラム名」と同じにする。
– あとは通常通りNamedしたり、NamedExecして実行する。構造体のタグ`db:”カラム名”`はSELECT文の受け手となる構造体を定義するときに使われますが、INSERT,UPDATEのプレースフォルダにも使えることを今回