▶ 技術めも
study golang memo
逆引きGolang
http://ashitani.jp/golangtips/index.html
Go言語 例文辞典 v1.1.1
http://www.openspc2.org/reibun/Go/1.1.1/
Go言語のstringsパッケージを試してみた
http://y0m0r.hateblo.jp/entry/20120917/1347892585
http://golang.jp/pkg/strings
さあGoを始めよう!環境構築,”Hello World”から簡単なバックエンドサーバーまで
http://postd.cc/how-i-start-go/
Go Con 2017スライドまとめと感想
http://tikasan.hatenablog.com/entry/2017/03/25/225619
net/httpで作るGo APIサーバー #1
http://akirachiku.com/2017/04/01/go-net-http-api-server-1.html
Go言語のFunctional Option Pattern
http://qiita.com/weloan/items/56f1c7792088b5ede136
http://dotinstall.com/lessons/basic_golang
http://golang.org
sudo yum install golang
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
go build hello.go
./hello
go run hello.go
変数
import "fmt"
// 変数名:1文字目に注意
func main() {
var msg string
msg = "hello world"
var msg = "hello world"
msg := "hello world" // 変数と値の入力
var a, b int
a , b = 10 , 15
a, b := 10, 15
// 型が違う文字を一度に設定
var (
c int
d string
)
fmt.Println(msg)
}
string "hello"
int 53
float64 10.2
bool true/false
nil
初期値
var s string // ""
var a int // 0
var f bool // false
fmt.Println()
a := 10
b := 12.5
c := "hello"
var d bool
fmt.Printf("a: %d, b %f, c: %s, d: %t\n", a, b, c, d)
%v で自動で判断
定数
const name = "taguchi"
name = "hoge" // エラー
イオタ
const (
sun = iota // 0
mon // 1
tue // 2
)
演算
数値 + - + / %
文字列 +
論理値 AND(&&) OR (||) NOT(!)
x += 3 // x = x + 3
x++ // ++x は不可
ポインタ
アドレスを指し示す。演算は出来ない
- ポインタ型: * で実体にアクセス
- 実体: & で番地に変換
a := 5
var pa *int
pa = &a // &a = aのアドレス
// pa の領域にあるデータの値 = *pa
fmt.Println(pa)
fmt.Println(*pa)
関数
func hi(name string) string {
fmt.Prinln("Hi! " + name)
msg : = "Hi! " + name
return msg
}
↓
func hi(name string) (msg string) {
fmt.Prinln("Hi! " + name)
msg : = "Hi! " + name
return
}
func main() {
fmt.Println(hi("taguchi"))
}
関数2
func swap(a, b int) (int, int) {
return b, a
}
func main() {
fmt.Println(swap(5, 2))
f := func(a, b int) (int, int) {
return b, a
}
fmt.Println(f(2, 3))
// 即時関数
func(msg string) {
fmt.Println(msg)
}("taguchi")
}
配列
var a [5]int // a[0] - a[4] (添字は0から, 0初期化)
a[2] = 3
a[4] = 10
b := [3]int{1, 3, 5}
↓個数は自明
b := [...]int{1, 3, 5}
fmt.Println(a)
fmt.Println(b)
fmt.Println(len(b))
スライス:配列への参照
可変長配列を持たない代わりに実装された型
配列全体のポインタ(ptr)、配列の長さ(len)、配列の容量(cap)からなるデータ構造を保持している
a := [5]int{2, 10, 8, 15, 4}
s := a[2:4] // [8, 15] 2から4未満までを取得
s := a[:4]
s := a[2:]
s := a[:]
s[1] = 12 // aの値も変更される(参照なので)
fmt.Println(a)
fmt.Println(b)
fmt.Println(b)
fmt.Println(cap(s)) // 切り出しうる最大個数 8, 15, 4 (8からスタートなので)
スライス make(), append(), copy()
// いきなりスライス作成
s := make([]int, 3) // [0 0 0] のスライス
s := []int{1, 3, 5} // [1 3 5] のスライス(要素数を入れないとスライスになる)
// スライスの末尾に値を追加(勝手に領域拡張)
s = append(s, 8, 2, 10)
// copy
t := make([]int, len(s))
n := copy(t, s) // コピーした要素数が n に入る
fmt.Println(s)
マップ(連想配列)
m := make(map[string]int) // キーがstring,値がint
m["taguchi"] = 200
m["fkoji"] = 300
fmt.Println(m)
m := map[string]int{"taguchi":100, "fkoji":200}
fmt.Println(m)
fmt.Println(len(m)) // 個数
delete(m, "taguchi") // 削除
fmt.Println(m)
fmt.Println(len(m)) // 個数
// 存在チェック
v, ok := m["fkoji"]
fmt.Println(v) // 200
fmt.Println(ok) // true 存在している
if 文
> >= < <= == != && || !
score := 83
if score > 80 {
fmt.Println("Great!")
} else if score > 60 {
fmt.Println("Good!")
} else {
fmt.Println("so so...")
}
// if文の中だけで有効な値も定義可能
if score := 83; score > 80 {
fmt.Println("Great!")
} else if score > 60 {
fmt.Println("Good!")
} else {
fmt.Println("so so...")
}
fmt.Println(score) // エラー
switch 文
signal := "red"
switch signal {
case "red":
fmt.Println("Stop")
case "yellow":
fmt.Println("Caution")
case "green", "blue": // カンマで複数指定
fmt.Println("Go")
default:
fmt.Println("wrong signal")
}
score := 83
swith {
case score > 80: // 条件式が書ける
fmt.Println("Great!")
default:
fmt.Println("so so...")
}
for 文
for i := 0; i < 10; i++ {
if i == 3 { break }
if i == 7 { continue }
fmt.Println(i)
}
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// 無限ループ
for {
if i == 3 { break }
}
range
s := []int{2, 3, 8}
for i, v := range s {
fmt.Println(i, v) // 0 2 -> 1 3 -> 2 8
}
for _, v := range s { // ブランク修飾子
fmt.Println(v)
}
m := map[string]int{"taguchi":200, "fkoji":300}
for k, v := range m {
fmt.Println(k, v) // taguchi 200 -> fkogi 300
}
構造体
type user struct {
name string // フィールド
score int
}
// 初期化が必要 new
u := new(user)
u.name = "taguchi"
u.score = 20
fmt.Println(u) // 初期値 &{"", 0}
// 初期値を設定
u := user{"taguchi", 50}
or
u := user{name:"taguchi", score:50}
メソッド(データ型に紐付いた関数)
type user struct {
name string // フィールド
score int
}
func (u user) show() { // レシーバ 値渡し(uでフィールドにアクセスできる)
fmt.Printf("name:%s, score:%d\n", u.name, u.score)
}
func (u *user) show() { // 参照渡し
fmt.Printf("name:%s, score:%d\n", u.name, u.score)
}
u.show()
インターフェイス
メソッドの一覧を定義したデータ型
異なる構造体でも同じインターフェイスを満たす型として処理できる
type greeter interface {
greet() // 挨拶
}
type jananese struct { }
type american struct { }
func (j japanese) greet() {
fmt.Println("Konnichiwa!")
}
func (a american) greet() {
fmt.Println("Hello!")
}
func main() {
greeters := []greeter{japanese{}, american{}} // インターフェイスを満たしている
for _, greeter := range greeters {
greeter.greet() // Konnichiwa! -> Hello!
}
}
空のインターフェイス型
すべてのデータ型が空のインターフェイスを満たしている
// 空のインターフェイスをつかってあらゆる型を受け取る
function show(t interfae{}){
// 2種類の型判断
// 型アサーション
_, ok := t.(japanese)
if (ok) {
fmt.Println("I am japanese")
} else {
fmt.Println("I am not japanese")
}
// 型Swich
switch t.(type) {
case japanese:
fmt.Println("I am japanese")
default:
fmt.Println("I am not japanese")
}
}
func main() {
greeters := []greeter{japanese{}, american{}} // インターフェイスを満たしている
for _, greeter := range greeters {
greeter.greet() // Konnichiwa! -> Hello!
show(greeter) // "I am japanese" -> "I am not japanese"
}
}
goroutine goルーチン:並行処理
package main
import (
"fmt"
"time"
)
func task1() {
time.Sleep(time.Secound * 2)
fmt.Println("task1 finished!")
}
func task2() {
fmt.Println("task2 finished!")
}
// 何も起きない goルーチンが終わる前にmainが終わっているので
func main() {
go task1() // go をつける
go task2()
}
func main() {
go task1() // go をつける
go task2()
time.Sleep(time.Secound * 3) // 3秒待つ
}
チャンネル
データの受け渡しをするパイプ
goルーチンではreturnは使えない
func task1(result chan string) {
time.Sleep(time.Secound * 2)
result<- "task1 finished!" // <- チェネルにデータを入れる
}
func task2() {
fmt.Println("task2 finished!")
}
func main() {
result := make(chan string) // チャネル型 chan string
go task1(result)
go task2()
fmt.Println(<-result) // resultに何か入るまで処理を待つ
}
Webサーバを作成
パッケージ
http://golang.org/pkg/
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)
}