hazuuuun
5/18/2016 - 8:47 AM

Go言語勉強会20160210資料

Go言語勉強会20160210資料

Go言語勉強会@Donuts

Presented by いわーく, 上田哲広

はじめに

Go言語で作ったチャットルームを公開しています。

githubでログインして使ってください。

http://52.193.149.39/index

ソースも公開しています。

https://github.com/Iwark/donuts-tech-calendar

資料はこちら

http://bit.ly/1O2zUl8

Go言語について

  • Googleが2009年に公開した比較的新しい言語
  • シンプルで読みやすいことを重視して作られた

Go言語の特徴

  • 静的型付け、静的コンパイル
  • コンパイル、実行速度が速い(ネイティブコンパイル)
  • 標準ツールが充実(go get, go fmt, go test...)
  • オープンソース
  • ガベージコレクションによるメモリ管理
  • 並列処理が得意
  • ダックタイピングができる
  • クロスコンパイル

Go言語を使っている会社

  • Google, Youtube
  • Docker
  • Dropbox
  • Facebook
  • GitHub
  • Twitter
  • Donuts

パスの設定

ホームディレクトリ以下のgocodeディレクトリを 作業ディレクトリとする場合、下記のようになる。

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

bash_profileやzshrc等に書いておくと、 起動時に読み込まれるため、毎回打つ必要がなくなる。

Windowsの人は 「windows 環境変数 path」等でググる。

各種URL

・公式サイト

https://golang.org/

・プレイグラウンド

https://play.golang.org/

Hello World

$HOME/gocode/src/hello/hello.go

package main // 実行されるパッケージ

import "fmt"  // fmtパッケージを使用する

func main() { // エントリーポイント
    fmt.Println("hello, world")
}

実行

$ go run hello.go

A tour og Go

A tour of Goで、Go言語の基本を習得しよう。

https://go-tour-jp.appspot.com/welcome/1

FizzBuzzを実装してみよう

1から100までの数値について、順番に数値を出力する。
ただし、3の倍数の場合は数値ではなく「Fizz」、5の倍数は「Buzz」、15の倍数は「Fizz Buzz」と出力する。

使うパッケージ:

  • fmtパッケージ

インターフェース

type Animal interface{
  Cry()
}

type Dog struct {
}
func (d Dog) Cry() {
  fmt.Println("bow bow")
}
type Cat struct {
}
func (c Cat) Cry() {
  fmt.Println("myaw myaw")
}

func main() {
  var a Animal
  a = &Dog{}
  a.Cry()
  a = &Cat{}
  a.Cry()
}

(ダックタイピングができる)

lsコマンド

カレントディレクトリにあるファイルの一覧を出力する。
余力がある人は、コマンド引数でディレクトリを指定できるようにする。

https://golang.org/pkg/

使うパッケージ:

  • fmt
  • ディレクトリの読み込み => "io/ioutil"パッケージのReadDir
  • コマンド引数 => "os"パッケージのArgs

grepコマンド

テキストファイルを読み込んで コマンド引数で指定された文字列を含む行だけを出力。 余力がある人は、正規表現にも対応する。

使うパッケージ:

  • fmt
  • コマンド引数, ファイルの読み込み => os
  • 行ごとのファイルの読み込み(Scanner) => bufio
  • 文字列の検索 => strings
  • 正規表現 => regexp

server

ローカルでHello Worldを表示するサーバー。

使うパッケージ:

  • net/http

おまけ(HTMLのパース)

HTMLファイルを解析してaタグのリンク先(href)のみを出力する

使うパッケージ:

  • go.net/html
http://www.donuts.ne.jp/

FizzBuzzのこたえ

package main

import (
  "fmt"
)

func main() {

  for i:= 1; i <= 100; i++ {
    if i % 3 == 0 && i % 5 == 0 {
      fmt.Println("FizzBuzz")
    } else if i % 3 == 0 {
      fmt.Println("Fizz")
    } else if i % 5 == 0 {
      fmt.Println("Buzz")
    } else {
      fmt.Println(i)
    }
  }
}

lsコマンドのこたえ

package main

import (
  "fmt"
  "io/ioutil"
)

func main() {
    files, err := ioutil.ReadDir("./")
    if err != nil {
        fmt.Println(err)
    } else {
        for _, f := range files {
            // ディレクトリは末尾に「/」をつける
            if f.IsDir() {
                fmt.Println(f.Name() + "/")
            } else {
                fmt.Println(f.Name())
            }
        }
    }
}

grepコマンドのこたえ

package main

import (
  "bufio"
  "fmt"
  "os"
  "regexp"
)

func main() {

  filePath := os.Args[1]
  grepString := os.Args[2]

  regex := regexp.MustCompile(grepString)

  file, err := os.Open(filePath)
  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }

  defer file.Close()

  scanner := bufio.NewScanner(file)

  for scanner.Scan() {
    text := scanner.Text()
    if regex.Match([]byte(text)) {
      fmt.Println(text)
    }
  }  
}

serverのこたえ

package main

import (
  "net/http"
)

func HelloServer(w http.resWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Hello, World"))
}

func main() {
  http.HandleFunc("/", HelloServer)
  http.ListenAndServe(":8080", nil)
}

HTMLのパースこたえ

package main

import (
  "fmt"
  "net/http"
  "golang.org/x/net/html"
  "io/ioutil"
  "strings"
)

func main() {

  url := "https://candypot.jp/summaries/1050"
  res, err := http.Get(url);
  if err != nil {
    fmt.Println(err)
    return
  }
  if res.StatusCode != 200 {
    fmt.Println(res.StatusCode)
    return
  }

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }

  doc, err := html.Parse(strings.NewReader(string(body)))
  if err != nil {
    fmt.Println(err)
    return
  }
  var f func(*html.Node)
  f = func(n *html.Node) {
    if n.Type == html.ElementNode && n.Data == "a" {
      // n.Attrで属性を一覧する
      for _, a := range n.Attr {
        if a.Key == "href" {
          fmt.Println(a.Val)
        }
      }
    }
    for c := n.FirstChild; c != nil; c = c.NextSibling {
      f(c)
    }
  }
  f(doc)
}