ENTRANCE

都内でエンジニアやってます。主にRubyとJavaを書いて遊んでる人のブログ。楽しくのんびりとがモットー。

【GO】Golangの勉強を始めたから殴り書きのメモ~その1

A tour of Go を基にメモ。 誤字脱字はすみません。 いつか綺麗に書く。多分。 tour.golang.org

  • Goのプログラムは、パッケージ( package )で構成される。
  • mainのmain()が実行される 次の二つは同じ
import "fmt"
import "math/rand"
import (
  "fmt"
  "math/rand"
)
  • 最初の文字が大文字で始まる名前は、外部のパッケージから参照できるエクスポート(公開)された名前( exported name )です。 => 大文字始まりにすれば、外部パッケージから参照できる。

    関数の定義

  • 普通にかく
// func 関数名(引数a aの型, 引数b bの型) int { ... }
func add(x int, y int, z int) int {
    return x + y + z
}
  • 引数の型が同じなら省略できる
// 上のやつと同じ
func add(x, y, z int) int {
    return x + y + z
}
  • 二つ戻り値もてるよ
func swap(x, y string) (string, string) {
    return y, x
}
func main() {
  // 関数の戻り値を代入
  a, b := swap("World", "Hellow")
  println(a, b) // Hellow World
}
  • 戻り値に名前つけられるよ
// xとyが戻り値。これも戻り値の型が同じだと省略できる。
// 短い関数だけで使おう。可読性が落ちるんだってさ。
func super() (x, y string) {
    x = "Java"
    y = "おじさん"
    return // naked return って言うらしい
}
func main() {
  fmt.Println(super()) // Java おじさん
}

変数の定義

  • 普通に宣言
package main
import "fmt"
// パッケージ内で宣言できるよ。
// 変数も同じ型なら省略できるんだって。
var c, python, java bool
func main() {
  // 関数内でも宣言できるよ。
  var i int
  // 宣言だけした場合、intは0, boolはfalseが入るよ。
    fmt.Println(i, c, python, java) // 0 false false false
}
  • 宣言して代入
package main
import "fmt"
// 宣言して代入
var i, j int = 1, 2
func main() {
  // 関数内でも宣言して代入
    var c, python, java = true, false, "no!"
    fmt.Println(i, j, c, python, java) // 1 2 true false no!
}
  • 省略した宣言して代入
package main
import "fmt"
// 関数の外では省略した書き方はできない
func main() {
  // 普通の宣言して代入
  var i, j int = 1, 2
  // 省略した書き方
  k := 3
    c, python, java := true, false, "no!"
    fmt.Println(i, j, k, c, python, java) //1 2 3 true false no!
}
  • 変数のゼロ値 宣言したけど初期値入れないとゼロ値が与えられる。
数値型(int,floatなど): 0
bool型: false
string型: "" (空文字列( empty string ))
  • 型の変換 T(v)・・・vをT型に変換する時
var i int = 42
// int -> float64
var f float64 = float64(i)
// float64 -> unit
var u uint = uint(f)
// 上のやつの省略系
i := 42
f := float64(i)
u := uint(f)

定数の定義

  • 普通に定義
package main
import "fmt"
// 関数外でも定義できるよ
// :=は使えない
const Pi = 3.14
func main() {
  // 関数内でも:=は使えない
    const World = "世界"
    fmt.Println("Hello", World)
    fmt.Println("Happy", Pi, "Day")
    const Truth = true
    fmt.Println("Go rules?", Truth)
}

For文

  • 一般的な形
func main() {
  sum := 0
  // iが10以上になったら終わり
  // iの初期値は0
  // 一周したらiをインクリメント(後処理ステートメント)
    for i := 0; i < 10; i++ {
        sum += i
    }
    fmt.Println(sum) // 45
}
  • 初期化とかなくてもええんやで
func main() {
  sum := 1
  // 初期化と後処理ステートメントはなくてもいい
    for ; sum < 1000; {
        sum += sum
    }
    fmt.Println(sum)
}
// 初期化と後処理ステートメントないならセミコロンもいらん
func main() {
    sum := 1
    for sum < 1000 {
        sum += sum
    }
    fmt.Println(sum)
}

if文

  • 一般的なif
func sqrt(x float64) string {
  // ()はいらない
    if x < 0 {
        return sqrt(-x) + "i"
    }
    return fmt.Sprint(math.Sqrt(x))
}
func main() {
    fmt.Println(sqrt(2), sqrt(-4))
}
func pow(x, n, lim float64) float64 {
  // 変数vを宣言できるよ
  // このifの中でしか変数vは使えないよ
    if v := math.Pow(x, n); v < lim {
        return v
    }
    return lim
}
  • if-else
func pow(x, n, lim float64) float64 {
    if v := math.Pow(x, n); v < lim {
    return v
  // elseも使えるね
    } else {
        fmt.Printf("%g >= %g\n", v, lim)
    }
    // can't use v here, though
    return lim
}

switch文

package main
import (
    "fmt"
    "runtime"
)
func main() {
  fmt.Print("Go runs on ")
  // if文と同じように変数osを定義できる
    switch os := runtime.GOOS; os {
    case "darwin":
    fmt.Println("OS X.")
    // breakはなくても良いのだよ
    case "linux":
        fmt.Println("Linux.")
    default:
        // freebsd, openbsd,
        // plan9, windows...
        fmt.Printf("%s.", os)
    }
}
func main() {
  t := time.Now()
  // こんな書き方もできる。
  // switch true {...} と同じ
    switch {
    case t.Hour() < 12:
        fmt.Println("Good morning!")
    case t.Hour() < 17:
        fmt.Println("Good afternoon.")
    default:
        fmt.Println("Good evening.")
    }
}

Defer(遅延させる)

package main
import "fmt"
func main() {
  // 引数の評価はされるけど、呼び出し元の関数がreturnするまで延期
    defer fmt.Println("world")
  fmt.Println("hello")
}
  // 出力
  // hello
  // world   ★ helloよりも後に実行される
  • 複数のDefer
package main
import "fmt"
func main() {
    fmt.Println("counting")
    for i := 0; i < 10; i++ {
    // たくさんdeferする
    // 先入れ後出し方式
    // 箱の中に順番にモノを入れていって、上から順番に出す感じです
        defer fmt.Println(i)
    }
    fmt.Println("done")
}
/* 出力
counting
done
9
8
7
6
5
4
3
2
1
0*/

続く。。。