Go 入門

Go言語入門⑨ ~log・エラーハンドリング・panicとrecover~

[box class="blue_box" title="☑本記事の内容"]

  • log
  • エラーハンドリング
  • panicとrecover

[/box]
参考資料:現役シリコンバレーエンジニアが教えるGo入門 + 応用でビットコインのシストレFintechアプリの開発
[box class="glay_box" title="Contents"]

  1. log
  2. エラーハンドリング
  3. panicとrecover

[/box]

log

[box class="yellow_box" title="✔logの目次"]

[/box]

基本的なこと

[box class="glay_box"]

  • 公式サイトで標準ライブラリの確認が出来る
  • 他のプログラミングと言語違い標準ライブラリにはlogを出すパッケージが最低限のものしかない
  • サードパーティのライブラリを使うと他の言語と似たようなものもある

[/box]

package main

import "log"

func main() {
	log.Println("logging!")
	log.Printf("%T %v", "test", "test")
}
(結果)
2021/02/02 21:04:35 logging!
2021/02/02 21:04:35 string test

errorlog

[box class="glay_box"]

  • Fatalを使う事でerrorlogを出せる
  • Fatalを使うとその後の処理は起こらない

[/box]

package main

import (
	"fmt"
	"log"
)

func main() {
	log.Fatalf("%T %v", "test", "test")

	fmt.Println("ok?")
}
(結果)
2021/02/02 21:06:25 string test
Process exiting with code: 1 signal: false

logファイルの出力

[box class="glay_box"]

  • 標準ライブラリでもlogファイルの出力が出来る
  • 最低限のものなので、詳しいlogファイルを出力したいときはサードパーティのライブラリを使用
  • 下記のコードではtest.logが出力される

[/box]

func LoggingSettings(logFile string) {
	logfile, _ := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	multiLogFile := io.MultiWriter(os.Stdout, logfile)
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.SetOutput(multiLogFile)
}

func main() {
	LoggingSettings("test.log")
	_, err := os.Open("fdafdsafa")
	if err != nil {
		log.Fatalln("Exit", err)
	}
}
(結果)
2021/02/02 21:13:40 lesson.go:20: Exit open fdafdsafa: The system cannot find the file specified.
Process exiting with code: 1 signal: false
(ファイルの中身)
2021/02/02 21:13:40 lesson.go:20: Exit open fdafdsafa: The system cannot find the file specified.

エラーハンドリング

[box class="yellow_box" title="✔エラーハンドリングの目次"]

[/box]

基本的なこと

[box class="glay_box"]

  • file, errのように後ろにエラーの変数を加える
  • errが空でない場合は処理をlogを出力するようにする
  • エラーの場合はerrにstringが入ってくる

[/box]

package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	file, err := os.Open("./lesson.go")
	if err != nil {
		log.Fatalln("Error!")
	}
	defer file.Close()
	data := make([]byte, 20)
	count, err := file.Read(data)
	if err != nil {
		log.Fatalln("Error")
	}
	fmt.Println(count, string(data))
}
(結果)
20 package main

impo

補足

[box class="glay_box"]

  • file, err :=count,err
    :=
    とerrを2回イニシャライズしているがこれは大丈夫
  • 片方だけでも初めて変数宣言している場合はエラーにならない
  • errのみ再度変数宣言をするとエラーになる

[/box]

package main

import (
	"log"
	"os"
)

func main() {
	file, err := os.Open("./lesson.go")
	if err != nil {
		log.Fatalln("Error!")
	}
	defer file.Close()
	err := os.Chdir("test")
}
(結果)エラー表示
no new variables on left side of :=

panicとrecover

[box class="yellow_box" title="✔panicとrecoverの目次"]

[/box]

panic

[box class="glay_box"]

  • 例外処理を追加すること
  • panicが起きると処理が強制終了する

[/box]

package main

import "fmt"

func thirdPartyConnectDB() {
	panic("Unable to connect database!")
}

func save() {
	thirdPartyConnectDB()
}

func main() {
	save()
	fmt.Println("OK?")
}
(結果)
panic: Unable to connect database!

goroutine 1 [running]:

recover

[box class="glay_box"]

  • panicから復帰させること
  • recoverよりもpanicが先にあると復帰出来ない

[/box]

package main

import "fmt"

func thirdPartyConnectDB() {
	panic("Unable to connect database!")
}

func save() {
	defer func() {
		s := recover()
		fmt.Println(s)
	}()
	thirdPartyConnectDB()
}

func main() {
	save()
	fmt.Println("OK?")
}
(結果)
Unable to connect database!
OK?

注意点

[box class="glay_box"]

  • Goではpanicを使用することを推奨していない
  • panicはエラー原因が分からずに起きていること
  • エラーハンドリングでしっかりとエラー状況を把握するのが大事

[/box]

Go言語入門⑩へ ≫

≪ Go言語入門⑧へ

目次

-Go, 入門