Skip to content

Instantly share code, notes, and snippets.

@Iwark
Created November 24, 2015 14:29
Show Gist options
  • Save Iwark/d1007db93e4608bdf4d2 to your computer and use it in GitHub Desktop.
Save Iwark/d1007db93e4608bdf4d2 to your computer and use it in GitHub Desktop.
Go言語勉強会の資料

Go言語勉強会@Donuts

Presented by いわーく, 上田哲広

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」等でググる。

Hello World

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

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

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

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

実行

$ go run hello.go

変数宣言

var n int = 1 // int型の変数n
n = 2
n += 1
n := 1 // 型推論(1を代入しているのでint型であると推論される)
n *= 3

数値型

型名 説明
uint8, uint16, uint32, uint64 符号なし整数(8-64bit)
byte uint8のalias(別名)
int8, int16, int32, int64 符号あり整数(8-64bit)
rune int32のalias(別名)。Unicode文字の1文字を格納する型。Go言語では文字のことをルーンと呼ぶ
float32, float64 浮動小数点数(32, 64bit)
complex64, complex128 複素数。実数部、虚数部それぞれが32bitまたは64bit
uint 符号なし整数。システム環境により32bitまたは64bit
int 符号あり整数。システム環境により32bitまたは64bit
uintptr ポインタの値を格納するための符号なし整数。サイズはシステム環境による

文字列型

文字列を格納するのにはstring型を使う。

package main

import (
  "fmt"
  "unicode/utf8"
)

func main() {
  var str string = "Donuts"

  // 「+」演算子で結合可能
  str = "株式会社" + str

  // 文字数を出力
  fmt.Println(str, "lenth:", utf8.RuneCountInString(str))
}

数値の変換

Go言語は型のチェックが厳しく、整数型同士でも型が違えば代入や比較ができない。 例) int32とint64

var i int = 1234
var u uint32 = uint32(i)
var f float32 = float32(u)

関数

func add(a int, b int) int{
  return a + b
}

sum := add(10, 20) // => 30
func calc(a int, b int) (int, int, int, float32){
  return(
    a + b,
    a - b,
    a * b,
    float32(a) / b
  )
}

sum, sub, mul, div := calc(1, 2) // => 3, -1, 2, 0.5

配列

配列型の書式は以下の通り。

[長さ]要素型
// 配列の宣言
var array1 [8]int64
var array2 [1]byte

// 初期化(不足分はゼロ値で初期化)
array3 := [6]int{1, 2, 3, 4}

// 配列の長さ
len(array1)

制御文

if文やfor文は他の言語でよくあるものと同様。丸カッコ「()」は要らない。
「range」式を使用すると配列などの値から要素を1つずつ取り出してループできる。

if 条件式 {
  // 条件式がtrueとなるとき実行されるブロック
} else {
  // falseとなるとき実行されるブロック
}

for i := 0; i < 5; i++ {
  // 5回繰り返されるブロック
}

for 変数 := range 配列等 {
  // 配列の要素の数だけ繰り返される
}

構造体

type Person struct {
  Height float32
  Weight float32    
}

FizzBuzzを実装してみよう

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

使うパッケージ:

  • fmtパッケージ

httpコマンド

以下のURLへHTTPでアクセスして、その結果を表示する

https://gist.githubusercontent.com/Iwark/8a294789add68b9a61fa/raw/f720b43e12539d03e2550e680b54baf8825f2db1/golang20151124.md

使うパッケージ:

  • fmt
  • net/http
  • io/ioutil

lsコマンド

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

使うパッケージ:

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

grepコマンド

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

使うパッケージ:

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

jsonコマンド

以下のJSON形式のテキストをデコードして、内部の値を表示する

https://gist.githubusercontent.com/Iwark/ba6f1f73a059f7f7f675/raw/39bde97ad72096bdf23ccb027b915c5e8c71966b/golang20151124json.json

使うパッケージ:

  • fmt
  • net/http
  • io/ioutil
  • encoding/json

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)
    }
  }
}

httpコマンドのこたえ

package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

func main() {
  url := "https://gist.githubusercontent.com/Iwark/8a294789add68b9a61fa/raw/f720b43e12539d03e2550e680b54baf8825f2db1/golang20151124.md"
  res, err := http.Get(url)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()
  if res.StatusCode != 200 {
    fmt.Println(res.StatusCode)
    return
  }
  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }
  fmt.Println(string(body))
}

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)
    }
  }  
}

jsonコマンドのこたえ

package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
  "encoding/json"
)

func main() {
  url := "https://gist.githubusercontent.com/Iwark/ba6f1f73a059f7f7f675/raw/39bde97ad72096bdf23ccb027b915c5e8c71966b/golang20151124json.json"
  res, err := http.Get(url)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()
  if res.StatusCode != 200 {
    fmt.Println(res.StatusCode)
    return
  }
  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }

  var data []struct {
    Todo string
    At string
  }
  json.Unmarshal(body, &data)

  for _, item := range data {
    fmt.Println(item.Todo + "を" + item.At + "にやる")
  }
}

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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment