ようへいの日々精進XP

よかろうもん

俺の A Tour of Go (2)

A Tour of Go

https://go-tour-jp.appspot.com/ を写経していく.

Variables

// filename: variables.go
package main

import "fmt"

var c, python, java bool

func main() {
    var i int
    fmt.Println(i, c, python, java)
}

以下, 実行結果.

$ ./_run.sh variables.go 
0 false false false

Variables with initializers

  • https://go-tour-jp.appspot.com/basics/9
  • var 宣言では, 変数毎に初期化子 (initializer) を与えることができる
  • 初期化子が与えられている場合は型を省略出来, その変数は初期化子が持つ型となる
// filename: variables-with-initializers.go
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)
}

以下, 実行結果.

$ ./_run.sh variables-with-initializers.go 
1 2 true false no!

あまり関係ないかもしれないけど, 変数にスコープって存在しないのかなと思ったりした.

Short variable declarations

  • https://go-tour-jp.appspot.com/basics/10
  • 関数の中では, var 宣言の代わりに, 短い := の代入文を使って暗黙的な型宣言が出来る
  • 関数外では, キーワードではじまる宣言 (var, func, など) が必要で := での暗黙的な宣言は利用出来ない
// filename: short-variable-declarations.go
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)
}

変数 kvar で宣言されていないが, 代入文として := が利用されている為, 3 が代入されている.

$ ./_run.sh short-variable-declarations.go 
1 2 3 true false no!

Basic types

Go 言語の基本型 (組み込み型) は以下の通り.

bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // uint8 の別名

rune // int32 の別名
     // Unicode のコードポイントを表す

float32 float64

complex64 complex128
  • https://go-tour-jp.appspot.com/basics/11
  • int, uint, uintptr 型は, 32-bit のシステムでは 32 bit で, 64-bit のシステムでは 64 bit を表現する
  • サイズ, 符号なし (unsigned) 整数の型を使うための特別な理由がない限り, 整数の変数が必要な場合は int を使うようにする
// filename: basic-types.go
package main

import (
    "fmt"
    "math/cmplx"
)

var (
    ToBe   bool       = false
    MaxInt uint64     = 1<<64 - 1
    z      complex128 = cmplx.Sqrt(-5 + 12i)
)

func main() {
    fmt.Printf("Type: %T Value: %v\n", ToBe, ToBe)
    fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt)
    fmt.Printf("Type: %T Value: %v\n", z, z)

以下, 実行結果.

$ ./_run.sh basic-types.go 
Type: bool Value: false
Type: uint64 Value: 18446744073709551615
Type: complex128 Value: (2+3i)

%T で変数の型, %v で変数の中身にアクセスすることが出来るようだ.

// filename: basic-types2.go
package main

import (
    "fmt"
)

var (
    Foo    string     = "Foo"
)

func main() {
    fmt.Printf("Type: %T Value: %v\n", Foo, Foo)
}

以下, 実行結果.

$ ./_run.sh basic-types2.go 
Type: string Value: Foo

Zero values

  • https://go-tour-jp.appspot.com/basics/12
  • 変数に初期値を与えずに宣言すると, ゼロ値 (zero value) が与えられる
  • ゼロ値は型によって以下のように与えられる
    • 数値型 (int,float など): 0
    • bool 型: false
    • string 型: "" (空文字列 (empty string))
// filename: zero.go
package main

import "fmt"

func main() {
    var i int
    var f float64
    var b bool
    var s string
    fmt.Printf("%v %v %v %q\n", i, f, b, s)
}

以下, 実行結果.

$ ./_run.sh zero.go 
0 0 false ""

Type conversions

以下, 変換の例.

var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

# よりシンプルに
i := 42
f := float64(i)
u := uint(f)

C 言語とは異なり, Go での型変換は明示的な変換が必要となる.

// filename: type-conversions.go
package main

import (
    "fmt"
    "math"
)

