「恥ずかしいGo言語」ハンズオン

· 437 words · 3 minute read

『恥ずかしい勉強会』とは

「今さら聞くのも恥ずかしいし勉強し始めるにも何から始めればいいか分からない人々が寄り添って1ミリだけ前進する」というコンセプトの勉強会です。 ノーマサカリ!「ググレカス」禁止!

建物にはたどり着いたけど、建物内で迷子になりました(恥ずかしい…)


お品書き

  • Go言語とは
  • Go言語のインストール
  • Hello, 世界!
  • 自作パッケージの開発・置き方 // ここをバッチリ聞きたい
  • GitHubを使った自作パッケージの公開
  • (時間が余りまくったら)自作HTTPサーバを書く

資料

https://gist.github.com/otiai10/c2a1cfefdfb7f5798865a30d12ade4c1


学んだこと

Go言語のインストール

わたしはGoのバージョン管理ツールgvmを利用しているので、以下のコマンドでインストールする。

$ gvm install go1.8

$ gvm use go1.8 --default

GOPATHの設定が重要。$GOPATH/src以下にすべてのパッケージが格納されるため。go getコマンドでパッケージを取得することができる。 GOROOTについては、現在では設定する必要はない。

gvmを使わない場合は、以下のを参考にシェルの設定に書いておくとよい。

export GOPATH=$HOME/go
export PATH="$GOPATH/bin:$PATH"

go envコマンドでgoの環境変数を確認する。下記のようになっているはず。

$ go env

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/mom0tomo/.gvm/pkgsets/go1.8/global"
GORACE=""
GOROOT="/Users/mom0tomo/.gvm/gos/go1.8"
GOTOOLDIR="/Users/mom0tomo/.gvm/gos/go1.8/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/kh/6_bmx1pn6rggyfv6c3l2r6ch0000gp/T/go-build863603804=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

Hello, 世界!

※GoではHello, WorldではなくHello, 世界! GoはUnicodeに対応しているため、漢字も使える。Hello, عالمとかも行ける。

package main // Goを実行するにはmainパッケージが必須

import "fmt" // 標準パッケージのfmt(フォーマットするやつ)をインポートする

func main() { // main関数も必須
    fmt.Println("Hello, 世界!")
}

実行する。

$ go run main.go

  Hello, 世界!

Goの基本的な書き方

main.go

package main 

import (// 複数パッケージをインポートするときは()でくくる
    "fmt" // Goの標準・準標準パッケージは上にまとめて書く
    "net/http"

    "github.com/mom0tomo/fizzbuzz" // OSSのパッケージは下にまとめて書く
)

func main() {
    fmt.Println("hogehoge") 
    // インポートしたのに使っていないパッケージがあるとコンパイル時に怒られる
}

GoでFizzBuzz

Goにはwhile文がない。for文はある。 if文はネストが深くなりがちなので、switch文を使うことが多い。

package main

import "fmt"


func GetOutput(i int) string {

    fizz := i % 3        // :=は代入変数。そして関数宣言と型宣言の役割をしてる
    buzz := i % 5

    switch {
        case fizz == 0 && buzz == 0: // case文に式を書ける!
            return "FizzBuzz" // breakしなくても自動でbreakしてくれる
        case fizz == 0:
            return "Fizz"
        case buzz == 0:
            return "Buzz"
        default:
            return fmt.Sprintf("%v", i) 
            // はじめに「S」をつけることで出力ではなくフォーマットした結果を文字列で返す。変数に代入する際などはこちらを使う
    }
}

func main() {

    for i := 0; i < 20; i++ {
        output := GetOutput(i)
        fmt.Println(output)
    }
}

go run してみる。

$ go run main.go

FizzBuzz
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
FizzBuzz
16
17
fizz
19

自作パッケージをつくる

mainパッケージに全て書いてしまっていたので、GetOutputメソッドを切り出してfizzbuzzパッケージとする。

$GOPATH/src配下にパッケージつくることで、標準パッケージのようにインポートして使うことができる。

$ cd $GOPATH/src
$ mkdir fizzbuzz
$ touch fizzbuzz/fizzbuzz.go

$ ls -la
drwxr-xr-x   3 mom0tomo  staff   102  6  8 21:08 fizzbuzz
drwxr-xr-x  21 mom0tomo  staff   714  6  8 20:27 github.com
drwxr-xr-x   3 mom0tomo  staff   102  4  3 20:54 golang.org

$GOAPTH/src/fizzbuzz.go

package fizzbuzz

import "fmt"

func GetOutput(i int) string {

    fizz := i % 3
    buzz := i % 5

    switch {
        case fizz == 0 && buzz == 0:
            return "FizzBuzz"
        case fizz == 0:
            return "Fizz"
        case buzz == 0:
            return "Buzz"
        default:
            return fmt.Sprintf("%v", i)
    }
}

main.go

package main

import (
    "fmt"
    "fizzbuzz" // 標準パッケージのようにインポートできる
)

func main() {

    for i := 0; i < 20; i++ {
        output := fizzbuzz.GetOutput(i)
        fmt.Println(output)
    }
}

GitHubを使った自作パッケージの公開

githubに公開してみる。

標準パッケージのような形式でインポートして開発してきたが、ここでgithubに公開したパッケージを使うことにする。

import部分の記述を以下のように変更する。

package main

import (
    "fmt"

    "github.com/{user name}/fizzbuzz" // githubに置いたパッケージを利用する
)

func main() {

    for i := 0; i < 20; i++ {
        output := fizzbuzz.GetOutput(i)
        fmt.Println(output)
    }
}

この状態で実行すると、以下のようなエラーが出る。 cannot find package "github.com/{user name}/fizzbuzz"

これは$GOPATH/src配下にインポートしようとしているパッケージがない、というエラー。

エラーを解消するために、go getというコマンドでパッケージを取得する。

$ go get gihub.com/{user name}/fizzbuzz

ここでgo runして、パッケージを分割する前と同じ結果になることを確認する。

$ go run main.go

FizzBuzz
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
FizzBuzz
16
17
fizz
19

OK!


いろいろ試してみる

パッケージの名前と関数の名前を変えてみる

fizzbuzz.go

package test // fizzbuzzじゃないのにしてみる

...

-> 動く!

main.goの名前を変えてみる

-> mom0tomo.goとかでにしても動く!