tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

【go】golangのエラー処理メモ - ③. pkg/errorsでのエラーハンドリング

はじめに

goをさわって数ヶ月ですが、雰囲気では書けていたものの
errorやエラーハンドリングについてはもやもやしたままだったので自分理解メモの③

関連

この記事の関連です。

アジェンダ

  1. エラーハンドリングで困る事
  2. pkg/errorsでのエラーハンドリング(errors.Wrap)
  3. pkg/errorsでのエラーハンドリング(errors.Cause)

1. エラーハンドリングで困る事

main -> packageA.method -> packageB.method のように呼び出しを行っている場合、
packageB.methodで起きたエラーをpackageA.methodで拾ってmainにさらに返したいときがあります。

packageA.methodでのハンドリングによっては、
mainでなんのエラーだったかわかりにくくなるときがあります。

サンプル

ここでは main -> fuga.method -> hoge.method のように呼び出しているとします。

hoge.methodが返すエラーをfuga.method
ハンドリングしてさらにエラーを返します。

mainではerrrorかどうかをハンドリングします。

コード
package hoge

import "fmt"

type HogeSomethingError struct{}

func (f *HogeSomethingError) Error() string {
  return fmt.Sprintf("this is HogeSomethingError")
}

type HogeAnythingError struct{}

func (f *HogeAnythingError) Error() string {
  return fmt.Sprintf("this is HogeAnythingError")
}

func DoSomething() error {
  return &HogeSomethingError{}
}

func DoAnything() error {
  return &HogeAnythingError{}
}

func DoExciting(b bool) error {
  if b {
    return DoSomething()
  } else {
    return DoAnything()
  }
  return nil
}
package fuga

import (
  "errors"
  "go-error-handling_pkg-errors/package/hoge"
)

func DoExciting(b bool) error {
  err := hoge.DoExciting(b)

  if err != nil {
    switch err.(type) {

    case *hoge.HogeSomethingError:
      return errors.New("error1 at fuga")

    case *hoge.HogeAnythingError:
      return errors.New("error2 at fuga")

    }
  }

  return nil
}
package main

import (
  "fmt"
  "os"

  "go-error-handling_pkg-errors/package/fuga"
)

func main() {
  if err := fuga.DoExciting(false); err != nil {
    fmt.Fprintln(os.Stderr, err)
    os.Exit(1)
  }

  fmt.Println("main success")
}
出力
$ go run src/go-error-handling_pkg-errors/sample01/main.go 
error2 at fuga
exit status 1
困ること

mainでは、error2 at fuga と出力され、
エラーがあったことはわかるものの、hogeでエラーだったことがわかりません。

2. pkg/errorsでのエラーハンドリング(errors.Wrap)

そんな場合に pkg/errors でエラーハンドリングを行ってみます。

インストール

使う前にインストールしておきます。

pkg/errrosgo getなら以下のようにしてインストールできます。

go get -v github.com/pkg/errors

自分はglide環境なので、glide.yamlを以下のようにしてglide installしました。

package: go-error-handling_pkg-errors
import:
  - package: github.com/pkg/errors

サンプル

さきほどの fuga.methodpiyo.methodに置き換えて、
main -> piyo.method -> hoge.method と呼び出すようにします。

