Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Golang入門

uhzz
January 26, 2021

 Golang入門

社内勉強会で使用したGoの入門スライド

uhzz

January 26, 2021
Tweet

More Decks by uhzz

Other Decks in Programming

Transcript

  1. Golang入門
    2019/11/30

    View Slide

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

    View Slide

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

    View Slide

  4. 1.こんにちは、Go

    View Slide

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

    View Slide

  6. Goのいいところ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. 2.Goハンズオン

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. ■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 (変数名) (型名)で初期化します。
    変数の値は初期化するときに代入することもできます。
    型推論で初期化することもできます。

    View Slide

  19. ■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文条件式の前に、代入文を書くことができます。

    View Slide

  20. ■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文はありません。

    View Slide

  21. ■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文は不要です!

    View Slide

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

    View Slide

  23. ■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}とフィールド名を省
    略することもできますし、後から値を変えることもできます!
    (変数名).(フィールド名)で取り出します

    View Slide

  24. ■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から実行されます。)

    View Slide

  25. ■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つのエラーを戻り値にしてい
    ます。※エラーを戻り値にしているのは後述

    View Slide

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

    View Slide

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

    View Slide

  28. ■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を使うなどして閉じ忘れには気をつけましょう!

    View Slide

  29. ■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オブジェクトに変換しています

    View Slide

  30. ■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サーバを構築しています!

    View Slide

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

    View Slide

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

    View Slide

  33. 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 


    View Slide

  34. goroutine

    View Slide

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

    View Slide

  36. package main
    import (
    "fmt"
    "time")
    func saveFile(ch chan bool) {
    time.Sleep(3 * time.Second)
    ch 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

    View Slide

  37. アプリを作ってみよう

    View Slide

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

    View Slide

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

    View Slide

  40. 課題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で起動してから確認してください!
    アプリを作ってみよう

    View Slide

  41. 参考 -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

    View Slide

  42. お疲れ様でした

    View Slide