Javaプログラマ向けGoガイド
Seasar Conference 2015
2015/09/26
米 林 正 明 @yone098
自己紹介
 米 林 正 明
 @yone098
 株式会社Abby(エビイ) 代表取締役
はじめに
 私とGo
 約1年 サーバサイドAPI
 今一番好きな言語
 Eclipse は数ヶ月起動していない
 わからない事は?
全部@mopemopeに聞けばいい
 対象
 Goに興味があるJavaプログラマ
 Goを少し触ったことがある人
agenda
 はじめに
 JavaからGoへ
 Go開発事例
 おわりに
Goとは
 静的型付けコンパイル言語
 C言語に近くLLではない
 継承がない
 ジェネリクスがない
 例外がない
 ライブラリのバージョン指定がない
Goとは
 静的型付けコンパイル言語
 C言語に近くLLではない
 継承がない
 ジェネリクスがない
 例外がない
 ライブラリのバージョン指定がない
 でも「まんまん満足!」
Goとは
 静的型付けコンパイル言語
 C言語に近くLLではない
 継承がない
 ジェネリクスがない
 例外がない
 ライブラリのバージョン指定がない
 でも「まんまん満足!」
 いいところ満載
JavaからGoへ
JavaからGoへ
 LLではないがLLに近い実行方法
 コンパイルと同時に実行出来る
 javac と java コマンドの合わせ技
$ go run main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("SeasarCon2015")
}
JavaからGoへ
 LLではないがLLに近い実行方法
 コンパイルと同時に実行出来る
 javac と java コマンドの合わせ技
$ go run main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("SeasarCon2015")
}
$ go run main.go
SeasarCon2015
JavaからGoへ
 LLではないがLLに近い実行方法
 コンパイルと同時に実行出来る
 javac と java コマンドの合わせ技
$ go run main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("SeasarCon2015")
}
$ go run main.go
SeasarCon2015
取り急ぎやってごらん
JavaからGoへ
 Java : classpath
 Go : $GOPATH
 go get で install
$ go get github.com/zenazn/goji
bin/
pkg/
src/
github.com/zanazn/goji
bitbucket.org/…
golang.org/…
JavaからGoへ
 Java : classpath
 Go : $GOPATH
 go get で install
$ go get github.com/zenazn/goji
bin/
pkg/
src/
github.com/zanazn/goji
bitbucket.org/…
golang.org/…
your_project/
.m2repo配下で開発するイメージ
JavaからGoへ
 package
 名前とモジュール管理 import パッケージ
 重複時 Go : alias
 重複時 Java : パッケージ名 + class名
package main
import (
"log" // logを取り込む
"github.com/zenazn/goji" // gojiを取り込む
mylog “myproject/log” // 自作logを取り込む
)
func main() {
mylog.Debugf("Go!")
...
}
JavaからGoへ
 package
 名前とモジュール管理 import パッケージ
 重複時 Go : alias
 重複時 Java : パッケージ名+class名
package main
import (
"log" // logを取り込む
"github.com/zenazn/goji" // gojiを取り込む
mylog “myproject/log” // 自作logを取り込む
)
Javaのようにコンパイル時にライブラリ指定が不
要でありソースコードで依存関係を明確にする
JavaからGoへ
 アクセス指定子
 Java : private, public
 Go : 大文字・小文字
package main
import (
"./sub"
"fmt"
)
func main() {
fmt.Println(sub.Func1())
fmt.Println(sub.func2()) // NG
}
package sub
func Func1() string {
return "Func1"
}
func func2() string {
return "func2"
}
JavaからGoへ
 アクセス指定子
 Java : private, public
 Go : 大文字・小文字
package main
import (
"./sub"
"fmt"
)
func main() {
fmt.Println(sub.Func1())
fmt.Println(sub.func2()) // NG
}
package sub
func Func1() string {
return "Func1"
}
func func2() string {
return "func2"
}
基本、メソッドやメンバは大文字から始めパッ
ケージ外に公開したくない場合は小文字ちゃん
JavaからGoへ
 interface
 Java : implements
 Go : メソッド定義
 メソッド定義でどんなオブジェクトでも代入可能
package main
func say(yone Yone) {
fmt.Println(yone.hello())
}
func main() {
var mope Mope
say(mope)
}
type Yone interface {
hello() string
}
type Mope struct{}
func (_ Mope) hello() string {
return "mope"
}
JavaからGoへ
 cast
 Java : (データ型)式 or ジェネリクス
 Go : 型アサーション 式.(データ型)
