Slide 1

Slide 1 text

Golang入門 2019/11/30

Slide 2

Slide 2 text

アジェンダ 0.自己紹介 1.こんにちは、Go(15min) ● Goとは ● Goのいいところ ● プロジェクトでの使われ方 2.Goハンズオン(1h45min) ● きほんの「き」 ● goroutine(ゴルーチン) ● アプリを作ってみよう

Slide 3

Slide 3 text

0.自己紹介 前職:社内ネットワークの運用 /保守 ←半年くらい - GUIツールを使った帯域の制御とか監視とか、、 - 空いた時間にVBAで自動化ツールを作ったりしてました。 今のプロジェクト:車両管理システムの開発  ←もうすぐ半年 - Go/Javaをメインに書いてます。 - GoとJavaはプロジェクトに入ってから始めました! 最近ハマってるもの:チョコ、チョコモナカジャンボ

Slide 4

Slide 4 text

1.こんにちは、Go

Slide 5

Slide 5 text

Goとは - Googleが開発しているプログラミング言語(コンパイラ言語)です - 2009年11月10日に登場してから今月で10年目を迎えます - 設計者のケン・トンプソン、ロブ・パイクはGoだけでなくUTF-8の開発者でもあります。 ( ケン・トンプソンはそのほかにUNIXの開発、C言語の設計も) - Goのコンパイラ、ツールおよびソースコードはすべてフリー   かつオープンソースです。 - マスコットキャラはGopher(ホリネズミ) 引用元:Go(プログラミング言語)

Slide 6

Slide 6 text

Goのいいところ

Slide 7

Slide 7 text

■クロスコンパイル Goのソースコードをビルド(コンパイル)する開発環境のOSとは別のOS向けに 実行ファイルを生成することができます!! たとえば、Mac上で開発したGoのソースコードから、 - Windows用実行ファイル - Linux用実行ファイル を生成して配布することができます(便利)! Goのいいところ

Slide 8

Slide 8 text

■並行処理 Goでは並行処理を「簡単」に書くことができます!! ※ここでの簡単とは、「並行処理に必要なあらゆる処理を Goが隠蔽して行ってくれるので、プログラマは並行処理したい処理に注力できる」の意で あり、並行処理簡単簡単 ♫ということではありません。 Goで並行処理を書くには、 - goroutine(”ゴルーチン”と読みます) - channel(そのまま”チャネル”です) の2つがキーワードになります! ※詳しくはハンズオンで説明します。 Goのいいところ

Slide 9

Slide 9 text

プロジェクトでの使われ方

Slide 10

Slide 10 text

主に、バックエンドのAPIサーバに使用されています。 イメージ図: ドライブ動画送信 APIサーバ Webサーバ APIサーバでは、 ・動画をMP4形式に変換 ・変換したデータをストレージに保存 ・Webサーバに動画の場所を教える といった、デバイスやWebサーバのようなシ ステムから要求されたデータ処理を 得意としています!

Slide 11

Slide 11 text

Goを採用しているオープンソースのプロダクト ■Go ←バージョン1.5からセルフホスティング(Go自身)で開発されている ■Docker ←コンテナの実行環境を提供 ■Kubernetes ←コンテナ化したアプリのオーケストレーションシステム ■Terraform ←インフラストラクチャ定義ツール ■Grafana ←ログデータ可視化ツール ...などなど、インフラのソフトウェア多め!!

Slide 12

Slide 12 text

Go、書きたくなったでしょ?

Slide 13

Slide 13 text

2.Goハンズオン

Slide 14

Slide 14 text

-ハンズオンを進めるにあたって- 対象:    プログラミングの基本構文は一通り勉強したことのある方 (型を扱うプログラム(C/Java)を勉強した経験があれば尚とっつきやすいです!) ※今回Goで初めて型を扱うプログラムを勉強する方、または Goからプログラムを初めて勉強される方で、不明点がありましたら どしどし聞いてください!(私が分からない時は助けてください)

Slide 15

Slide 15 text

-ハンズオンを進めるにあたって- ■ハンズオンで取り扱うサンプルプログラムはGoをPCにインストール しなくても実行することができるようになっています。※一部を除く ■Goは最初の環境構築をする必要なく、「Go Playground」という Web上でGoのプログラムを実験するための環境を用意しています! ※構文の勉強には環境構築いらずで手軽なのでオススメです! ■また、これから説明する構文やパッケージの使い方に関して、 分かりにくいと感じたり、もっと詳しく知りたい!という場合は 「A Tour of Go」というチュートリアル形式で学べるサイトが あるのでそちらも併せてご活用ください。 ※「インストールした Goを動かしたいよ!」という方は、スライドで紹介するプログラムを $GOPATH/srcディレクトリ配下に「 main.go」というファイルを作成して保存し、 保存したディレクトリで、 $ go run main.go を実行してください。

Slide 16

Slide 16 text

きほんの「き」 -構文編-

Slide 17

Slide 17 text

■hello,world きほんの「き」 -構文編- package main import "fmt" func main() { fmt.Println("hello,world") } 「hello,world」と出力されたらOK! 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行)

Slide 18

