Go言語始めました。

Go言語始めました

環境準備(Mac

  • 以下の公式サイトからGoのダウンロードを行う
    https://go.dev/dl/
  • インストール後に、Pathを通す必要あり。 nanoを起動してパスを記載。
$ sudo nano ~/.bashrc

# 以下、~/.bashrcの内容
export GOPATH=$(go env GOPATH)
export PATH=$PATH:$GOPATH/bin
  • ~/.bashrcへの登録内容を環境に反映する。
$ source ~/.bashrc
  • go install golang.org/x/tools/cmd/godoc@v0.1.10 「go get」はVer1.16で廃止されているため、パッケージのInstallは「go install」で行う。@の後ろでVersionを指定すること。

初歩

Hello World

以下の通りコーディングして実行する。

package main

import "fmt"

func init() {
    fmt.Println("init")
}
func bazz() {
    fmt.Println("Bazz")
}

func main() {
    bazz()
    fmt.Println("Hello world!")
}
  • 実行するには、main()が必要であること。
  • init()は、最初に(mainよりも先に)呼び出されること。
  • Publicメソッドは、冒頭大文字で始めるのが原則であること
  • IDE「Go Land」では、文字列変数には「a....」というガイドが表示されること
  • コメントは、「//」でインラインコメント、「//」でブロックコメント。
  • 実行ショートカットは、Macの場合、デフォルトは「Control+R」。Preferenceから変更可能。

パッケージのインポート

  • importを複数行う場合は、import()で記載する
import (
    "fmt"
    "os/user"
    "time"
)
  • 上記「os/user」のように、階層下がある場合は「/」で区切ること.
    標準パッケージは、以下のサイトを参照する。

pkg.go.dev

  • メソッドの説明を確認する場合は上のドキュメントを参照するか、ターミナルから次のコマンドを実行する。
# go doc パッケージ名 メソッド名
$ go doc fmt Println
package fmt // import "fmt"

func Println(a ...any) (n int, err error)
    Println formats using the default formats for its operands and writes to
    standard output. Spaces are always added between operands and a newline is
    appended. It returns the number of bytes written and any write error
    encountered.

特徴的なポイント

宣言時のデータ型は、前ではなく後ろで行う(VBっぽい?)

// 関数宣言
func(param int) float64 {
  // :
}

// 変数宣言
var variable int

// 変数宣言(配列)
var ary []int

配列とスライス

素数が予め固定なのを「配列」と呼び、要素数が動的なものを「スライス」と呼ぶ(ようです)

ファンクションは変数に代入できる(最近珍しくはない)

add := func(x int ,y int){
    return x+y
}

result := add(3,5)
fmt.Println(result) // -> 8

クロージャってなんじゃ?

昔から名前だけは聞いていたけど、出会ったことはなかったクロージャ。Static、というかPrivateメンバ変数を持ったクラスと理解したけど、ちょっと違いそう。そもそもGoにクラスがないことをここで知った。

func incrementGenerator() func() int {
    x := 0
    return func() int {
        x++
        return x
    }
}

func main() {
    counter := incrementGenerator()
    fmt.Println(counter()) // -> 1
    fmt.Println(counter()) // -> 2
    fmt.Println(counter()) // -> 3
    fmt.Println(counter()) // -> 4
}

遅延処理を行う defer

ファンクション単位の最後に実行を行うDefer。

func main(){
    defer fmt.Println("test1")
    fmt.Println("test2")
    fmt.Println("test3")
    fmt.Println("test4")
}
// -> test2
// -> test3
// -> test4
// -> test1 ← defer を書いた行がこちらが後に出る

主な用途としては、ファイルのOpen/Close処理。Try~Finallyみたいなイメージ?

func main(){
    file, _ := os.Open("./test.go")
    defer file.Close() // <- 処理後にファイルクローズする行われる
    data := make([]byte ,100)
    file.Read(data)
    fmt.Println(string(data))
}

エラーハンドリング。

GoにはTry~Catch、Exceptionが存在しない。エラーは、ファンクションの戻り値として規定し、その値を単純にIFで比較する。

func main() {
    file, err := os.Open("./tsest.go")
    defer file.Close()
    // ↓ 単純に、err を Ifで判定。
    if err != nil {
        log.Fatalln("Error!", err)
    }
}

panicとrecover

panicはPGの強制終了。recoverはpanicで終了されることを防ぐもの。ただし、コード原則としてエラーは適切にハンドリングするべきであり、panicは作らないようにすべき。

func DBConnect() {
    // PG強制終了
    panic("Unable to Connect Database!")
}

func save() {
    // deferのため、DBConnect()後に処理
    defer func() {
        s := recover() // DBConnect()のPanicをキャッチ
        fmt.Println(s)
    }()

    DBConnect()
}

func main() {
    save()
    fmt.Println("OK?")
}