share facebook facebook twitter menu hatena pocket slack

2018.09.18 TUE

俺の A Tour of Go (2)

川原 洋平

WRITTEN BY 川原 洋平

A Tour of Go

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

Variables

  • https://go-tour-jp.appspot.com/basics/8
  • var ステートメントは変数 (variable) を宣言する
  • 関数の引数リストと同様に, 複数の変数の最後に型を書くことで変数のリストを宣言することが出来る
  • var ステートメントはパッケージ、または、関数で利用出来る
// 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 が終了〜でした.

元記事はこちら

俺の A Tour of Go (2)

cloudpack

cloudpackは、Amazon EC2やAmazon S3をはじめとするAWSの各種プロダクトを利用する際の、導入・設計から運用保守を含んだフルマネージドのサービスを提供し、バックアップや24時間365日の監視/障害対応、技術的な問い合わせに対するサポートなどを行っております。
AWS上のインフラ構築およびAWSを活用したシステム開発など、案件のご相談はcloudpack.jpよりご連絡ください。