====== 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]]