Go言語とはなにか? †
- 概要
- Google
- シンプルな言語仕様
- 高速
- 並行プログラミング
- 環境
- CentOS7 (Vagrant)
- sudo yum install golang
$ pwd
/home/vagrant/golang_lessons
$ sudo yum -y install golang
$ go version
go version go1.6.3 linux/amd64
はじめてのGoプログラム †
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
$ go build hello.go
$ ls
hello hello.go
$ ./hello
hello world
$ go run hello.go
hello world
- 言語の特徴
- 1行コメントは「//」複数行コメントは「/* */」
- 文末に「;」は不要
- インデントはスペースではなくタブ推奨
変数を使ってみよう †
func main() {
var msg string
msg = "hello world"
fmt.Println(msg)
}
- 変数宣言と同時に値代入 ※ 型 (string) は省略可能
func main() {
var msg = "hello world"
fmt.Println(msg)
}
func main() {
msg := "hello world"
fmt.Println(msg)
}
$ go run hello.go
hello world
func main() {
// var a, b int
// a, b = 10, 15
a, b := 10, 15
}
func main() {
var (
c int
d string
)
c = 20
d = "hoge"
}
- 変数名の規則
- 1文字目が小文字: そのパッケージ内からのみアクセス可
- 1文字目が大文字: 他のパッケージからもアクセス可
- 変数、定数、関数についても同じルール
基本データ型を使ってみよう †
- 文字列: string
- "hello"
- 初期値: 空文字 "" ※ nil では無い
package main
import "fmt"
func main() {
a := 10
b := 12.3
c := "hoge"
var d bool
fmt.Printf("a:%d, b:%f, c:%s, d:%t\n", a, b, c, d)
}
$ go run hello.go
a:10, b:12.300000, c:hoge, d:false
定数を使ってみよう †
package main
import "fmt"
func main() {
const name = "taguchi"
name = "fkoji"
fmt.Println(name)
}
$ go run hello.go
# command-line-arguments
./hello.go:7: cannot assign to name
- iota を使った定数宣言 ※ 自動で連番の値を付与
package main
import "fmt"
func main() {
const (
sun = iota // 0
mon // 1
tue // 2
)
fmt.Println(sun, mon, tue)
}
$ go run hello.go
0 1 2
基本的な演算をしてみよう †
- 四則演算: + - * / %
- 文字列: +
- 論理値: AND(&&) OR(||) NOT(!)
func main() {
var x int
x = 10 % 3
fmt.Println(x)
}
$ go run hello.go
1
func main() {
var x int
x += 3 // x = x + 3
fmt.Println(x)
}
$ go run hello.go
3
- インクリメント ※ "x = x++" や "++x" の記法はGoでは使えない
func main() {
var x int
x++
fmt.Println(x)
}
$ go run hello.go
1
func main() {
var s string
s = "hello " + "world"
fmt.Println(s)
}
$ go run hello.go
hello world
func main() {
a := true
b := false
fmt.Println(a && b)
fmt.Println(a || b)
fmt.Println(!a)
}
$ go run hello.go
false
true
false
ポインタを使ってみよう †
package main
import "fmt"
func main() {
a := 5
var pa *int
pa = &a // &a = aのアドレス
// paの領域にあるデータの値 = *pa
fmt.Println(pa)
fmt.Println(*pa)
}
$ go run hello.go
0xc82000a2a0
5
関数を使ってみよう †
func hi() {
fmt.Println("hi!")
}
func main() {
hi()
}
$ go run hello.go
hi!
func hi(name string) {
fmt.Println("hi!" + name)
}
func main() {
hi("yuji")
}
$ go run hello.go
hi!yuji
func hi(name string) string { // 返り値の型を指定
msg := "hi!" + name
return msg
}
func main() {
fmt.Println(hi("yuji"))
}
$ go run hello.go
hi!yuji
- 返り値に変数名 (msg) を指定 ※ return 時に変数名指定が不要
func hi(name string) (msg string) {
msg = "hi!" + name
return
}
func main() {
fmt.Println(hi("yuji"))
}
$ go run hello.go
hi!yuji
- 返り値を2つ指定 ※ Go言語の特徴として返り値を2つ指定することが可能
func swap(a, b int) (int, int) {
return b, a
}
func main() {
fmt.Println(swap(5, 2))
}
func main() {
f := func(a, b int) (int, int) { // 関数名は省略可
return b, a
}
fmt.Println(f(2, 3))
}
$ go run hello.go
3 2
func main() {
func(msg string) {
fmt.Println(msg)
}("yuji")
}
$ go run hello.go
yuji
配列を使ってみよう †
func main() {
var a [5]int // a[0] - a[4]
a[2] = 3
a[4] = 10
fmt.Println(a)
fmt.Println(a[2])
}
$ go run hello.go
[0 0 3 0 10]
3
func main() {
// b := [3]int{1, 3, 5}
b := [...]int{1, 3, 5} // 配列の個数は自明のため省略 (...) 可
fmt.Println(b)
fmt.Println(len(b)) // 配列の要素の個数を取得
}
$ go run hello.go
[1 3 5]
3
スライスを使ってみよう †
- 配列
- 関数に配列を渡す場合には値を丸ごと渡すためメモリ的に非効率
- 配列の要素数は固定になっていて動的に変化させることができない
- スライス
- 配列を便利に使えるようにしたデータ型
- 配列の一部または全部を指し示す参照型のデータ
- Go言語においては配列よりもスライスがよく使われる
func main() {
a := [5]int{2, 10, 8, 15, 4}
s := a[2:4] // [8, 15] ... 配列 a の添字は省略可 [:] [:4] [2:] 等
fmt.Println(a)
fmt.Println(s)
}
$ go run hello.go
[2 10 8 15 4]
[8 15]
- スライスの値を変更 ※ 参照先の配列の値も変更されることに注意
func main() {
a := [5]int{2, 10, 8, 15, 4}
s := a[2:4] // [8, 15]
s[1] = 12
fmt.Println(a)
fmt.Println(s)
}
$ go run hello.go
[2 10 8 12 4]
[8 12]
- len (要素数), cap (スライスの最大容量: スライスの最初の位置から切り出せる最大個数)
func main() {
a := [5]int{2, 10, 8, 15, 4}
s := a[2:4] // [8, 15]
s[1] = 12
fmt.Println(len(s))
fmt.Println(cap(s))
}
$ go run hello.go
2
3
make()、append()、copy()を使おう †
func main() {
s := make([]int, 3) // [0 0 0]
fmt.Println(s)
}
- make を使ってスライスを宣言 (初期値を指定)
func main() {
s := []int{1, 3, 5}
fmt.Println(s)
}
$ go run hello.go
[1 3 5]
func main() {
s := []int{1, 3, 5}
// append
s = append(s, 8, 2, 10)
fmt.Println(s)
}
$ go run hello.go
[1 3 5 8 2 10]
- copy を使ってスライス s をスライス t にコピー ※ copy() の返り値はコピーした要素の数
func main() {
s := []int{1, 3, 5}
// append
s = append(s, 8, 2, 10)
// copy
t := make([]int, len(s))
n := copy(t, s)
fmt.Println(s)
fmt.Println(t)
fmt.Println(n)
}
$ go run hello.go
[1 3 5 8 2 10]
[1 3 5 8 2 10]
6
マップを使ってみよう †
- 添字にキーを使ってキーと値のペアで管理可能なデータ型
- 他の言語では ハッシュ や 連想配列 とも呼ばれている
func main() {
m := make(map[string]int) // key: string型, value: int型
m["yuji"] = 200
m["shimojo"] = 300
fmt.Println(m)
}
$ go run hello.go
map[yuji:200 shimojo:300]
- マップの宣言と key / value の代入を同時に実施
func main() {
m := map[string]int{"yuji":100, "shimojo":200}
fmt.Println(m)
}
$ go run hello.go
map[shimojo:200 yuji:100]
- len (key/valueペアの要素数), delete (ペアの削除)
func main() {
m := map[string]int{"yuji":100, "shimojo":200}
fmt.Println(m)
fmt.Println(len(m))
delete(m, "yuji")
fmt.Println(m)
}
$ go run hello.go
map[yuji:100 shimojo:200]
2
map[shimojo:200]
func main() {
m := map[string]int{"yuji":100, "shimojo":200}
v, ok := m["shimojo"]
fmt.Println(v)
fmt.Println(ok)
}
$ go run hello.go
200
true
ifで条件分岐をしてみよう †
func main() {
score := 83
if score > 80 {
fmt.Println("Great!")
} else if score > 60 {
fmt.Println("Good!")
} else {
fmt.Println("so so...")
}
}
$ go run hello.go
Great!
func main() {
if score := 43; score > 80 {
fmt.Println("Great!")
} else if score > 60 {
fmt.Println("Good!")
} else {
fmt.Println("so so...")
}
// fmt.Println(score)
// score は if 文の中のスコープのため上記は undefined エラーとなる
}
$ go run hello.go
so so...
- if 文 の条件で利用可能な演算子
- 比較演算子: > >= < <= == !=
- 論理演算子: && || !
switchで条件分岐をしてみよう †
func main() {
signal := "blue"
switch signal {
case "red":
fmt.Println("Stop")
case "yellow":
fmt.Println("Caution")
case "green", "blue":
fmt.Println("Go")
default:
fmt.Println("wrong signal")
}
}
$ go run hello.go
Go
func main() {
score := 82
switch {
case score > 80:
fmt.Println("Great!")
default:
fmt.Println("so so ...")
}
}
$ go run hello.go
Great!
forでループ処理をしてみよう †
- Go言語では繰り返し処理は for 文のみ (while 文は存在しない)
func main() {
for i := 0; i < 10; i++ {
// if i == 3 { break } // 0, 1, 2
if i == 3 { continue } // 0, 1, 4, 5, 6, 7, 8, 9
fmt.Println(i)
}
}
$ go run hello.go
0
1
2
4
5
6
7
8
9
func main() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
$ go run hello.go
0
1
2
3
4
5
6
7
8
9
- 条件を省略 ※ 無限ループとなるため break 必須
func main() {
i := 0
for {
fmt.Println(i)
i++
if i == 3 { break }
}
}
$ go run hello.go
0
1
2