Slide 18 text

■var きほんの「き」 -構文編- package main import "fmt" func main() { var num int var message string = "hi!" Ver := 1.13 fmt.Println("num:", num) fmt.Println("message:", message) fmt.Println("Go version:", Ver) } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) Goでは変数をvar (変数名) (型名)で初期化します。 変数の値は初期化するときに代入することもできます。 型推論で初期化することもできます。

Slide 19

Slide 19 text

■if/else きほんの「き」 -構文編- package main import "fmt" func main() { if num := 1; num % 2 == 0 { fmt.Println("num is even") } else { fmt.Println("num is odd") } } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) Goのif文は丸括弧()不要です。 また、if文条件式の前に、代入文を書くことができます。

Slide 20

Slide 20 text

■for きほんの「き」 -構文編- package main import "fmt" func main() { for i:=0; i < 5; i++ { fmt.Println("num:", i) } list := []int{1,2,3,4,5} for i, v := range list { fmt.Printf("list[%d] : %d\n", i, v) } } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) 通常のfor文 foreach的なfor文 ※Goにwhile文はありません。

Slide 21

Slide 21 text

■switch/case きほんの「き」 -構文編- package main import "fmt" func main() { var num int switch num { case 0: fmt. Println("num is 0") default: fmt. Println("num is not 0" ) } } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) Goのcase文はマッチするとデフォルトで breakします。 → break文は不要です!

Slide 22

Slide 22 text

■type/struct きほんの「き」 -構文編- package main import "fmt" func main() { type MyInt int var num MyInt = 1 fmt.Println("num:", num) } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) Goでは、type (任意の型名) (型名)とすることで任意の型名を宣 言して使用することができます!

Slide 23

Slide 23 text

■type/struct きほんの「き」 -構文編- package main import "fmt" func main() { type Human struct { Name string Age int } user := Human{Name:"hoge", Age:20} fmt.Println("name:", user.Name) fmt.Println("age:", user.Age) } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) Goにはオブジェクト指向言語における classがありません。。 その代わり、struct(構造体)といった形で変数をひとまとめにして使用する ことができます!(ほぼクラス) 構造体の要素をフィールドと言います。 初期化するときはHuman{“hoge”,20}とフィールド名を省 略することもできますし、後から値を変えることもできます! (変数名).(フィールド名)で取り出します

Slide 24

Slide 24 text

■defer きほんの「き」 -構文編- package main import "fmt" func main() { defer fmt.Println("--- main function end ---" ) defer fmt.Println("file Close") defer fmt.Println("done") fmt.Println("--- main function start ---" ) fmt.Println("file Open") fmt.Println("processing..." ) } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) defer文に渡した処理は呼び出し元の関数が終わる直前まで遅らせることができま す。(例のように関数が終了するタイミングでファイルを閉じる処理などを defer文で 宣言しておくような使い方 ) また、defer文は複数書くことができ、 後入れ先出し(LIFO)で実行されます。 (一番下のdeferから実行されます。)

Slide 25

Slide 25 text

■func きほんの「き」 -構文編- package main import "fmt" func something(s string) (string, error) { result := "something returns " + s return result, nil } func main() { result, err := something("my heart") if err != nil { fmt.Println(err) } fmt.Println(result) } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) Goでは、func 関数名(引数...)(戻り値..){}で関数を宣言することができます。 また特徴として、Goの関数は複数の戻り値を持つことができます!! この例では、文字列を引数にとって、1つの文字列と、1つのエラーを戻り値にしてい ます。※エラーを戻り値にしているのは後述

Slide 26

Slide 26 text

きほんの「き」 -パッケージ編-

Slide 27

Slide 27 text

パッケージとは? きほんの「き」 -パッケージ編- package main import "fmt" パッケージを使用することで、外部で提供されるプログラムを import文で宣言して 呼び出すことができます。 (しれっと最初から登場している fmt.Println(パッケージ名.関数名)は、 外部のfmtパッケージからPrintln関数を呼び出していました) Goではmainパッケージがエントリポイント (プログラムが最初に実行されるパッケ ージ)になっています。 もちろん自作パッケージを作って import文で呼び出すことも可能です!

Slide 28

Slide 28 text

■os きほんの「き」 -パッケージ編- package main import ( "fmt" "os" ) func main() { file, err := os.OpenFile("arop.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) if err != nil { fmt.Println(err) } defer file.Close() fmt.Fprintln(file, "第27回AROP") } 以下のプログラムをご自身の環境で実行してみましょう!※Playgroundで実行できませんのでご注意ください。 osパッケージでは、ファイルやディレクトリを操作することができます! ここではosパッケージのOpenFile関数を使用して、このプログラムのあるディレクトリと同じ 階層に”arop.txt”というファイルがあれば開きます。(無ければ新規作成) 開いたファイルはdeferを使うなどして閉じ忘れには気をつけましょう!

Slide 29

Slide 29 text

■json きほんの「き」 -パッケージ編- package main import ( "encoding/json" "fmt" ) type Message struct{ Text string } func main() { a := Message{Text: "happy golang!"} json, _ := json.Marshal(a) fmt.Println(string(json)) } 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) jsonパッケージでは、Go構造体(struct)をjsonオブジェクトへ変換する ことができます。 また、その逆(jsonオブジェクト → Go構造体)も可能です! ここでは、Message構造体をjsonオブジェクトに変換しています

Slide 30

Slide 30 text

■net/http きほんの「き」 -パッケージ編- package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "very very happy golang") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } 以下のプログラムをご自身の環境で実行してみましょう!※Playgroundで実行できませんのでご注意ください。 net/httpパッケージはサーバ /クライアントの機能を提供します。 この例ではプログラムを実行して、「 http://localhost:8080」にアクセスすると 応答メッセージを返す簡易 APIサーバを構築しています!