func main() {
    var x, y int = 3, 4
    var f float64 = math.Sqrt(float64(x*x + y*y))
    var z uint = uint(f)
    fmt.Println(x, y, z)
}

以下, 実行結果.

$ ./_run.sh type-conversions.go 
3 4 5

以下, float64 に型変換しなかった場合の実行結果.

$ ./_run.sh type-conversions.go 
# command-line-arguments
/sandbox/type-conversions.go:11:33: cannot use x * x + y * y (type int) as type float64 in argument to math.Sqrt

Type inference

  • https://go-tour-jp.appspot.com/basics/14
  • 明示的な型を指定せずに変数を宣言する場合 (:= や var = のいずれか), 変数の型は右側の変数から型推論される
  • 以下のように, 右側の変数が型を持っている場合, 左側の新しい変数は同じ型になる
var i int
j := i // j の型は int になる

上記を念の為, 確認する.

// filename: type-inference-check1.go
package main

import (
    "fmt"
)

func main() {
  var i int = 100
  j := i
  fmt.Printf("Type: %T Value: %v\n", j, j)
}

実行してみると...

$ ./_run.sh type-inference-check.go 
Type: int Value: 100

右側に型を指定しない数値である場合, 左側の新しい変数は右側の定数の精度に基いて int, float64, complex128 の型となる.

i := 42           // int
f := 3.142        // float64
g := 0.867 + 0.5i // complex128

こちらも念の為に確認.

// filename: type-inference-check2.go
package main

import (
    "fmt"
)

func main() {
  i := 42
  f := 3.142
  g := 0.867 + 0.5i
  fmt.Printf("Type: %T Value: %v\n", i, i)
  fmt.Printf("Type: %T Value: %v\n", f, f)
  fmt.Printf("Type: %T Value: %v\n", g, g)
}

実行してみると...

$ ./_run.sh type-inference-check2.go 
Type: int Value: 42
Type: float64 Value: 3.142
Type: complex128 Value: (0.867+0.5i)

以下, ツアーのコード.

// filename: type-inference.go
package main

import "fmt"

func main() {
    v := 42 // change me!
    fmt.Printf("v is of type %T\n", v)
}

以下, 実行.

$ ./_run.sh type-inference.go 
v is of type int

例えば, v の値を "foo" にした場合には以下のような結果となった.

$ ./_run.sh type-inference.go 
v is of type string

Constants

  • https://go-tour-jp.appspot.com/basics/15
  • 定数 (constant) は, const キーワードを使って変数と同じように宣言可
  • 定数は, 文字 (character), 文字列 (string), boolean, 数値 (numeric) のみで利用可能
  • 定数は := を使って宣言不可
// filename: constants.go
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)
}

以下, 実行結果.

$ ./_run.sh constants.go 
Hello 世界
Happy 3.14 Day
Go rules? true

Numeric Constants

// filename: numeric-constants.go
package main

import "fmt"

const (
    // Create a huge number by shifting a 1 bit left 100 places.
    // In other words, the binary number that is 1 followed by 100 zeroes.
    Big = 1 << 100
    // Shift it right again 99 places, so we end up with 1<<1, or 2.
    Small = Big >> 99
)

func needInt(x int) int { return x*10 + 1 }
func needFloat(x float64) float64 {
    return x * 0.1
}

func main() {
    fmt.Println(needInt(Small))
    fmt.Println(needFloat(Small))
    fmt.Println(needFloat(Big))
}

以下, 実行例.

$ ./_run.sh numeric-constants.go 
21
0.2
1.2676506002282295e+29

コードの needInt(Big) を出力した場合...

$ ./_run.sh numeric-constants.go 
# command-line-arguments
/sandbox/numeric-constants.go:20:21: constant 1267650600228229401496703205376 overflows int

int は 64-bit の整数を保持出来るが, それでは足りないことがある場合に const を活用する.

Go, Go, Go, Go 〜 (郷ひろみ風)

以上, Basics が終了〜でした.