LoginSignup
1
1

More than 3 years have passed since last update.

Goの文法を雑多にまとめる

Last updated at Posted at 2020-02-15

Golangの文法を自分用メモとしてまとめる。

雑多なメモ

# ライブラリのdocの確認
$ godoc fmt Println
$ godoc os/user Current

# コマンドラインでフォーマット形成
$ gofmt -w file.go

# ドキュメントをローカルポートから見る
$ godoc -http=:6060
// %ホニャララのPrintf (Printlnだとダメ)
fmt.Printf("%T", var) // 変数の型
fmt.Printf("%v", var) // value in default format
fmt.Printf("%d", var) // 10進数で表示

// intは環境によって32bitか64bit,指定したい場合にはint32, int64を使う。

// 文字列からn番目の要素を取り出す
fmt.Println("Hello"[0])  // 72(ASCIIコード)
fmt.Println(string("Hello"[0])) // "H"(stringに戻す)

// エラーを生じうる型変換
i, err := strconv.AtoI("15")

// バイト配列
b := []byte{72, 73} // [72 73]
c := []byte("HI")   // [72 73]
string(b)           // "HI"

// 可変長引数を関数に渡す
func foo(params ...int){処理} // paramsにはintのスライスが入る
// スライスを展開し各を引数として関数に放る
foo([]int{1, 2, 3}...) 

// 標準パッケージのtesting
$ go test ./...

クロージャ(関数閉包)

closureの定義のちゃんとした説明には踏み込まず、具体例からやんわりまとめる。


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

func main() {
    counter := incrementGenerator()
    fmt.Println(counter())
    fmt.Println(counter())
}

以上の例だと、counterという変数には無名関数が保存されており、この関数内から、この関数外で定義された変数xを参照している。このため、このxの値は保持され、二度目にcounter()を呼び出した際には、x=1が入っている。

logライブラリ

log.Println("error message")
log.Fatalln("error message") // プログラム終了する

ログをファイルに書き出すようにsettingをするには以下。


func LoggingSettings(logFile string) {
    logfile, _ := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    //multiWriterは複数のio.Writerを受け取り、すべてに同時に書き込み対象に設定
    multiLogFile := io.MultiWriter(os.Stdout, logfile)
    log.SetFlags(log.LDate | log.Ltime | log.Llongfile)
    log.SetOutput(miltiLogFile)
}


func main() {
    LoggingSettings("test.log")
}

panicとrecover

golangでは使用が推奨されておらず、エラーハンドリングを使うべし。deferで指定する関数に入れることで生じたpanicをキャッチして処理できる。

// panicのキャッチかつプリント
s := recover()
fmt.Println("OK?")

ポインタ周り

// *int型を返す [ポインタ!!]
new(int)

 // ポインタではなくスライス型を返す
make([]int, 0)
  • 初期化

    • スライスやマップは[]int{}よりmake([]int, 0)で初期化が推奨される。
    • 構造体はnew(MyStruct)より&MyStruct{}で初期化されることが多い。
  • (構造体のポインタ).(属性値) = (*構造体のポインタ=実態).(属性値)が成立、つまり、

// 構造体の初期化かつそのポインタの取得
s := &MyStruct{初期化}

// どっちでもいい
s.field1 = "field1"
*s.field2 = "field2" 

構造体周り

  • 構造体のコンストラクタのプラクティス
func New(x, y int) *Mystruct{
    return MyStruct{x, y}
}
  • 構造体の破壊的/非破壊的メソッド
// 破壊的メソッドの定義
func (s *MyStruct) overwrite {
    s.var = "new value"
}


// 非破壊的メソッドの定義
func (s MyStruct) overwrite {
    s.var = "new value"
}
  • golangの構造体は継承をembedding(実現)によって実現する
  • non-struct型のメソッドを拡張
// カスタムの新しい型を作る
type MyInt int

func (i MyInt) newMethod {処理}

Type Assertionとswitch-assert文

  • Type Assertion
    インターフェイスから他の型へはtype assertion、ある型から他の型へはキャスト、,type conversionと呼ぶ。
// interface{}型からint型へ
var a interface{} = 5
b := a.(int) // エラー時にはpanicが生じる
  • switch-assert文
switch t := i.(type) {
    case int: 
        処理
    case string
        処理
    default: 
        処理
    }
}
1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1