Go言語入門
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
** Go言語とはなにか? [#z4caea8f]
- 概要
-- Google
-- シンプルな言語仕様
-- 高速
-- 並行プログラミング
- 公式サイト
-- https://golang.org/
- 前提知識
-- Unixコマンド
-- C言語
- 環境
-- CentOS7 (Vagrant)
-- sudo yum install golang
- Goインストール
$ pwd
/home/vagrant/golang_lessons
$ sudo yum -y install golang
$ go version
go version go1.6.3 linux/amd64
** はじめてのGoプログラム [#u15e3fc8]
- hello.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行コメントは「//」複数行コメントは「/* */」
-- 文末に「;」は不要
-- インデントはスペースではなくタブ推奨
** 変数を使ってみよう [#ld66c6f8]
- 基本形
func main() {
var msg string
msg = "hello world"
fmt.Println(msg)
}
- 変数宣言と同時に値代入 &color(red){※}; 型 (string) は省...
func main() {
var msg = "hello world"
fmt.Println(msg)
}
- 変数宣言と同時に値代入 &color(red){※}; := を利用した記法
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文字目が大文字: 他のパッケージからもアクセス可
-- 変数、定数、関数についても同じルール
** 基本データ型を使ってみよう [#nfef6c70]
- 文字列: string
-- "hello"
-- 初期値: 空文字 &color(red){※}; nil では無い
- 整数: int
-- 53
-- 初期値: 0
- 浮動小数: float64
-- 10.2
- 真偽値: bool
-- false / true
-- 初期値: false
- nil
- printf の使い方
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
** 定数を使ってみよう [#v40588d3]
- const で宣言
- 値の変更不可
- hello.go
package main
import "fmt"
func main() {
const name = "yuji"
name = "shimojo"
fmt.Println(name)
}
- 実行結果
$ go run hello.go
# command-line-arguments
./hello.go:7: cannot assign to name
- iota を使った定数宣言 &color(red){※}; 自動で連番の値を...
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
** 基本的な演算をしてみよう [#v6694ecc]
- 四則演算: + - * / %
- 文字列: +
- 論理値: AND(&&) OR(||) NOT(!)
- 余りの計算
func main() {
var x int
x = 10 % 3
fmt.Println(x)
}
- 実行結果
$ go run hello.go
1
- x = x + 3 の代入
func main() {
var x int
x += 3 // x = x + 3
fmt.Println(x)
}
- 実行結果
$ go run hello.go
3
- インクリメント &color(red){※}; "x = x++" や "++x" の記...
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
** ポインタを使ってみよう [#ie5aa5f1]
- ポインタ
-- メモリ上のアドレスを指し示す変数
-- 演算はできない
- hello.go
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
** 関数を使ってみよう [#r985b6fc]
- 基本形 (引数なし)
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) を指定 &color(red){※}; return 時に...
func hi(name string) (msg string) {
msg = "hi!" + name
return
}
func main() {
fmt.Println(hi("yuji"))
}
- 実行結果
$ go run hello.go
hi!yuji
- 返り値を2つ指定 &color(red){※}; Go言語の特徴として返り...
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
** 配列を使ってみよう [#u958a099]
- 基本形
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
** スライスを使ってみよう [#e8115998]
- 配列
-- 関数に配列を渡す場合には値を丸ごと渡すためメモリ的に非...
-- 配列の要素数は固定になっていて動的に変化させることがで...
- スライス
-- 配列を便利に使えるようにしたデータ型
-- 配列の一部または全部を指し示す参照型のデータ
-- Go言語においては配列よりもスライスがよく使われる
- 配列の一部をスライスで参照
func main() {
a := [5]int{2, 10, 8, 15, 4}
s := a[2:4] // [8, 15] ... 配列 a の添字は省略可 [:]...
fmt.Println(a)
fmt.Println(s)
}
- 実行結果
$ go run hello.go
[2 10 8 15 4]
[8 15]
- スライスの値を変更 &color(red){※}; 参照先の配列の値も変...
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()を使おう [#w048b810]
- make を使ってスライスを宣言 (初期値は0)
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]
- append を使ってスライスの末尾に要素を追加
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 にコピー &color(re...
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
** マップを使ってみよう [#u24de239]
- 添字にキーを使ってキーと値のペアで管理可能なデータ型
- 他の言語では ハッシュ や 連想配列 とも呼ばれている
- 基本形
func main() {
m := make(map[string]int) // key: string型, value: i...
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で条件分岐をしてみよう [#jf0f6a42]
- 基本形
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!
- if 文の中で変数を定義
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 文の中のスコープのため上記は undefine...
}
- 実行結果
$ go run hello.go
so so...
- if 文 の条件で利用可能な演算子
-- 比較演算子: > >= < <= == !=
-- 論理演算子: && || !
** switchで条件分岐をしてみよう [#ke0f0c15]
- 基本形
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
- if else 文を switch 文で置き換え
func main() {
score := 82
switch {
case score > 80:
fmt.Println("Great!")
default:
fmt.Println("so so ...")
}
}
- 実行結果
$ go run hello.go
Great!
** forでループ処理をしてみよう [#n543ff36]
- 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
- while 文風な記法
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
- 条件を省略 &color(red){※}; 無限ループとなるため break ...
func main() {
i := 0
for {
fmt.Println(i)
i++
if i == 3 { break }
}
}
- 実行結果
$ go run hello.go
0
1
2
** rangeを使ってみよう [#jb8bbb93]
- 配列 / スライスやマップに対して要素分だけ何らかの処理を...
- スライスの値を一つずつ取得して要素番号 (index) と値 (va...
func main() {
s := []int{2, 3, 8}
for i, v := range s {
fmt.Println(i, v)
}
}
- 実行結果
$ go run hello.go
0 2
1 3
2 8
- 要素番号 (index) の代わりにブランク修飾子を使って値 (va...
func main() {
s := []int{2, 3, 8}
for _, v := range s {
fmt.Println(v)
}
}
- 実行結果
$ go run hello.go
2
3
8
- マップに対しての繰り返し処理
func main() {
m := map[string]int{"yuji":200, "shimojo":300}
for k, v := range m {
fmt.Println(k, v)
}
}
- 実行結果
$ go run hello.go
yuji 200
shimojo 300
** 構造体を使ってみよう [#u2b6cbbe]
- 複数の値を意味のあるまとまりとして新しい型を定義するこ...
- フィールド: 構造体内で定義する各変数
- user 型の構造体定義 &color(red){※}; 構造体 u の返り値は...
type user struct {
name string
score int
}
func main() {
u := new(user)
fmt.Println(u)
}
- 実行結果
$ go run hello.go
&{ 0}
- フィールドに値を代入
type user struct {
name string
score int
}
func main() {
u := new(user)
// (*u).name = "yuji"
u.name = "yuji"
u.score = 20
fmt.Println(u)
}
- 実行結果
$ go run hello.go
&{yuji 20}
- 構造体の初期化時に値を代入 &color(red){※}; 返り値はポイ...
type user struct {
name string
score int
}
func main() {
// u := user{"yuji", 50}
u := user{name:"yuji", score:50}
fmt.Println(u)
}
- 実行結果
$ go run hello.go
{yuji 50}
** メソッドを使ってみよう [#l11b9595]
- Go言語ではオブジェクト指向言語で提供されるクラスやメソ...
- Go言語のメソッドは構造体などのデータ型に紐付いた関数
- 関数をデータ型と紐づけるためにレシーバーと呼ばれるもの...
- メソッド (値渡し) &color(red){※}; メソッドの引数として...
type user struct {
name string
score int
}
func (u user) show() {
fmt.Printf("name:%s, score:%d\n", u.name, u.score)
}
func main() {
u := user{name:"yuji", score:50}
u.show()
}
- 実行結果
$ go run hello.go
name:yuji, score:50
- メソッド (参照渡し) &color(red){※}; 値渡しの場合だと u....
type user struct {
name string
score int
}
func (u user) show() {
fmt.Printf("name:%s, score:%d\n", u.name, u.score)
}
func (u *user) hit() {
u.score++
}
func main() {
u := user{name:"yuji", score:50}
u.hit()
u.show()
}
- 実行結果
$ go run hello.go
name:yuji, score:51
** インターフェースを使ってみよう [#k49ab556]
- メソッドの一覧を定義したデータ型
- 異なる構造体が共通のインターフェースを実装することで同...
package main
import "fmt"
type greeter interface {
greet()
}
type japanese struct {}
type american struct {}
func (j japanese) greet() {
fmt.Println("Konnnichiwa!")
}
func (a american) greet() {
fmt.Println("Hello!")
}
func main() {
greeters := []greeter{japanese{}, american{}}
for _, greeter := range greeters {
greeter.greet()
}
}
- 実行結果
$ go run hello.go
Konnnichiwa!
Hello!
** 空のインターフェース型を使おう [#b2a57e42]
- 空のインターフェースは実装すべきメソッドが無い
- これを活用することにより実際的に全てのデータ型を受け取...
- 処理中の実装には空のインターフェース型が何か (データ型...
- 型アサーションを使ったデータ型判別
func show(t interface{}) {
// 型アサーション
_, ok := t.(japanese)
if ok {
fmt.Println("i am japanese")
} else {
fmt.Println("i am not japanese")
}
}
type greeter interface {
greet()
}
type japanese struct {}
type american struct {}
func (j japanese) greet() {
fmt.Println("Konnnichiwa!")
}
func (a american) greet() {
fmt.Println("Hello!")
}
func main() {
greeters := []greeter{japanese{}, american{}}
for _, greeter := range greeters {
greeter.greet()
show(greeter)
}
}
- 型Switchを使ったデータ型判別
func show(t interface{}) {
// 型Switch
switch t.(type) {
case japanese:
fmt.Println("i am japanese")
default:
fmt.Println("i am not japanese")
}
}
type greeter interface {
greet()
}
type japanese struct {}
type american struct {}
func (j japanese) greet() {
fmt.Println("Konnnichiwa!")
}
func (a american) greet() {
fmt.Println("Hello!")
}
func main() {
greeters := []greeter{japanese{}, american{}}
for _, greeter := range greeters {
greeter.greet()
show(greeter)
}
}
- 実行結果
$ go run hello.go
Konnnichiwa!
i am japanese
Hello!
i am not japanese
** goroutineを使ってみよう [#xff5aec0]
- 並行処理を簡易的に実装可能
- 並行処理を使わない場合 &color(red){※}; task1 の完了を待...
package main
import (
"fmt"
"time"
)
func task1() {
time.Sleep(time.Second * 2)
fmt.Println("task1 finished!")
}
func task2() {
fmt.Println("task2 finished!")
}
func main() {
task1()
task2()
}
- 実行結果
$ go run hello.go
task1 finished!
task2 finished!
- 並行処理 (goroutine) を使った場合
package main
import (
"fmt"
"time"
)
func task1() {
time.Sleep(time.Second * 2)
fmt.Println("task1 finished!")
}
func task2() {
fmt.Println("task2 finished!")
}
func main() {
go task1()
go task2()
time.Sleep(time.Second * 3)
// goroutine が終わる前に main 関数が終了しないよう...
}
- 実行結果
$ go run hello.go
task2 finished!
task1 finished!
** チャネルを使ってみよう [#pfe3149f]
- goroutine のデータの受け渡しをするパイプ
- 参照型のデータ型 (chan 型)
package main
import (
"fmt"
"time"
)
func task1(result chan string) {
time.Sleep(time.Second * 2)
result<- "task1 result"
}
func task2() {
fmt.Println("task2 finished!")
}
func main() {
result := make(chan string)
go task1(result)
go task2()
fmt.Println(<-result)
time.Sleep(time.Second * 3)
}
- 実行結果
$ go run hello.go
task2 finished!
task1 result
** Webサーバーを作ってみよう [#t515df73]
- net/http パッケージを利用した web サーバー構築
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
- 実行後 8080 番で Listen するのでブラウザ経由でアクセス
- http://192.168.33.10:8080/ へアクセスすると "Hi" と表示
- http://192.168.33.10:8080/yuji/ へアクセスすると "Hi yu...
- &color(red){※}; 事前に firewalld を停止しておくこと
終了行:
#contents
** Go言語とはなにか? [#z4caea8f]
- 概要
-- Google
-- シンプルな言語仕様
-- 高速
-- 並行プログラミング
- 公式サイト
-- https://golang.org/
- 前提知識
-- Unixコマンド
-- C言語
- 環境
-- CentOS7 (Vagrant)
-- sudo yum install golang
- Goインストール
$ pwd
/home/vagrant/golang_lessons
$ sudo yum -y install golang
$ go version
go version go1.6.3 linux/amd64
** はじめてのGoプログラム [#u15e3fc8]
- hello.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行コメントは「//」複数行コメントは「/* */」
-- 文末に「;」は不要
-- インデントはスペースではなくタブ推奨
** 変数を使ってみよう [#ld66c6f8]
- 基本形
func main() {
var msg string
msg = "hello world"
fmt.Println(msg)
}
- 変数宣言と同時に値代入 &color(red){※}; 型 (string) は省...
func main() {
var msg = "hello world"
fmt.Println(msg)
}
- 変数宣言と同時に値代入 &color(red){※}; := を利用した記法
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文字目が大文字: 他のパッケージからもアクセス可
-- 変数、定数、関数についても同じルール
** 基本データ型を使ってみよう [#nfef6c70]
- 文字列: string
-- "hello"
-- 初期値: 空文字 &color(red){※}; nil では無い
- 整数: int
-- 53
-- 初期値: 0
- 浮動小数: float64
-- 10.2
- 真偽値: bool
-- false / true
-- 初期値: false
- nil
- printf の使い方
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
** 定数を使ってみよう [#v40588d3]
- const で宣言
- 値の変更不可
- hello.go
package main
import "fmt"
func main() {
const name = "yuji"
name = "shimojo"
fmt.Println(name)
}
- 実行結果
$ go run hello.go
# command-line-arguments
./hello.go:7: cannot assign to name
- iota を使った定数宣言 &color(red){※}; 自動で連番の値を...
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
** 基本的な演算をしてみよう [#v6694ecc]
- 四則演算: + - * / %
- 文字列: +
- 論理値: AND(&&) OR(||) NOT(!)
- 余りの計算
func main() {
var x int
x = 10 % 3
fmt.Println(x)
}
- 実行結果
$ go run hello.go
1
- x = x + 3 の代入
func main() {
var x int
x += 3 // x = x + 3
fmt.Println(x)
}
- 実行結果
$ go run hello.go
3
- インクリメント &color(red){※}; "x = x++" や "++x" の記...
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
** ポインタを使ってみよう [#ie5aa5f1]
- ポインタ
-- メモリ上のアドレスを指し示す変数
-- 演算はできない
- hello.go
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
** 関数を使ってみよう [#r985b6fc]
- 基本形 (引数なし)
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) を指定 &color(red){※}; return 時に...
func hi(name string) (msg string) {
msg = "hi!" + name
return
}
func main() {
fmt.Println(hi("yuji"))
}
- 実行結果
$ go run hello.go
hi!yuji
- 返り値を2つ指定 &color(red){※}; Go言語の特徴として返り...
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
** 配列を使ってみよう [#u958a099]
- 基本形
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
** スライスを使ってみよう [#e8115998]
- 配列
-- 関数に配列を渡す場合には値を丸ごと渡すためメモリ的に非...
-- 配列の要素数は固定になっていて動的に変化させることがで...
- スライス
-- 配列を便利に使えるようにしたデータ型
-- 配列の一部または全部を指し示す参照型のデータ
-- Go言語においては配列よりもスライスがよく使われる
- 配列の一部をスライスで参照
func main() {
a := [5]int{2, 10, 8, 15, 4}
s := a[2:4] // [8, 15] ... 配列 a の添字は省略可 [:]...
fmt.Println(a)
fmt.Println(s)
}
- 実行結果
$ go run hello.go
[2 10 8 15 4]
[8 15]
- スライスの値を変更 &color(red){※}; 参照先の配列の値も変...
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()を使おう [#w048b810]
- make を使ってスライスを宣言 (初期値は0)
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]
- append を使ってスライスの末尾に要素を追加
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 にコピー &color(re...
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
** マップを使ってみよう [#u24de239]
- 添字にキーを使ってキーと値のペアで管理可能なデータ型
- 他の言語では ハッシュ や 連想配列 とも呼ばれている
- 基本形
func main() {
m := make(map[string]int) // key: string型, value: i...
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で条件分岐をしてみよう [#jf0f6a42]
- 基本形
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!
- if 文の中で変数を定義
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 文の中のスコープのため上記は undefine...
}
- 実行結果
$ go run hello.go
so so...
- if 文 の条件で利用可能な演算子
-- 比較演算子: > >= < <= == !=
-- 論理演算子: && || !
** switchで条件分岐をしてみよう [#ke0f0c15]
- 基本形
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
- if else 文を switch 文で置き換え
func main() {
score := 82
switch {
case score > 80:
fmt.Println("Great!")
default:
fmt.Println("so so ...")
}
}
- 実行結果
$ go run hello.go
Great!
** forでループ処理をしてみよう [#n543ff36]
- 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
- while 文風な記法
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
- 条件を省略 &color(red){※}; 無限ループとなるため break ...
func main() {
i := 0
for {
fmt.Println(i)
i++
if i == 3 { break }
}
}
- 実行結果
$ go run hello.go
0
1
2
** rangeを使ってみよう [#jb8bbb93]
- 配列 / スライスやマップに対して要素分だけ何らかの処理を...
- スライスの値を一つずつ取得して要素番号 (index) と値 (va...
func main() {
s := []int{2, 3, 8}
for i, v := range s {
fmt.Println(i, v)
}
}
- 実行結果
$ go run hello.go
0 2
1 3
2 8
- 要素番号 (index) の代わりにブランク修飾子を使って値 (va...
func main() {
s := []int{2, 3, 8}
for _, v := range s {
fmt.Println(v)
}
}
- 実行結果
$ go run hello.go
2
3
8
- マップに対しての繰り返し処理
func main() {
m := map[string]int{"yuji":200, "shimojo":300}
for k, v := range m {
fmt.Println(k, v)
}
}
- 実行結果
$ go run hello.go
yuji 200
shimojo 300
** 構造体を使ってみよう [#u2b6cbbe]
- 複数の値を意味のあるまとまりとして新しい型を定義するこ...
- フィールド: 構造体内で定義する各変数
- user 型の構造体定義 &color(red){※}; 構造体 u の返り値は...
type user struct {
name string
score int
}
func main() {
u := new(user)
fmt.Println(u)
}
- 実行結果
$ go run hello.go
&{ 0}
- フィールドに値を代入
type user struct {
name string
score int
}
func main() {
u := new(user)
// (*u).name = "yuji"
u.name = "yuji"
u.score = 20
fmt.Println(u)
}
- 実行結果
$ go run hello.go
&{yuji 20}
- 構造体の初期化時に値を代入 &color(red){※}; 返り値はポイ...
type user struct {
name string
score int
}
func main() {
// u := user{"yuji", 50}
u := user{name:"yuji", score:50}
fmt.Println(u)
}
- 実行結果
$ go run hello.go
{yuji 50}
** メソッドを使ってみよう [#l11b9595]
- Go言語ではオブジェクト指向言語で提供されるクラスやメソ...
- Go言語のメソッドは構造体などのデータ型に紐付いた関数
- 関数をデータ型と紐づけるためにレシーバーと呼ばれるもの...
- メソッド (値渡し) &color(red){※}; メソッドの引数として...
type user struct {
name string
score int
}
func (u user) show() {
fmt.Printf("name:%s, score:%d\n", u.name, u.score)
}
func main() {
u := user{name:"yuji", score:50}
u.show()
}
- 実行結果
$ go run hello.go
name:yuji, score:50
- メソッド (参照渡し) &color(red){※}; 値渡しの場合だと u....
type user struct {
name string
score int
}
func (u user) show() {
fmt.Printf("name:%s, score:%d\n", u.name, u.score)
}
func (u *user) hit() {
u.score++
}
func main() {
u := user{name:"yuji", score:50}
u.hit()
u.show()
}
- 実行結果
$ go run hello.go
name:yuji, score:51
** インターフェースを使ってみよう [#k49ab556]
- メソッドの一覧を定義したデータ型
- 異なる構造体が共通のインターフェースを実装することで同...
package main
import "fmt"
type greeter interface {
greet()
}
type japanese struct {}
type american struct {}
func (j japanese) greet() {
fmt.Println("Konnnichiwa!")
}
func (a american) greet() {
fmt.Println("Hello!")
}
func main() {
greeters := []greeter{japanese{}, american{}}
for _, greeter := range greeters {
greeter.greet()
}
}
- 実行結果
$ go run hello.go
Konnnichiwa!
Hello!
** 空のインターフェース型を使おう [#b2a57e42]
- 空のインターフェースは実装すべきメソッドが無い
- これを活用することにより実際的に全てのデータ型を受け取...
- 処理中の実装には空のインターフェース型が何か (データ型...
- 型アサーションを使ったデータ型判別
func show(t interface{}) {
// 型アサーション
_, ok := t.(japanese)
if ok {
fmt.Println("i am japanese")
} else {
fmt.Println("i am not japanese")
}
}
type greeter interface {
greet()
}
type japanese struct {}
type american struct {}
func (j japanese) greet() {
fmt.Println("Konnnichiwa!")
}
func (a american) greet() {
fmt.Println("Hello!")
}
func main() {
greeters := []greeter{japanese{}, american{}}
for _, greeter := range greeters {
greeter.greet()
show(greeter)
}
}
- 型Switchを使ったデータ型判別
func show(t interface{}) {
// 型Switch
switch t.(type) {
case japanese:
fmt.Println("i am japanese")
default:
fmt.Println("i am not japanese")
}
}
type greeter interface {
greet()
}
type japanese struct {}
type american struct {}
func (j japanese) greet() {
fmt.Println("Konnnichiwa!")
}
func (a american) greet() {
fmt.Println("Hello!")
}
func main() {
greeters := []greeter{japanese{}, american{}}
for _, greeter := range greeters {
greeter.greet()
show(greeter)
}
}
- 実行結果
$ go run hello.go
Konnnichiwa!
i am japanese
Hello!
i am not japanese
** goroutineを使ってみよう [#xff5aec0]
- 並行処理を簡易的に実装可能
- 並行処理を使わない場合 &color(red){※}; task1 の完了を待...
package main
import (
"fmt"
"time"
)
func task1() {
time.Sleep(time.Second * 2)
fmt.Println("task1 finished!")
}
func task2() {
fmt.Println("task2 finished!")
}
func main() {
task1()
task2()
}
- 実行結果
$ go run hello.go
task1 finished!
task2 finished!
- 並行処理 (goroutine) を使った場合
package main
import (
"fmt"
"time"
)
func task1() {
time.Sleep(time.Second * 2)
fmt.Println("task1 finished!")
}
func task2() {
fmt.Println("task2 finished!")
}
func main() {
go task1()
go task2()
time.Sleep(time.Second * 3)
// goroutine が終わる前に main 関数が終了しないよう...
}
- 実行結果
$ go run hello.go
task2 finished!
task1 finished!
** チャネルを使ってみよう [#pfe3149f]
- goroutine のデータの受け渡しをするパイプ
- 参照型のデータ型 (chan 型)
package main
import (
"fmt"
"time"
)
func task1(result chan string) {
time.Sleep(time.Second * 2)
result<- "task1 result"
}
func task2() {
fmt.Println("task2 finished!")
}
func main() {
result := make(chan string)
go task1(result)
go task2()
fmt.Println(<-result)
time.Sleep(time.Second * 3)
}
- 実行結果
$ go run hello.go
task2 finished!
task1 result
** Webサーバーを作ってみよう [#t515df73]
- net/http パッケージを利用した web サーバー構築
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
- 実行後 8080 番で Listen するのでブラウザ経由でアクセス
- http://192.168.33.10:8080/ へアクセスすると "Hi" と表示
- http://192.168.33.10:8080/yuji/ へアクセスすると "Hi yu...
- &color(red){※}; 事前に firewalld を停止しておくこと
ページ名: