ようへいの日々精進XP

よかろうもん

俺の A Tour of Go (1)

A Tour of Go

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

成果は...

github.com

こちらに.

Packages

  • https://go-tour-jp.appspot.com/basics/1
  • Go は package で構成されている
  • プログラムは main パッケージから開始される
  • 以下のプログラムでは "fmt""math/rand" パッケージをインポート( import )している
  • 規約では, パッケージ名はインポートパスの最後の要素と同じ名前になる
  • 例えば, インポートパスが "math/rand" のパッケージは, package rand ステートメントで始まるファイル群で構成する
// filename: codes/packages.go
package main

import (
    "fmt"
    "math/rand"
)

func main() {
    fmt.Println("My favorite number is", rand.Intn(10))
}

もし, import パスが "golang.org/x/net/websocket" のような URL が含まれる場合には, package websocket となる.

# コードの実行結果
$ ./_run.sh packages.go 
My favorite number is 1

Imports

// filename: codes/imports.go
package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Printf("Now you have %g problems.", math.Sqrt(7))
}

factored (要素化, グループ化, 整理済み) インポートステートメントの方がより良いスタイルである.

# コードの実行結果
$ ./_run.sh imports.go 
Now you have 2.6457513110645907 problems.

Exported names

  • https://go-tour-jp.appspot.com/basics/3
  • 最初の文字が大文字で始まる名前は, 外部パッケージから参照できるエクスポート(公開)された名前 ( exported name )
  • 小文字ではじまる pi 等はエクスポートされていない名前
  • パッケージをインポートすると, そのパッケージがエクスポートしている名前を参照することができる
  • エクスポートされていない名前(小文字ではじまる名前)は, 外部のパッケージからアクセスすることはできない
// filename: codes/exported-names.go
package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Println(math.pi)
}

pi という名前ではエクポートされていないので, 実行するとエラーとなる.

$ ./_run.sh exported-names.go 
# command-line-arguments
/sandbox/exported-names.go:10:14: cannot refer to unexported name math.pi
/sandbox/exported-names.go:10:14: undefined: math.pi

以下のように修正する.

// filename: codes/exported-names.go
package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Println(math.Pi)
}

改めて実行すると...

$ ./_run.sh exported-names.go 
3.141592653589793

Functions

  • https://go-tour-jp.appspot.com/basics/4
  • 関数は, 0 個以上の引数を取ることができる
  • 以下のコードにおいて, add 関数は int 型の 2 つのパラメータを取る
  • 変数名の後ろに型名を書く
// filename: codes/functions.go
package main

import "fmt"

func add(x int, y int) int {
    return x + y
}

func main() {
    fmt.Println(add(42, 13))
}

実行.

$ ./_run.sh functions.go 
55

Functions continued

// filename: codes/function-continued.go
package main

import "fmt"

func add(x, y int) int {
    return x + y
}

func main() {
    fmt.Println(add(42, 13))
}

実行.

$ ./_run.sh function-continued.go 
55

Multiple results

// filename: codes/multiple-results.go
package main

import "fmt"

func swap(x, y string) (string, string) {
    return y, x
}

func main() {
    a, b := swap("hello", "world")
    fmt.Println(a, b)
}

実行.

s$ ./_run.sh multiple-results.go 
world hello

Named return values

  • https://go-tour-jp.appspot.com/basics/7
  • 戻り値となる変数に名前をつける( named return value )ことが出来る
  • 戻り値に名前をつけると, 関数の最初で定義した変数名として扱われる
  • 戻り値の名前は, 戻り値の意味を示す名前とすることで, 関数のドキュメントとして表現するようにする
  • 名前をつけた戻り値の変数を使うと, return ステートメントに何も書かずに戻すことが出来る (これを "naked" return と呼ぶ)
// filename: codes/named-results.go
package main

import "fmt"

func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return
}

func main() {
    fmt.Println(split(17))
}

"naked" return ステートメントは, 短い関数でのみ利用すべき. 長い関数で使うと読みやすさ( readability )に悪影響がある.

$ ./_run.sh named-results.go 
7 10

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

以上, Go, Go, Go, Go 〜でした.