====== Go ====== Pythonで作成したものをGoに移植する上で調査したメモ\\ ===== 開発環境 ===== Visual Studio CodeのGo Extensionを使用している。\\ GO開発用ダウンロード Microsoft Windows版1.18.1 https://go.dev/dl/ * [[https://qiita.com/suke_masa/items/0c45c92934b9a2807ddb|WindowsにGo言語開発環境をインストールする]] ==== 拡張機能 ==== [[https://yurupro.cloud/767/|【2022年最新版】VSCodeをPython超特化型にする、最高の拡張機能20選まとめ。 【VisualStudio Code】【プラグイン】]] 下記の拡張機能をインストール * indent-rainbow * ZenKaku * Trailing Spaces ==== 実行ファイル作成 ==== VSCodeのターミナル上でbuildコマンドを入力する。\\ 複数ファイルはある場合、スペース区切りでgoファイルを指定する。\\ 「-o」オプションで実行ファイル名を指定する。 > go build -o executename.exe main.go test.go * [[https://mebee.info/2020/02/27/post-6530/|go言語で開発したファイルをexe化する]] * [[https://astaxie.gitbooks.io/build-web-application-with-golang/content/ja/01.3.html|go buildのコマンド]] * [[https://qiita.com/t-yama-3/items/1b6e7e816aa07884378e|【備忘】Go 言語のビルドと実行(3パターン)]] === ラズパイ用の実行ファイル作成 === powershellでenvを設定する。この環境変数設定方法は、powershellのセッション内だけで有効。 GOOSやGOARCHの一覧は下記コマンドで取得できる。 >go tool dist list linux/arm linux/arm64 ラズパイ用の実行ファイル生成コマンド > $env:GOOS = "linux" > $env:GOARCH = "arm" > go build -o executename main.go test.go 環境変数を取り除く場合 > rm env:GOOS > rm env:GOARCH * [[https://kitagry.github.io/blog/programmings/2020/12/windows_go_build_for_linux/|Windowsでlinux用にGoのクロスビルドする]] * [[https://qiita.com/suin/items/7ddfcbc708c8863ea76a|Go言語のクロスコンパイル設定値 $GOOS, $GOARCH 一覧リスト]] * [[https://tkyonezu.com/%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB-%E8%A8%80%E8%AA%9E/raspberry-pi-%E3%81%AB-go-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/|Raspberry Pi に Go をインストール]] ===== コーディング関連 ===== ==== コーディング規約 ==== * [[https://golang.org/doc/effective_go.html|golang.org Effective Go]] * [[https://github.com/golang/go/wiki/CodeReviewComments|golang.org Go Code Review Comments]] * [[https://qiita.com/knsh14/items/8b73b31822c109d4c497|Go Code Review Comments 日本語翻訳]] * [[https://qiita.com/keitakn/items/804c6abb0a98dfb094ee|他言語プログラマが最低限、気にすべきGoのネーミングルール]] === インデントはタブ === Go公式のインデントの指定はスペースではなく「タブ」 * [[https://qiita.com/iwasiman/items/0f771f9066b68b96e21c|【Go】VSCodeでGo言語の開発環境を整えてみよう【Golang】【主にWindows・初心者向け】]] ==== コメント記載方法 ==== go用のコメントのいいのがなかったので、今回はC#版のドキュメント コメント方式を採用した。\\ https://www.tairax.com/entry/Csharp/Document-Comment スラッシュ3つは、Goでは分割されてしまうので2つとする。 // // イヌの飼い主のメッセージを取得 // // 年齢 // 名前 // メッセージ public string GetDogMessage(int ownerAge, string ownerName) ==== 定義変数 ==== Go 言語の定数は、const キーワードを使用して定義します。\\ 型の指定も可能であるが、通常は型を指定せずに記述する。\\ 定数の命名規則はないが、定数は先頭のみ大文字またはすべて大文字を使用し、単語を区切るにはアンダースコアを使用する。\\ スコープを考慮して、先頭が大文字ならパッケージ外からもアクセス可能、英小文字ならプライベート扱いとする。 const ( DATE_FORMAT = "20060102" TIME_FORMAT = "15:04:05.000" ) * [[https://www.techscore.com/tech/Go/Lang/Basic5/#2|Go入門 → 5. 変数と定数]] * [[https://kazuhira-r.hatenablog.com/entry/2021/01/17/012840|Goで定数や関数定義などをパッケージ外からアクセスしたい(エクスポートしたい)場合、名前を大文字で始める必要があるという話]] ==== 文字列の囲み ==== 文字列の囲みは、二重引用符(ダブルクォーテーション)を使う。 複数行にまたぐ文字列はバッククォート (backquote) で囲む\\ [[http://psychedelicnekopunch.com/archives/1098|Golang にて複数行にまたぐ文字列を簡単に扱う方法]] === 文字列の長さ取得 === C#の用に文字列のメソッドになっていない。 ✕ "abc".Length ◯ len("abc") ==== switch case文 ==== 普通にある。 [[https://golang.hateblo.jp/entry/2019/10/07/225026|Go言語(golang) switch文の書き方]] ==== フォーマット書式 ==== パッケージ fmtを使用する。改行コードは"\n"\\ https://xn--go-hh0g6u.com/pkg/fmt/ import ( "fmt" ) str := "Go" fmt.Printf("文字列 = %s\n", str) * [[https://qiita.com/Sekky0905/items/c9cbda2498a685517ad0|忘れがちなGo言語の書式指定子を例付きでまとめた]] * [[https://qiita.com/ogrew/items/0632ef56147c7f3d2866|Golangのフォーマット指定子についてカンペを作っておいた。package fmt]] === print系関数 === Fprint, Sprintln, Printf...などいろいろある。\\ [[https://qiita.com/taji-taji/items/77845ef744da7c88a6fe|【Go】print系関数の違い]] ^標準|標準出力に出力します。| ^接頭辞 F|書き込み先を明示的に指定| ^接頭辞 S|結果を文字列で返す| ^接尾辞 f|フォーマットを指定| ^接尾辞 ln|オペランド間にスペース、最後に改行を追加| === 日付書式 === Goのtimeパッケージのフォーマットは独特だ。普通のUnixのstrftimeとかだとフォーマット文字列は%Yとか%mといった文字列なのだけど、Goの場合はそのかわりにある種の「サンプル文字列」を与えるという仕組みになっている。 アメリカ式の時刻の順番なのだ。"1月2日午後3時4分5秒2006年"(つまり「自然な順番」で1, 2, 3, 4, 5, 6) n := time.Now() fmt.Println(n) // 2016-03-25 19:05:54.785208 +0900 JST fmt.Println(n.Format("2006-01-02")) // 2016-03-25 fmt.Println(n.Format("2006-01-02 15:04:05")) // 2016-03-25 19:05:54 * [[https://qiita.com/icbmuma/items/5617f3fc5bc0215aade2|golangの日付のフォーマット指定]] * [[https://qiita.com/ruiu/items/5936b4c3bd6eb487c182|Goのtimeパッケージのリファレンスタイム(2006年1月2日)は何の日?]] === ミリ秒 === [[https://qiita.com/ayatothos/items/3b06855ae331689730ae|Goの日付フォーマットでミリ秒、マイクロ秒、ナノ秒を取得するには]] t := time.Date(2020, 2, 3, 14, 26, 31, 123456700, time.Local) fmt.Println(t.Format("2006/01/02 15:04:05.000")) // ミリ秒 2020/02/03 14:26:31.123 fmt.Println(t.Format("2006/01/02 15:04:05.000000")) // マイクロ秒 2020/02/03 14:26:31.123456 fmt.Println(t.Format("2006/01/02 15:04:05.000000000")) // ナノ秒 2020/02/03 14:26:31.123456700 ==== 例外処理 ==== Go言語にはtry~catch~finallyの例外処理は存在しません。\\ http://golang.jp/go_faq#exceptions >例外(exception)がない理由は? > >我々は、処理構造を制御するためのtry-catch-finally形式の例外処理機構によって、コードが入り組んでしまうと考えています。 >[[https://tmrtmhr.info/tech/why-does-golang-not-have-exceptions/|なぜGo言語はエラー返却に例外機構を使わないのか]] Go言語ではエラーを処理するためにerrorインタフェースが用意されています。 * [[https://qiita.com/nayuneko/items/3c0b3c0de9e8b27c9548|Go言語のエラーハンドリングについて]] * [[https://qiita.com/Maki-Daisuke/items/80cbc26ca43cca3de4e4|「例外」がないからGo言語はイケてないとかって言ってるヤツが本当にイケてない件]] * [[https://zenn.dev/koduki/articles/2840dab22efc68|Goのエラーハンドリングの考え方が良く分からない]] === defer === defer へ渡した関数の引数は、すぐに評価されますが、その関数自体は呼び出し元の関数がreturnするまで実行されません。 >C#やJava の finally よりも go の defer のほうが筋が良さそうだ >[[https://www.kaoriya.net/blog/2014/04/17/|または私は如何にして例外するのを止めて golang を愛するようになったか]] >Defer を使って、ある関数を確実に後で呼ばせることができる。 これは後片付けにしばしば使われる機能だ。 他の言語だと ensure や finally といったキーワードを使う場面で、Go では defer を使う >[[https://www.spinute.org/go-by-example/defer.html|サンプルで学ぶ Go 言語:Defer]] * [[https://qiita.com/Ishidall/items/8dd663de5755a15e84f2|Go言語のdeferを正しく理解する | How defer in Golang works]] * [[https://asapoon.com/golang/3858/defer/|【Golang】defer関数の使い方をGoエンジニアが優しく解説!]] ==== 配列およびリスト処理 ==== * スライス(slice)が他の言語でいうところの「配列」みたいなもの * マップ(map)が他の言語でいうところの「連想配列」みたいなもの * [[https://ashitani.jp/golangtips/tips_slice.html|逆引きGolang (配列)]] * [[https://qiita.com/YumaInaura/items/aec7857518102ff5e27c|Go言語の基本 — array と slice の違い]] * [[http://psychedelicnekopunch.com/archives/311|Golang における配列操作(定義、追加、削除)]] ===== コマンドライン引数の処理 ===== osパッケージのArgsを使用する。\\ args[0]には実行内容が入りますので、実際の内容はargs[1]から入ります。\\ [[https://zenn.dev/a_ichi1/articles/9d976e8daa357f|【Go】コマンドライン引数を扱う。flagとos.Args]] VSCodeからデバッグ実行した場合、args[0]には"__debug_bin.exe"が入る。 ==== 実行ファイルのパスを取得 ==== ファイル名までのフルパスが exe に格納される。 exe, err := os.Executable() file_path = filepath.Base(exe) [[https://qiita.com/summer/items/2674a178ffe6acb895fb|Go で実行ファイルのパスを取得]] ===== ファイル関連 ===== ==== パス操作 ==== path/filepathパッケージを使用する。 package main import ( "path/filepath" ) func main() { name := "/path/to/dir/filename.txt" extname := filepath.Ext(name) println(extname) // .txt basename := filepath.Base(name) println(basename) // filename.txt dirname := filepath.Dir(name) println(dirname) // /path/to/dir dirname, basename = filepath.Split(name) println(basename) // filename.txt println(dirname) // /path/to/dir/ (Dir と違って最後に / が付いてる) } * [[https://takuroooooo.hatenablog.com/entry/2020/08/15/Go_path/filepath|Go path/filepathでファイルパスを操作する]] * [[https://golang.hateblo.jp/entry/golang-filepath-split-path|Go言語(golang) filepathでパスを扱う]] * [[https://mebee.info/2021/06/06/post-23371/|go言語 パスを結合させる]] ==== ファイル読み書き ==== ioパッケージを使用する。 * [[https://hake.hatenablog.com/entry/20150817/p1|Go言語 - Shift_JISファイルの読み書き]] * [[https://www.kwbtblog.com/entry/2020/05/07/014836|Go言語でファイル・IO・ストリームを使った読み書き方法のメモ]] * [[https://zenn.dev/hsaki/books/golang-io-package/viewer/file|ファイルの読み書き]] * [[https://qiita.com/Kashiwara/items/9a8365ea800e6f39713f|Go言語でのファイル読み取り]] * [[https://golang.hateblo.jp/entry/2018/11/09/163000|Go言語(golang) ファイルの読み書き、作成、存在確認、一行ずつ処理、コピー など]] ==== フォルダ未存在時作成 ==== フォルダ名は、フルパスで指定すればいい。 if _, err := os.Stat(new_path); err != nil { os.Mkdir(new_path, 0777) } ===== HTTP クライアント ===== net/httpパッケージを使用する。 * [[https://qiita.com/howmuch515/items/65094d18292ff1c4408c|Golangで構造体をJSONに変換してPOSTする]] * [[https://code-database.com/knowledges/99|【Golang】GolangでJSONを用いたAPIを実装する方法について解説]] * [[https://www.cdatablog.jp/entry/golanghttpapi|Go の net/http を使って Web API にリクエストを行う:CData API Server]]