🐕
A Tour of Goを試す
"A Tour of Go"のBasicsを読んだメモ。
package
Go
はpackage
で構成され、main
パッケージから開始される。
import
facotred import statement
パッケージのインポートをグループ化
import(
"fmt"
"math"
)
// 下記と同じ
import "fmt"
import "math"
exported name
パッケージをインポートすると、エクスポート(公開)している名前(大文字で始まる名前)を参照できる。
エクスポートされていないもの(小文字で始まる名前)は外部のパッケージからアクセス不可。
function
- 変数名の後ろには型名を書く
- 2つ以上の引数が同じ型の場合は最後の型以外を省略できる
x, y int // <--- x int, y int
- 複数の戻り値を返すことが可能
- 戻り値の変数に名前を付けられる
- 名前付き戻り値の変数を使うと
return
文に何も書かなくて良い(naked return)
- 名前付き戻り値の変数を使うと
変数
-
var
で宣言 - まとめて複数宣言可能。型は最後
-
var
はパッケージ、関数で利用
var a, b, c int
- 宣言と同時に初期化子を与える。型を省略できる
var a, b = 1, 2
short variable declaration
関数の中でvar
の代わりに:=
の代入文で暗黙的な型宣言ができる。
関数の外では不可
factored宣言
var (
ToBe bool = false
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)
基本型(組み込み型)
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 の別名
rune // int32 の別名
// Unicode のコードポイントを表す
float32 float64
complex64 complex128
ゼロ値
変数に初期値を与えずに宣言するとゼロ値が設定される。
- 数値型(int,floatなど):
0
- bool型:
false
- string型:
""
(空文字列)
型変換
T(v)
で変数vをT型に変換。
型変換しないとエラーになる。
var o int = 42
var p float64 = o
// ./prog.go:15:6: cannot use o (type int) as type float64 in assignment
型推論
明示的に型を指定せずに変数を宣言した場合(:=
やvar =
)、変数の型は右側の変数の型から型推論される。
定数
-
const
キーワードを使って宣言する - 英数は文字、文字列、数値のみで利用可能
- 定数は
:=
で宣言不可 - 数値の定数は、高精度な値(?)
For文
- 初期化ステートメント、条件式、後処理ステートメント
- セミコロン(;)で区切る。
- () は不要
- 初期化ステートメントと後処理ステートメントは省略可
for i := 0; i < 10; i++ { /* process */ }
- セミコロン(;)は省略可。いわゆる
while
文と同じ
for sum < 100 { /* process */ }
- ループ条件を省略すると無限ループ
for { /* process */ }
if文
() は不要
評価式
- 条件の前に評価式を書くことができる
-
else
ブロックでも宣言されて変数を利用可能
演習(平方根)
こんな感じでいいのかな?
package main
import (
"fmt"
)
func Sqrt(x float64) float64 {
// z := 1.0
z := x
end := z
count := 0
// for i := 1; i <= 10; i++ {
for i := 1; ; i++ {
z -= (z*z - x) / (2*z)
count = i
// if end == z { break }
if f := end - z; f < 0.001 { break }
end = z
}
fmt.Println("count :", count, ", over 10 :", count > 10)
return z
}
func main() {
fmt.Println(Sqrt(2))
}
Switch文
- 合致した
case
のみ実行(break
不要) - 合致したら停止(自動的に
break
する) -
case
で合致させるものは何でもよい(?)
switch value {
case "foo":
// process
default:
// process
}
- 条件なしは
switch true
と書くことと同じ
switch {
case i > 0:
// process
default:
// process
}
defer文
-
defer
へ渡した関数の引数はすぐに評価され、関数自体は呼び出し元の関数が終わる(return
される)まで実行されない - 呼び出しはスタックされ、LIFOの順番で実行される
ポインタ
- ポインタは値のメモリアドレスを指す
- 変数Tのポインタは、
*T
型で、ゼロ値はnil
&
オペレータは、そのオペランドへのポインタを引き出す*
オペレータは、ポインタの指す先の変数を示す
struct(構造体)
-
struct
はフィールドの集まり - structリテラルはフィールドの値を列挙して初期化。フィールド名を明記することも可能。フィールドの一部でも良い。
- フィールドは
ドット(.)
でアクセス。またstruct
のポイント経由でアクセス可能。
type Vertex struct {
X int
Y int
}
v := Vertex{1, 2}
// v2 = Vertex{X: 1, Y: 2}
v.X = 4
// pointer
p := &v
p.X = 1e9
Array(配列)
[n]T型は、型Tのn個の変数の配列を表します。
- 配列は固定長。配列のサイズを変えることはできない
var array [2]string
var array = [2]string{"Hello", "World"}
Slice
型[]Tは型Tのスライスを表します。
- スライスは可変長
- スライスはどんなデータも格納しておらず、単に元の配列の部分列を指し示しています。
- スライスの要素を変更すると、その元となる配列の対応する要素が変更されます。
- 同じ元となる配列を共有している他のスライスは、それらの変更が反映されます。
primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[1:4]
// var s = []int{3, 5, 7}
default
- 既定値を代わりに使用することで上限または下限を省略することができます。
既定値は下限が0で上限はスライスの長さです。
length & capacity
スライスは長さ( length )と容量( capacity )の両方を持っています。
スライスの長さは、それに含まれる要素の数です。
スライスの容量は、スライスの最初の要素から数えて、元となる配列の要素数です。
スライスs
の長さと容量はlen(s)
とcap(s)
という式を使用して得ることができます。
再スライス
スライスの長さを伸ばすことができる
nilスライス
- スライスのゼロ値は
nil
-
nil
スライスは0の長さと容量を持っている
スライスのスライス
スライスは、他のスライスを含む任意の型を含むことができます。
スライスの作成
組み込みのmake
関数でスライスを作成
s := make([]int, 5)
要素の追加
組み込みのappend
関数でスライスへ新しい要素を追加
s = append(s, 2, 3, 4)
range
- for文で反復処理をするために使う
- インデックスと要素のコピーの2つの変数を返す
- インデックスや値は
_
へ代入して捨てることができる
for index, value := range pow {
// process
}
Map
-
map
はキーと値とを関連付ける - ゼロ値は
nil
-
make
関数で作成
v := make(map[int]string)
v[0] = "Foo"
演習(Map)
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
results := map[string]int{}
for _, value := range strings.Fields(s) {
if v, ok := results[value]; ok {
results[value] = v + 1
} else {
results[value] = 1
}
}
return results
}
func main() {
wc.Test(WordCount)
}
関数値(function value)
- 関数は他の関数の引数や戻り値として利用できる
- 関数はクロージャ(closure)
演習(フィボナッチ数)
再帰的関数の実装がわからず。
func fibonacci() func() int {
r := [2]int{0, 1}
i := 0
return func() int {
defer func() { i++ }()
switch {
case i == 0:
return 0
case i == 1:
return 1
default:
v := r[0] + r[1]
r[0] = r[1]
r[1] = v
return v
}
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Discussion