var i interface{} = "hoge”
if s, ok := i.(string); ok {
fmt.Println("String: ", s)
} else {
fmt.Println("Not String” , s)
}
JavaからGoへ
 cast
 Java : (データ型)式 or ジェネリクス
 Go : 型アサーション
var i interface{} = "hoge”
if s, ok := i.(string); ok {
fmt.Println("String: ", s)
} else {
fmt.Println("Not String")
}
iがstringであればsに変換結果, okにはtrueがセットされる。
そうでなければsにstring初期値, okにはfalseがセットされる。
okを指定せず戻り値をsだけにして型アサーションした場合には型変
換に失敗した場合にはランタイムパニックになる。
JavaからGoへ
 例外
 Java : Exception, try-catch
 Go : 無し!とにかく if err != nil
 常にエラーを返す
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
JavaからGoへ
 例外
 Java : Exception, try-catch
 Go : 無し!とにかく if err != nil
 常にエラーを返す
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
JavaからGoへ
 例外
 Java : Exception, try-catch
 Go : 無し!とにかく if err != nil
 常にエラーを返す
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
err := func1()
if err != nil {
// エラー処理
}
err = func2()
if err != nil {
// エラー処理
}
err = func3()
if err != nil {
// エラー処理
}
err = func4()
if err != nil {
// エラー処理
}
これがGoだ!これがGoだ!これがGoだ!これがGoだ!これがGo
だ!これがGoだ!これがGoだ!これがGoだ!これがGoだ!これが
JavaからGoへ
 戻り値
 Java : 単一
 Go : 多値
 受け取り無視にはブランク識別子
val, err := sum(1, 2)
if err != nil {
// エラー処理
}
val, _, _, err = func2()
if err != nil {
// エラー処理
}
JavaからGoへ
 戻り値
 Java : 単一
 Go : 多値
 受け取り無視にはブランク識別子
val, err := sum(1, 2)
if err != nil {
// エラー処理
}
val, _, _, err = func2()
if err != nil {
// エラー処理
}
値の受け取りを無視しても良いが戻り値のerrをブランク識別子で受けて
はダメなんだぞぉ〜。Javaのtry-catchで処理を書かないことと同じ!
JavaからGoへ
 資源解放
 Java : try-finally
 Go : defer
func finally() {
fmt.Println("finally")
}
func main() {
defer finally()
for i := 0; i < 10; i++ {
fmt.Println("i:", i)
}
}
JavaからGoへ
 資源解放
 Java : try-finally
 Go : defer
func finally() {
fmt.Println("finally")
}
func main() {
defer finally()
for i := 0; i < 10; i++ {
fmt.Println("i:", i)
}
}
deferは関数終了時にコールされる。
複数deferを登録すると最後に登録したdeferから実行される。
$ go run main.go
i: 0
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
finally
JavaからGoへ
 初期化子
 Java : staticイニシャライザ
 Go : init()
package sub
import (
"fmt"
)
func init() {
fmt.Println("sub init()")
}
func Func1() {
fmt.Println("Func1")
}
package main
import (
"./sub"
"fmt"
)
func main() {
fmt.Println("SeasarCon2015")
sub.Func1()
}
JavaからGoへ
 初期化子
 Java : staticイニシャライザ
 Go : init()
package sub
import (
"fmt"
)
func init() {
fmt.Println("sub init()")
}
func Func1() {
fmt.Println("Func1")
}
初期化関数はmain関数の定義されたソースから連鎖的にimportされた
パッケージのみのため予期せず使用しないソースのinitは実行されない
package main
import (
"./sub"
"fmt"
)
func main() {
fmt.Println("SeasarCon2015")
sub.Func1()
}
JavaからGoへ
 配布形式
 Java : jar, war
 配布には必要ライブラリを含める
 Go : 単一の実行可能ファイル
 クロスコンパイル
GOOS=windows GOARCH=amd64 go build -o seasar.exe
GOOS=darwin GOARCH=amd64 go build -o seasar
GOOS=linux GOARCH=amd64 go build -o seasar
JavaからGoへ
 配布形式
 Java : jar, war
 配布には必要ライブラリを含める
 Go : 単一の実行可能ファイル
 クロスコンパイル
配布がとくかく容易
GOOS=windows GOARCH=amd64 go build -o seasar.exe
GOOS=darwin GOARCH=amd64 go build -o seasar
GOOS=linux GOARCH=amd64 go build -o seasar
JavaからGoへ
 本番と開発の設定変更
 Java : profile(maven, Spring Boot)
 Go : tag
go build –tags release
// +build !release
package env
const DEBUG = true
// +build release
package env
const DEBUG = false
env.go env_release.go
if env.DEBUG {
log.Println(”debug print")
}
JavaからGoへ
 アノテーション
 Java : annotasion
 Go : tag
type Person struct {
Id int64 `json:"code"`
Name string `json:“name“`
Age int `json:“age"`
CreatedAt int64
}
JavaからGoへ
 Test
 Java : JUnit
 Assert
 Go : testing
 Assertは無い, if文で
 ソースファイルと同一パッケージ
 calc.go なら calc_test.go
func TestSum(t *testing.T) {
actual := Sum(1, 2)
expected := 3
if actual != expected {
t.Errorf(”actual %v expected %v", actual, expected)
}
}
JavaからGoへ
 コード整形
 Java : IDE
 Go : gofmt, goimports
 公式サポート
 コードの統一
 golint, go vet でチェック
JavaからGoへ
 依存関係
 Java : gradle, maven
 Go : godep, gb, vendor
 バージョン指定が出来ない
 マルチプロジェクトで困る
 $GOPATH/src以下にfetch
 Go1.5 Vendoring!
JavaからGoへ
 Javaプログラマ向けチートシート
 javac->java : go run
 classpath : $GOPATH
 import : import
 public, private : 大文字・小文字
 implements : メソッド定義
 (データ型)式 : v, ok := 式.(データ型)
 例外あり : 例外無し if err != nil
 単一を返す : 多値を返せる
 try-finally : defer
 static{} : init()
 jar, war : クロスコンパイル
 profile : -tags
 @annotation : タグ
 JUnit : testing
 IDE : gofmt, goimports
 gradle, maven : godep, gb, vendor
Go開発事例
Go開発事例
 ムーミン APIサーバ
 Go1.4
 goji
 godep, fresh
 drone slack通知 成果物dropbox
 DDLをbranch毎
 goconvey カバレッジ
 circus
 nginx
 mysql join禁止
 log LTSV, Elasticsearch, kibana
 管理画面
 @mopeomope
Go開発事例
 最新
 Go1.5
 goji, gorm, pq
 gb, goemon, goconvey
 drone slack通知 成果物dropbox
 nginx
 postgresql
 Redis Pub/Sub
 websocket
終わりに
終わりに
 みんなもGoやろう!
 プロダクトで使ってみた感想
 JavaプログラマにはGoは向いていると思う!
 これからもGoを採用していく予定
 Go1.5
 期待!
おまけ
Goよりも
普通に
Ingressが好き💙
Thank you!

Go guide for Java programmer

  • 1.
  • 2.
    自己紹介  米 林正 明  @yone098  株式会社Abby(エビイ) 代表取締役
  • 3.
    はじめに  私とGo  約1年サーバサイドAPI  今一番好きな言語  Eclipse は数ヶ月起動していない  わからない事は? 全部@mopemopeに聞けばいい  対象  Goに興味があるJavaプログラマ  Goを少し触ったことがある人
  • 4.
    agenda  はじめに  JavaからGoへ Go開発事例  おわりに
  • 5.
    Goとは  静的型付けコンパイル言語  C言語に近くLLではない 継承がない  ジェネリクスがない  例外がない  ライブラリのバージョン指定がない
  • 6.
    Goとは  静的型付けコンパイル言語  C言語に近くLLではない 継承がない  ジェネリクスがない  例外がない  ライブラリのバージョン指定がない  でも「まんまん満足!」
  • 7.
    Goとは  静的型付けコンパイル言語  C言語に近くLLではない 継承がない  ジェネリクスがない  例外がない  ライブラリのバージョン指定がない  でも「まんまん満足!」  いいところ満載
  • 8.
  • 9.
    JavaからGoへ  LLではないがLLに近い実行方法  コンパイルと同時に実行出来る javac と java コマンドの合わせ技 $ go run main.go package main import ( "fmt" ) func main() { fmt.Println("SeasarCon2015") }
  • 10.
    JavaからGoへ  LLではないがLLに近い実行方法  コンパイルと同時に実行出来る javac と java コマンドの合わせ技 $ go run main.go package main import ( "fmt" ) func main() { fmt.Println("SeasarCon2015") } $ go run main.go SeasarCon2015
  • 11.
    JavaからGoへ  LLではないがLLに近い実行方法  コンパイルと同時に実行出来る javac と java コマンドの合わせ技 $ go run main.go package main import ( "fmt" ) func main() { fmt.Println("SeasarCon2015") } $ go run main.go SeasarCon2015 取り急ぎやってごらん
  • 12.
    JavaからGoへ  Java :classpath  Go : $GOPATH  go get で install $ go get github.com/zenazn/goji bin/ pkg/ src/ github.com/zanazn/goji bitbucket.org/… golang.org/…
  • 13.
    JavaからGoへ  Java :classpath  Go : $GOPATH  go get で install $ go get github.com/zenazn/goji bin/ pkg/ src/ github.com/zanazn/goji bitbucket.org/… golang.org/… your_project/ .m2repo配下で開発するイメージ
  • 14.
    JavaからGoへ  package  名前とモジュール管理import パッケージ  重複時 Go : alias  重複時 Java : パッケージ名 + class名 package main import ( "log" // logを取り込む "github.com/zenazn/goji" // gojiを取り込む mylog “myproject/log” // 自作logを取り込む ) func main() { mylog.Debugf("Go!") ... }
  • 15.
    JavaからGoへ  package  名前とモジュール管理import パッケージ  重複時 Go : alias  重複時 Java : パッケージ名+class名 package main import ( "log" // logを取り込む "github.com/zenazn/goji" // gojiを取り込む mylog “myproject/log” // 自作logを取り込む ) Javaのようにコンパイル時にライブラリ指定が不 要でありソースコードで依存関係を明確にする
  • 16.
    JavaからGoへ  アクセス指定子  Java: private, public  Go : 大文字・小文字 package main import ( "./sub" "fmt" ) func main() { fmt.Println(sub.Func1()) fmt.Println(sub.func2()) // NG } package sub func Func1() string { return "Func1" } func func2() string { return "func2" }
  • 17.
    JavaからGoへ  アクセス指定子  Java: private, public  Go : 大文字・小文字 package main import ( "./sub" "fmt" ) func main() { fmt.Println(sub.Func1()) fmt.Println(sub.func2()) // NG } package sub func Func1() string { return "Func1" } func func2() string { return "func2" } 基本、メソッドやメンバは大文字から始めパッ ケージ外に公開したくない場合は小文字ちゃん
  • 18.
    JavaからGoへ  interface  Java: implements  Go : メソッド定義  メソッド定義でどんなオブジェクトでも代入可能 package main func say(yone Yone) { fmt.Println(yone.hello()) } func main() { var mope Mope say(mope) } type Yone interface { hello() string } type Mope struct{} func (_ Mope) hello() string { return "mope" }
  • 19.
    JavaからGoへ  cast  Java: (データ型)式 or ジェネリクス  Go : 型アサーション 式.(データ型) var i interface{} = "hoge” if s, ok := i.(string); ok { fmt.Println("String: ", s) } else { fmt.Println("Not String” , s) }
  • 20.
    JavaからGoへ  cast  Java: (データ型)式 or ジェネリクス  Go : 型アサーション var i interface{} = "hoge” if s, ok := i.(string); ok { fmt.Println("String: ", s) } else { fmt.Println("Not String") } iがstringであればsに変換結果, okにはtrueがセットされる。 そうでなければsにstring初期値, okにはfalseがセットされる。 okを指定せず戻り値をsだけにして型アサーションした場合には型変 換に失敗した場合にはランタイムパニックになる。
  • 21.
    JavaからGoへ  例外  Java: Exception, try-catch  Go : 無し!とにかく if err != nil  常にエラーを返す err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 }
  • 22.
    JavaからGoへ  例外  Java: Exception, try-catch  Go : 無し!とにかく if err != nil  常にエラーを返す err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 }
  • 23.
    JavaからGoへ  例外  Java: Exception, try-catch  Go : 無し!とにかく if err != nil  常にエラーを返す err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } err := func1() if err != nil { // エラー処理 } err = func2() if err != nil { // エラー処理 } err = func3() if err != nil { // エラー処理 } err = func4() if err != nil { // エラー処理 } これがGoだ!これがGoだ!これがGoだ!これがGoだ!これがGo だ!これがGoだ!これがGoだ!これがGoだ!これがGoだ!これが
  • 24.
    JavaからGoへ  戻り値  Java: 単一  Go : 多値  受け取り無視にはブランク識別子 val, err := sum(1, 2) if err != nil { // エラー処理 } val, _, _, err = func2() if err != nil { // エラー処理 }
  • 25.
    JavaからGoへ  戻り値  Java: 単一  Go : 多値  受け取り無視にはブランク識別子 val, err := sum(1, 2) if err != nil { // エラー処理 } val, _, _, err = func2() if err != nil { // エラー処理 } 値の受け取りを無視しても良いが戻り値のerrをブランク識別子で受けて はダメなんだぞぉ〜。Javaのtry-catchで処理を書かないことと同じ!
  • 26.
    JavaからGoへ  資源解放  Java: try-finally  Go : defer func finally() { fmt.Println("finally") } func main() { defer finally() for i := 0; i < 10; i++ { fmt.Println("i:", i) } }
  • 27.
    JavaからGoへ  資源解放  Java: try-finally  Go : defer func finally() { fmt.Println("finally") } func main() { defer finally() for i := 0; i < 10; i++ { fmt.Println("i:", i) } } deferは関数終了時にコールされる。 複数deferを登録すると最後に登録したdeferから実行される。 $ go run main.go i: 0 i: 1 i: 2 i: 3 i: 4 i: 5 i: 6 i: 7 i: 8 i: 9 finally
  • 28.
    JavaからGoへ  初期化子  Java: staticイニシャライザ  Go : init() package sub import ( "fmt" ) func init() { fmt.Println("sub init()") } func Func1() { fmt.Println("Func1") } package main import ( "./sub" "fmt" ) func main() { fmt.Println("SeasarCon2015") sub.Func1() }
  • 29.
    JavaからGoへ  初期化子  Java: staticイニシャライザ  Go : init() package sub import ( "fmt" ) func init() { fmt.Println("sub init()") } func Func1() { fmt.Println("Func1") } 初期化関数はmain関数の定義されたソースから連鎖的にimportされた パッケージのみのため予期せず使用しないソースのinitは実行されない package main import ( "./sub" "fmt" ) func main() { fmt.Println("SeasarCon2015") sub.Func1() }
  • 30.
    JavaからGoへ  配布形式  Java: jar, war  配布には必要ライブラリを含める  Go : 単一の実行可能ファイル  クロスコンパイル GOOS=windows GOARCH=amd64 go build -o seasar.exe GOOS=darwin GOARCH=amd64 go build -o seasar GOOS=linux GOARCH=amd64 go build -o seasar
  • 31.
    JavaからGoへ  配布形式  Java: jar, war  配布には必要ライブラリを含める  Go : 単一の実行可能ファイル  クロスコンパイル 配布がとくかく容易 GOOS=windows GOARCH=amd64 go build -o seasar.exe GOOS=darwin GOARCH=amd64 go build -o seasar GOOS=linux GOARCH=amd64 go build -o seasar
  • 32.
    JavaからGoへ  本番と開発の設定変更  Java: profile(maven, Spring Boot)  Go : tag go build –tags release // +build !release package env const DEBUG = true // +build release package env const DEBUG = false env.go env_release.go if env.DEBUG { log.Println(”debug print") }
  • 33.
    JavaからGoへ  アノテーション  Java: annotasion  Go : tag type Person struct { Id int64 `json:"code"` Name string `json:“name“` Age int `json:“age"` CreatedAt int64 }
  • 34.
    JavaからGoへ  Test  Java: JUnit  Assert  Go : testing  Assertは無い, if文で  ソースファイルと同一パッケージ  calc.go なら calc_test.go func TestSum(t *testing.T) { actual := Sum(1, 2) expected := 3 if actual != expected { t.Errorf(”actual %v expected %v", actual, expected) } }
  • 35.
    JavaからGoへ  コード整形  Java: IDE  Go : gofmt, goimports  公式サポート  コードの統一  golint, go vet でチェック
  • 36.
    JavaからGoへ  依存関係  Java: gradle, maven  Go : godep, gb, vendor  バージョン指定が出来ない  マルチプロジェクトで困る  $GOPATH/src以下にfetch  Go1.5 Vendoring!
  • 37.
    JavaからGoへ  Javaプログラマ向けチートシート  javac->java: go run  classpath : $GOPATH  import : import  public, private : 大文字・小文字  implements : メソッド定義  (データ型)式 : v, ok := 式.(データ型)  例外あり : 例外無し if err != nil  単一を返す : 多値を返せる  try-finally : defer  static{} : init()  jar, war : クロスコンパイル  profile : -tags  @annotation : タグ  JUnit : testing  IDE : gofmt, goimports  gradle, maven : godep, gb, vendor
  • 38.
  • 39.
    Go開発事例  ムーミン APIサーバ Go1.4  goji  godep, fresh  drone slack通知 成果物dropbox  DDLをbranch毎  goconvey カバレッジ  circus  nginx  mysql join禁止  log LTSV, Elasticsearch, kibana  管理画面  @mopeomope
  • 40.
    Go開発事例  最新  Go1.5 goji, gorm, pq  gb, goemon, goconvey  drone slack通知 成果物dropbox  nginx  postgresql  Redis Pub/Sub  websocket
  • 41.
  • 42.
    終わりに  みんなもGoやろう!  プロダクトで使ってみた感想 JavaプログラマにはGoは向いていると思う!  これからもGoを採用していく予定  Go1.5  期待!
  • 43.
  • 44.