Slide 31

Slide 31 text

きほんの「き」 -エラー処理編-

Slide 32

Slide 32 text

■エラー処理と言えば、 きほんの「き」 -エラー処理編- try { something() } catch(Exception e) { error(e) } 1.tryの中で何らかの処理をして、 2.何らかの処理が失敗すればcatchに入って エラー処理 と、このようによく見るtry-catch文ですが、 実はGoには例外処理が存在しません!!!

Slide 33

Slide 33 text

file, err := os.OpenFile("arop.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) if err != nil { fmt.Println(err) } ■if err != nil きほんの「き」 -エラー処理編- Goでエラーを処理するためにはこう書きます。 os.OpenFile()を実行してファイルが開けなかった場合、 err変数に エラー内容が代入されます。 err変数にエラー内容が代入された場合、 err変数はnil(GoのNULL)以 外であるので、if err != nil { エラー処理 }の形でエラーを処理 します。(条件!=はイコールでないことを表しています。) 例外処理がなぜないのか気になる方は、以下の FAQを参考にしてください。 http://golang.jp/go_faq#exceptions 


Slide 34

Slide 34 text

goroutine

Slide 35

Slide 35 text

https://talks.golang.org/2012/waza.slide goroutine ■goroutine/channelについて - goroutineは複数のCPUを使って1つの処理を同時に計算する「並列」ではなく、複数の 処理を同時にさばく「並行」処理で動いています。(下図参照) - 並行処理を実現するためにデータは、メモリを共有するのではなくgoroutine間で channelを使ってデータの受け渡しを行います。 本を取りに行く(goroutine4) 本を燃やす(goroutine3) 本を運ぶ(goroutine2) 本を乗せる(goroutine1)

Slide 36

Slide 36 text

package main import ( "fmt" "time") func saveFile(ch chan bool) { time.Sleep(3 * time.Second) ch <- true} func main() { ch := make(chan bool, 1) go saveFile(ch) for { if len(ch) > 0 { fmt.Println("file saved" ) break } time. Sleep(1 * time.Second) fmt. Println("waiting..." )}} 以下のプログラムをPlaygroundまたはご自身の環境で実行してみましょう!(Playgroundで実行) goroutineを起動するには、go (並行処理する関数名 )と書くだけです! (この例では、saveFile関数を非同期で実行させています。) channelの受信チェック channelを受信するまでmain関数内で別の処理を行うこと ができます!(複数の処理を同時に行う) channelを送信 goroutine

Slide 37

Slide 37 text

アプリを作ってみよう

Slide 38

Slide 38 text

つくるもの:IP管理ツール アプリを作ってみよう WEBサーバ テキストファイル (JSON形式) 概要:IPとホスト名の情報を表示 /更新/削除できるWEBアプリ 次の機能を持ったAPIを実装します。 1.表示:JSON形式のテキストファイルを読み込んだ HTMLファイルを返します。 2.更新:POSTメソッドを使って、IP/ホスト名の情報を更新します。 3.削除:POSTメソッドを使って、IP/ホスト名の情報を削除します。 HTMLファイル

Slide 39

Slide 39 text

アプリを作ってみよう ディレクトリ構成 golang_in_handson ├── main.go ←今回編集するファイル └── static ├── seed.json ←このファイルに管理情報をjson形式で保存 └── index.html ←今回編集しなくて良いファイル ドライブから課題をダウンロードしてください!

Slide 40

Slide 40 text

課題1: http://localhost:8080/にアクセスして、index.htmlを表示させる。 課題2: POSTメソッドを使って、次の情報をテキストファイルに追加する。 - IP: 192.168.0.10 - Host: USER10 - Status: available ※追加できたら、index.htmlを表示して確認しましょう。 課題3: POSTメソッドを使って、STEP2で追加した情報を テキストファイルから削除する。 ※削除できたら、index.htmlを表示して確認しましょう。 ※main.goを編集した後に 、$ go run main.goで起動してから確認してください! アプリを作ってみよう

Slide 41

Slide 41 text

参考 -Goのインストール- 方法1:公式の手順でインストール(英語)(https://golang.org/doc/install) 方法2: - Mac https://qiita.com/Noah0x00/items/63e024f9b5a27276401b - Linux   https://qiita.com/notchi/items/5f76b2f77cff39eca4d8 - Windows https://qiita.com/yoskeoka/items/0dcc62a07bf5eb48dc4b

Slide 42

Slide 42 text

お疲れ様でした