また、piyo.methodでは`pkg/errorsを使ってエラーハンドリングするようにしてみます。

コード
上記と同じです
package piyo

import (
  "go-error-handling_pkg-errors/package/hoge"

  "github.com/pkg/errors"
)

func DoExciting(b bool) error {
  err := hoge.DoExciting(b)

  if err != nil {
    switch err.(type) {

    case *hoge.HogeSomethingError:
      return errors.Wrap(err, "error1 at piyo")

    case *hoge.HogeAnythingError:
      return errors.Wrap(err, "error2 at piyo")

    }
  }

  return nil
}
package main

import (
  "fmt"
  "os"

  "go-error-handling_pkg-errors/package/piyo"
)

func main() {
  if err := piyo.DoExciting(false); err != nil {
    fmt.Fprintln(os.Stderr, err)
    os.Exit(1)
  }

  fmt.Println("main success")
}
出力
$ go run src/go-error-handling_pkg-errors/sample02/main.go 
error2 at piyo: this is HogeAnythingError
exit status 1
結果

error2 at piyoに続いて、大元の: this is HogeAnythingErrorも表示されました。

3. pkg/errorsでのエラーハンドリング(errors.Cause)

errors.Causeというのもあり、
これを使うと上記の例でいうとmainで原因となるエラーの型ハンドリングが可能となります。

mainだけ変更した例をのせておきます。

コード
package main

import (
  "fmt"
  "os"

  "github.com/pkg/errors"

  "go-error-handling_pkg-errors/package/hoge"
  "go-error-handling_pkg-errors/package/piyo"
)

func main() {
  if err := piyo.DoExciting(false); err != nil {
    switch errors.Cause(err).(type) {
    case *hoge.HogeSomethingError:
      fmt.Fprintln(os.Stderr, "case1 at main:", err)
    case *hoge.HogeAnythingError:
      fmt.Fprintln(os.Stderr, "case1 at main:", err)
    }
  }

  fmt.Println("main success")
}
出力
$ go run src/go-error-handling_pkg-errors/sample03/main.go 
case1 at main: error2 at piyo: this is HogeAnythingError
main success

おわり

こちらの参考でも言われてますが、
たしかにあまり深くWarpしまくるのも、という気もするので結局悩ましいループになりそう\(^o^)/

参考

【go】golangのエラー処理メモ - ②. 例外はないがエラーハンドリングはできるよ(インスタンスや型でハンドリング)

はじめに

goをさわって数ヶ月ですが、雰囲気では書けていたものの
errorやエラーハンドリングについてはもやもやしたままだったので自分理解メモの②

関連

この記事の関連です。

アジェンダ

  1. goのエラーについて
  2. 一番簡単なエラーハンドリング
  3. エラーハンドリングのパターン
  4. パターン1: errorの文字列で
  5. パターン2: errors.Newのインスタンス
  6. パターン3: カスタムエラーのインスタンス
  7. パターン4: カスタムエラーの型で

1. goのエラーについて

goのエラーについては以下に記載してみました。
【go】golangのエラー処理メモ - ①. errorとError型とカスタムErrorと

あえて項目にするまでもなかったけど前提として載せておきます

2. 一番簡単なエラーハンドリング

goは例外というモノがなく、
基本的には関数を呼び出した結果がエラーな場合はその場で処理します。

簡単なエラーハンドリング

その場で処理しちゃう例の一番簡単なものです。

サンプル

サンプルコード

package main

import (
  "errors"
  "fmt"
  "os"
)

func doSomething() error {
  return errors.New("doSomething is error.")
}

func main() {

  err := doSomething()

  // nilと比較してerrorオブジェクトが返ってたらエラーと見なす
  if err != nil {
    fmt.Println("main is failed")
    os.Exit(1)
  }

  fmt.Println("main is success")
}
出力
$ go run src/go-error-handling/sample01/main.go 
main is failed
exit status 1

エラーを無視する

また、エラーでも問題ない場合は_や単に何も受け取らないことで無視する事もできます。

サンプル

サンプルコード

package main

import (
  "errors"
  "fmt"
)

func doSomething() error {
  return errors.New("doSomething is error.")
}

func doHoge() {
  err := doSomething()

  // nilと比較してerrorオブジェクトが返ってたらエラーと見なす
  if err != nil {
    fmt.Println("doHoge is failed")
    return
  }

  // 処理を続ける
  fmt.Println("doHoge is success")
}

func doFuga() {

  // _ でerrorを無視する
  _ = doSomething()

  // 処理を続ける
  fmt.Println("doFuga is success")
}

func doPiyo() {
  // 単に受け取らないことも
  doSomething()

  // 処理を続ける
  fmt.Println("doPiyo is success")
}

func main() {

  doHoge()

  doFuga()

  doPiyo()

  fmt.Println("main is success")
}
出力
$ go run src/go-error-handling/sample02/main.go 
doHoge is failed
doFuga is success
doPiyo is success
main is success

3. エラーハンドリングのパターン

上記のような簡単なエラーハンドリングでも事足りる事はあります。

しかし、
実際は下位のmethodで発生したエラーをハンドリングしては上位に返して…
を繰り返すと困る事がでてきます。

自分は以下のような事が困りました。

  • 最上位でハンドリングで出力したものの根本原因がどこかわからない
  • エラーによって分岐したいがどのようにするのがベストプラクティスかわからない

エラーハンドリングのパーターンとしては以下のサイトが非常に参考になります。

参考サイトを参考に、
エラーハンドリングは以下のようなパターンで行う事ができます。

エラーハンドリングのパターン
  • パターン1: errorの文字列で
  • パターン2: errors.Newのインスタンス
  • パターン3: カスタムエラーのインスタンス
  • パターン4: カスタムエラーの型で

バッドノウハウなパターンも含まれてますが、
さっと書く使い捨てのscriptだったりではバッドノウハウパターンでも無いよりは良いかな、という印象です。

4. パターン1: errorの文字列で

errors.Newなりfmt.Errorfの文字列を受け取り側で比較するというものです。

単純ですがバッドノウハウとされているパターンです。

サンプル

サンプルコード

package main

import (
  "errors"
  "fmt"
  "os"
)

const (
  ERROR_MSG_01 = "doSomething is error. b is true"
  ERROR_MSG_02 = "doSomething is error. b is false"
)

func doSomething(b bool) error {

  if b {
    return errors.New(ERROR_MSG_01)

  } else {
    return errors.New(ERROR_MSG_02)
  }

  return nil
}

func main() {

  err := doSomething(true)

  if fmt.Sprintf("%s", err) == ERROR_MSG_01 {
    fmt.Println("ERROR: ERROR_MSG_01に応じた処理を行う")
    os.Exit(1)

  } else if fmt.Sprintf("%s", err) == ERROR_MSG_02 {
    fmt.Println("ERROR: ERROR_MSG_02に応じた処理を行う")
    os.Exit(1)
  }
  fmt.Println("main is success")
}
出力
$ go run src/go-error-handling/sample03/main.go 
ERROR: ERROR_MSG_01に応じた処理を行う
exit status 1
困る点

ハンドリング後、さらに呼び出し元に返そうとするととたんに困ります…

  // fmt.Errorfでさらに呼び出し元に返すとハンドリングできなく...
  if fmt.Sprintf("%s", err) == ERROR_MSG_01 {
    return fmt.Errorf("ERROR: err=%+v", err)
  }

5. パターン2: errors.Newのインスタンス

errors.Newのインスタンスで比較するパターンです。

osパッケージなんかでも使われてたりします
https://golang.org/src/os/error.go#L11

サンプル

サンプルコード

package main

import (
  "errors"
  "fmt"
  "os"
)

const (
  ERROR_MSG_01 = "doSomething is error. b is true"
  ERROR_MSG_02 = "doSomething is error. b is false"
)

var (
  ERROR_01 = errors.New(ERROR_MSG_01)
  ERROR_02 = errors.New(ERROR_MSG_02)
)

func doSomething(b bool) error {

  if b {
    return ERROR_01

  } else {
    return ERROR_02
  }

  return nil
}

func main() {

  err := doSomething(false)

  if err == ERROR_01 {
    fmt.Println("ERROR: インスタンスERROR_01に応じた処理を行う")
    os.Exit(1)

  } else if err == ERROR_02 {
    fmt.Println("ERROR: インスタンスERROR_02に応じた処理を行う")
    os.Exit(1)
  }
  fmt.Println("main is success")
}

コード自体はだいぶマシになった気はしてきます

出力
$ go run src/go-error-handling/sample04/main.go 
ERROR: インスタンスERROR_02に応じた処理を行う
exit status 1
困る点

パターン1と同様ですがハンドリングの結果、上位にエラーを返すときに困ります。

そのまま返すとどこでエラーだったのかわかりずらくなり、
fmt.Errorfなどで新規にインスタンスを作ってしまうと別物になってしまいます。

  // そのまま返し続けると結局どこのエラーだったのか...という感じに
  if err == ERROR_01 {
    return ERROR_01
  }
  // fmt.Errorfをかますと、違うインスタンスになってしまう
  if err == ERROR_01 {
    return fmt.Errorf("ERROR: err=%+v", ERROR_01)
  } 

6. パターン3: カスタムエラーのインスタンス

【go】golangのエラー処理メモ - ①. errorとError型とカスタムErrorと
でも触れたカスタムエラーを定義してそのインスタンスでハンドリングするパターンです。
1つのカスタムエラーを使い回してますが、カスタムエラー自体を複数用意しても良いです。

サンプル

サンプルコード

package main

import "fmt"

const (
  ERROR_MSG_01 = "doSomething is error. b is true"
  ERROR_MSG_02 = "doSomething is error. b is false"
)

type MyError struct {
  Msg  string
  Code int
}

func (err *MyError) Error() string {
  return fmt.Sprintf("%s, %d", err.Msg, err.Code)
}

var (
  MyError_01 = &MyError{Msg: "MyError_001 is occur", Code: 30001}
  MyError_02 = &MyError{Msg: "MyError_002 is occur", Code: 30002}
)

func doSomething(b bool) error {

  if b {
    return MyError_01

  } else {
    return MyError_02
  }

  return nil
}

func main() {

  err := doSomething(false)

  switch err {
  case MyError_01:
    fmt.Println("ERROR: インスタンスMyError_01に応じた処理")
    fmt.Printf("ERROR: %+v\n", err)

  case MyError_02:
    fmt.Println("ERROR: インスタンスMyError_02に応じた処理")
    fmt.Printf("ERROR: %+v\n", err)

    // ちなみにdoSomethingの返り値は
    // errorインターフェースであってMyError_01ではない。
    // ココに以下のようなコードは書けない
    //fmt.Printf("ERROR: Msg=%s, Code=%d", err.Msg, err.Code)
  }
  fmt.Println("main is success")
}
出力
$ go run src/go-error-handling/sample05/main.go 
ERROR: インスタンスMyError_02に応じた処理
ERROR: MyError_002 is occur, 30002
main is success
困る点

パターン2に同じ

7. パターン4: カスタムエラーの型で

カスタムエラーの型でハンドリングするパターンです。

err.(type)という記述をしますが、
これはerrorがinterface型のために行えるらしいです。(知らなかった)

また、これをConversion構文というらしいです。
https://golang.org/ref/spec#Conversions

サンプル

サンプルコード

package main

import "fmt"

type MyError_01 struct {
  Code int
}

func (err *MyError_01) Error() string {
  return fmt.Sprintf("this is MyError_01")
}

type MyError_02 struct {
  Code int
}

func (err *MyError_02) Error() string {
  return fmt.Sprintf("this is MyError_02")
}

func doSomething(b bool) error {

  if b {
    return &MyError_01{Code: 30001}

  } else {
    return &MyError_02{Code: 30002}
  }

  return nil
}

func main() {

  err := doSomething(false)

  switch e := err.(type) {
  case *MyError_01:
    fmt.Println("ERROR: MyError_01の型に応じた処理")
    fmt.Printf("ERROR: err=%+v, e=%+v, code=%d\n", err, e, e.Code)

  case *MyError_02:
    //fmt.Printf("ERROR: MyError_02のエラー, err=%+v, code=%d\n", e, e.Code)
    fmt.Println("ERROR: MyError_02の型に応じた処理")
    fmt.Printf("ERROR: err=%+v, e=%+v, code=%d\n", err, e, e.Code)
  }

  fmt.Println("main is success")
}
出力
$ go run src/go-error-handling/sample06/main.go 
ERROR: MyError_02の型に応じた処理
ERROR: err=this is MyError_02, e=this is MyError_02, code=30002
main is success
困る点

これまでの中では一番すっきりした感があります。

しかし、参考サイトまんまの受け売りですが、
このままerrorを上に上に伝搬させていくと
上位ロジックが全てのerrorを把握している必要がある、という感じ。

ではどうするのか

pkg/errorsを使うと良いらしい
が、長くなったのでまた次の記事にします。

これもまた参考サイトが非常に参考になりました!

おわり

errorについても奥が深い!\(^o^)/

【go】golangのエラー処理メモ - ①. errorとError型とカスタムErrorと

はじめに

goをさわって数ヶ月ですが、雰囲気では書けていたものの
errorやエラーハンドリングについてはもやもやしたままだったので自分理解メモの①

関連

この記事の関連です。

アジェンダ

  1. errorの基本の書き方
  2. Error型について
  3. 任意の文字列でError型を返す(errors.Newとfmt.Error)
  4. カスタムError

1. errorの基本の書き方

以下のコードがerrorについての基本です。

// Openに成功したらnil(エラー無し)が返される
// Openに失敗したらerror側の値が返却される
f, err := os.Open("filename.ext")
if err != nil {
    log.Fatal(err)
}

返されるerror変数とnilを比較することで操作が成功したか判断します。
上記で言えば if err != nil { です。

os.Openの定義は以下のようになっています。

func Open(name string) (file *File, err error)
https://golang.org/pkg/os/#Open

2. Error型について

errorはgoのビルトインのインターフェース型の1つです。

type error interface {
    Error() string
}

多くの内部パッケージにおいて使用されるerrorは
errorsパッケージ以下で実装されたプライベート構造体errorStringらしいです。

// Package errors implements functions to manipulate errors.
package errors

// New returns an error that formats as the given text.
func New(text string) error {
  return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
  s string
}

func (e *errorString) Error() string {
  return e.s
}

使う場合は、errors.Newを通して文字列をerrorStringに変換し
インターフェースerrorを満たすオブジェクトを得る、という感じになってます。

3. 任意の文字列でError型を返す(errors.Newとfmt.Error)

Error型について触れましたが、任意の文字列でerror型を返すには主に以下の2つがメジャーです。

用途としての大きな違いは、
fmt.Errorはフォーマットを指定したエラーを返せる ので
固定文字列でよければerrors.New、可変文字列を含めたければfmt.Errorという感じでしょうか。

以下で使ってみます。

errors.New

errors.Newに文字列を渡すだけです。

サンプル

https://github.com/tweeeety/go-error/blob/master/src/go-error/sample01/main.go

package main

import (
  "errors"
  "fmt"
)

func errorsNewSsample() error {
  err := errors.New("this is errors.New sample.")
  return err
}

func main() {
  err := errorsNewSsample()

  fmt.Println(err)
  fmt.Printf("%T\n", err)
}
出力
$ go run src/go-error/sample01/main.go 
this is errors.New sample.
*errors.errorString

fmt.Error

フォーマット文字列を渡せるので、変数の値を一緒に出したい場合などに使います。

サンプル

https://github.com/tweeeety/go-error/blob/master/src/go-error/sample02/main.go

package main

import (
  "fmt"
)

func fmtErrorfSsample(str string) error {
  err := fmt.Errorf("this is fmt.Errorf sample. str: %s", str)
  return err
}

func main() {
  err := fmtErrorfSsample("hogehoge")
  fmt.Println(err)
  fmt.Printf("%T\n", err)
}
出力
$ go run src/go-error/sample02/main.go 
this is fmt.Errorf sample. str: hogehoge
*errors.errorString

4. カスタムError

2. Error型についてで触れた通り
errorインターフェース満たすにはError()を実装すれば良いです。

この方法で任意のカスタムError型を作ります。

sample01/main.go
package main

import (
  "fmt"
)

// カスタムErrorの構造体
type MyError struct {
  Msg  string
  Code int
}

// error interfaceを実装
func (err *MyError) Error() string {
  return fmt.Sprintf("ERROR: %d %s", err.Code, err.Msg)
}

// 何かする処理
func doSomething() error {
  return &MyError{Msg: "doSomething is unexpected error", Code: 30001}
}

func main() {
  if err := doSomething(); err != nil {
    fmt.Println(err)
    fmt.Printf("%T\n", err)
  }
}
出力
$ go run src/go-error/sample03/main.go
ERROR: 30001 doSomething is unexpected error
*main.MyError

おわり

errorの扱いについてサラっとまとめました。
あまり長いと書くのも読むのも疲れるのでエラーハンドリングについては別記事でかきます\(^o^)/

参考

【mac】macでポート(port)を使用しているプロセス(pid)を調べる - 例) goapp serve

はじめに

localなmacで開発をしているとたまに既にport使用してるから立ち上げられんで!みたいなエラーがでる事があります。
そんなときにプロセスを調べるメモ

調べ方

先んじて結論ですが、lsof で調べます。
8080を使っているプロセスを知りたい時のコマンドです

sudo lsof -P -i:8080

こんな時 例

今回の例ですが、ポートを指定してlocalにサーバを立ち上げる とします。
もうちょっと具体的にすると、localなmacgolang x appengineの開発を行おうとしている、という例として進めます。

goapp serve hoge.yamlはlocalにサーバを立ち上げますが、
これはデフォルトで8080ポートを使用します。

いざ立ち上げようと思ったらこんなエラーが出ました。

$ goapp serve hoge.yaml 
INFO     2017-08-07 07:57:54,539 devappserver2.py:764] Skipping SDK update check.
INFO     2017-08-07 07:57:54,602 api_server.py:268] Starting API server at: http://localhost:62294
INFO     2017-08-07 07:57:54,606 api_server.py:700] Applying all pending transactions and saving the datastore
INFO     2017-08-07 07:57:54,606 api_server.py:703] Saving search indexes
Traceback (most recent call last):
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/dev_appserver.py", line 101, in <module>
    _run_file(__file__, globals())
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/dev_appserver.py", line 97, in _run_file
    execfile(_PATHS.script_file(script_name), globals_)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/devappserver2.py", line 1041, in <module>
    main()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/devappserver2.py", line 1029, in main
    dev_server.start(options)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/devappserver2.py", line 825, in start
    options.grpc_apis)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/dispatcher.py", line 196, in start
    _module.start()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/module.py", line 1198, in start
    self._balanced_module.start()
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/wsgi_server.py", line 330, in start
    self._start_all_fixed_port(host_ports)
  File "/usr/local/Cellar/app-engine-go-64/1.9.48/share/app-engine-go-64/google/appengine/tools/devappserver2/wsgi_server.py", line 367, in _start_all_fixed_port
    raise BindError('Unable to bind %s:%s' % self.bind_addr)
google.appengine.tools.devappserver2.wsgi_server.BindError: Unable to bind localhost:8080
error while running dev_appserver.py: exit status 1

Unable to bind localhost:8080 とあるのでポートがすでに使われている可能性はあるもののterminal上どこでも立ち上げてる形跡はない…という状況です。

そのときのコマンド例

8080を使用しているプロセスを調べます。

$ sudo lsof -P -i:8080 
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
Python  58645 hoge   11u  IPv6 0x51abc044e9105fdb      0t0  TCP localhost:8080 (LISTEN)
Python  58645 hoge   12u  IPv4 0x51abc044e8ae2963      0t0  TCP localhost:8080 (LISTEN)

このプロセスに思い当たりがなければ思い切ってkillします。

$ sudo kill -9 58645 58645

再度立ち上げてみると無事立ち上がりました。めでたし

$ goapp serve local_production.yaml 
INFO     2017-08-07 08:47:58,533 devappserver2.py:764] Skipping SDK update check.
INFO     2017-08-07 08:47:58,611 api_server.py:268] Starting API server at: http://localhost:62971
INFO     2017-08-07 08:47:58,616 dispatcher.py:199] Starting module "borr" running at: http://localhost:8080
INFO     2017-08-07 08:47:58,621 admin_server.py:116] Starting admin server at: http://localhost:8000
WARNING  2017-08-07 08:47:58,621 devappserver2.py:836] No default module found. Ignoring.

オプション

申しわけ程度にlsofのオプションです。

オプション 説明
-c プロセス名を指定する
-i ネットワークソケットファイルを表示する
-n IPアドレスを表示する(名前解決しない)
-p プロセスIDを指定する
-P ポート番号をサービス名に変換しない

おわり

lsofはlinuxでも比較的よく使いますがオプション忘れては調べてるので備忘録的に書きました!

【SublimeText】jsHintとSublimeLinter-jshintを入れるメモ for mac

はじめに

久しぶりにsublimeが使いたい用途があり
今さらですがSublimeLinter-jshintを入れたので簡易手順メモ。

ちなみにES6などはESlintのほうが良いです。

アジェンダ

  1. jsHintをインストー
  2. jsHint/SublimeLinter/SublimeLinter-jshintについて
  3. SublimeLinterのインストー
  4. SublimeLinter-jshintのインストー
  5. 使ってみる

1. jsHintをインストー

jsHintのインストールはterminalコマンドで行います。

また、npmでインストールするのでnodeは必要ですが今回は省きます。
nodeとnpmが入っていれば以下のコマンドでjsHintインストールは終わりです。

# インストール
$ npm install -g jshint

# 確認
$ jshint -v
jshint v2.9.5

2. jsHint/SublimeLinter/SublimeLinter-jshintについて

休憩がてら自分用メモです。

jshintについて

jshintはコマンドで入れたように、SublimeLinter-jshint がなくても単体でjsHintとして動きます。

例えば以下コードを保存してjshintをコマンド実行する事もできます。

  • sample.js
(function(){
  "strict"
})();
  • 実行
# jsが入ってるディレクトリに対してjshint
$ jshint js_dir
js_dir/sample.js: line 2, col 11, Missing semicolon.

1 error

vimでも使えるので便利です。

SublimeTextについて

ここからはsublimeText上で行います。

SublimeTextでのパッケージインストールはPackage Controlが必要ですが、これも今回は省きます。

たまにしかSublimeを開かない自分用に
よく忘れるPackage Controlのショートカットも書いておきます。

Ctrl + Shift + p

SublimeLinterとSublimeLinter-jshintについて

SublimeLinterはリアルタイムにコードのエラーをチェックできるフレームワークのようなものです。
jsに限らず様々な言語のlinterとして動作しますが、言語ごとの設定を持っていません。

そこで、SublimeLinter-jshintというjavascript用のプラグインを追加で入れる事で
linter + javascriptな環境になります。

3. SublimeLinterのインストー

Package Controlから入れるだけです。

Ctrl + Shift + pでPackage Control開いてinstallと入力します。
Package Control: Install Packageを選択します。
f:id:tweeeety:20170725221240p:plain

ダイアログが開いたらSublimeLinterを選択してインストール完了です。 f:id:tweeeety:20170725221300p:plain

4. SublimeLinter-jshintのインストー

SublimeLinterと手順は同様です。

Ctrl + Shift + pでPackage Control開いてinstallと入力します。
Package Control: Install Packageを選択します。
ダイアログが開いたらSublimeLinter-jshintを選択してインストール完了です。

5. 使ってみる

使う前に、SublimeTextを再起動しておきます。
これをしないと動かないなーなんてことも。

適当なファイルを保存して開いてみると
先ほど書いたファイルを開いてみるとエラーの行数にオレンジのマークをしてくれます。 f:id:tweeeety:20170725221703p:plain

また、画面下部ににエラー内容も表示してくれます。

UTF-8, Error: Missing semicolon, Line2, Column11

おわり

久しぶりにsublime使いましたがパッケージのインストールもお手軽 \(^o^)/

【git】.gitignoreの書き方 - テンプレートを使うその3 - 任意のファイルを.gitignoreとして読み込む

はじめに

git管理化から特定のファイルなどを無視したければ.gitignoreに追加します。
しかもだいたいが適宜気づいたら、つどつど。

ただ、言語、フレームワーク、ツールなどのファイルは
新しいプロジェクトのたび x 適宜気づくたびに追加するのは面倒です。

そこで、
プロジェクトによらない.gitignoreしたいものはテンプレ化しておきたいですよね。
.gitignoreテンプレ化については以下を参考にしてみてください。

しかし、せっかくテンプレは手にいれたものの
vim使ってるの自分だけだしプロジェクトの.gitignoreを汚したくない…
そんなときのメモです。

やってみる

.gitignoreファイルはリポジトリ直下にある.gitignore以外にも
configのcore.excludesfileに任意のファイルを指定する事で無視してくれます。

なので、例えば$HOME/.gitignore_myというファイルを作り
そこに個人的なignoreリストを作成してconfigに登録しておくことで、
チーム共通のリポジトリ.gitignoreを汚さずにすみます

# 
$ cd `プロジェクトリポジトリ`

# ${プロジェクトディレクトリ}/.gitignoreの他に読み込むファイルを指定
$ git config --local core.excludesfile $HOME/.gitignore_my

# .git/configに追記されている
$ cat .git/config 
[core]
  ~ 省略 ~ 
  excludesfile = /Users/hoge/.gitignore_my
  ~ 省略 ~ 

こうしておけば
gitignore.iogiboので取得した自分だけが使ってるツールなどのgitignoreテンプレート設定を別にすることができます。

おわり

gitは長らく使ってるつもりでも知らない事が多いですね\(^o^)/

【git】.gitignoreの書き方 - テンプレートを使うその2 - gibo(gitignore boilerplates)

はじめに

git管理化から特定のファイルなどを無視したければ.gitignoreに追加します。
しかもだいたいが適宜気づいたら、つどつど。

ただ、言語、フレームワーク、ツールなどのファイルは
新しいプロジェクトのたび x 適宜気づくたびに追加するのは面倒です。

そこで、
今回はお決まりのgitignoreテンプレを提供してくれるgiboのメモ

アジェンダ

  1. giboとは
  2. giboを使ってみる for mac

1. giboとは

公式サイトはこちらです。 https://github.com/simonwhitaker/gibo

gibo (short for .gitignore boilerplates) is a shell script to help you easily access .gitignore boilerplates from github.com/github/gitignore.

公式からですが、giboはgithub.com/github/gitignoreのボイラープレートにアクセスしてくれるshell script とのことです。

むしろボイラープレートって言葉が初耳でした..w
ボイラープレートとは

2. giboを使ってみる for mac

使い方は簡単です。
macでhomebrewを使っているならbrew install giboとするだけです。

使ってみた感じです。

gibo入れる
# インストール
$ brew install gibo

# version確認してみる
# + 何か怒られるが、これは後述する-lすると.gitignore-boilerplatesが作られて解消されます
gibo --version
fatal: Cannot change to '/Users/hoge/.gitignore-boilerplates': No such file or directory
gibo 1.0.5 by Simon Whitaker <sw@netcetera.org>

# git -lでリスト確認
# + .gitignore-boilerplates の作成
$ gibo -l
fatal: Cannot change to '/Users/hoge/.gitignore-boilerplates': No such file or directory
Cloning https://github.com/github/gitignore.git to /Users/hoge/.gitignore-boilerplates
Cloning into '/Users/hoge/.gitignore-boilerplates'...
remote: Counting objects: 6896, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 6896 (delta 6), reused 11 (delta 2), pack-reused 6880
Receiving objects: 100% (6896/6896), 1.37 MiB | 299.00 KiB/s, done.
Resolving deltas: 100% (3687/3687), done.
Checking connectivity... done.
=== Languages ===

Actionscript    CommonLisp    Erlang      IGORPro     Maven     Prestashop    Scrivener   Unity
Ada     Composer    ExpressionEngine  Java      Mercury     Processing    Sdcc      UnrealEngine
Agda      Concrete5   ExtJs     Jboss     MetaProgrammingSystem PureScript    SeamGen     VisualStudio
Android     Coq     Fancy     Jekyll      Nanoc     Python      SketchUp    VVVV
AppceleratorTitanium  CraftCMS    Finale      Joomla      Nim     Qooxdoo     Smalltalk   Waf
AppEngine   CUDA      ForceDotCom   Julia     Node      Qt      Stella      WordPress
ArchLinuxPackages D     Fortran     KiCad     Objective-C   R     SugarCRM    Xojo
Autotools   Dart      FuelPHP     Kohana      OCaml     Rails     Swift     Yeoman
C++     Delphi      Gcov      LabVIEW     Opa     RhodesRhomobile   Symfony     Yii
C     DM      GitBook     Laravel     OpenCart    ROS     SymphonyCMS   ZendFramework
CakePHP     Drupal      Go      Leiningen   OracleForms   Ruby      Terraform   Zephir
CFWheels    Eagle     Gradle      LemonStand    Packer      Rust      TeX
ChefCookbook    Elisp     Grails      Lilypond    Perl      Sass      Textpattern
Clojure     Elixir      GWT     Lithium     Phalcon     Scala     TurboGears2
CMake     Elm     Haskell     Lua     PlayFramework   Scheme      Typo3
CodeIgniter   EPiServer   Idris     Magento     Plone     SCons     Umbraco

=== Global ===

Anjuta      CVS     Espresso    Lazarus     ModelSim    Redis     TextMate    Xcode
Ansible     DartEditor    FlexBuilder   LibreOffice   Momentics   SBT     TortoiseGit   XilinxISE
Archives    Dreamweaver   GPG     Linux     MonoDevelop   SlickEdit   Vagrant
Bazaar      Dropbox     JDeveloper    LyX     NetBeans    Stata     Vim
BricxCC     Eclipse     JEnv      macOS     Ninja     SublimeText   VirtualEnv
Calabash    EiffelStudio    JetBrains   Matlab      NotepadPP   SVN     VisualStudioCode
Cloud9      Emacs     Kate      Mercurial   Otto      SynopsysVCS   WebMethods
CodeKit     Ensime      KDevelop4   MicrosoftOffice   Redcar      Tags      Windows
[~ 15:44:06]$ gibo --version
gibo 1.0.5 by Simon Whitaker <sw@netcetera.org>
https://github.com/simonwhitaker/gibo

# 再度versionを確認
$ gibo --version
gibo 1.0.5 by Simon Whitaker <sw@netcetera.org>
https://github.com/simonwhitaker/gibo
gibo使う

vim用のgitignoreを出力してみる

$ gibo vim
### https://raw.github.com/github/gitignore/8edb8a95c4c4b3dce71a378aaaf89275510b9cef/Global/vim.gitignore

# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]

# Session
Session.vim

# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
その他

見ての通り標準出力に出力されるだけなので自分で追記してやります。

$ gibo vim >> .gitignore

また、適宜updateして更新してあげましょう。

$ gibo -u

おわり

こういうテンプレは自分でメンテしてくのも大変だし
お任せできるって素敵ですね\(^o^)/