http://go-tour-jp.appspot.com/#1
Golangが熱いと小耳に挟んだので読める程度に基本的な文法を抑えていきます。
#Hallo World
package main
import("fmt")
func main() {
fmt.Println("Hallo World")
}
開始点:package mainが必要
#型
int:初期値 0
float32: 初期値 0
bool: 初期値 false
string: 初期値 ""
complex64: 初期値 (0+0i)
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 の別名
rune // int32 の別名
// Unicode のコードポイントを表す
float32 float64
complex64 complex128
#配列
p := []int{2, 3, 5, 7, 11, 13}
配列のfor文
for i := 0; i < len(p); i++ {
fmt.Printf("p[%d] == %d\n", i, p[i])
}
部分配列
p[<start>:<end>]
p[1:4]
p[1:]//p[1:<last>]
p[:4]//p[0:4]
配列のメモリ確保
make([]int, 5) // len(a)=5
make([]int, 0, 5) // len(b)=0, cap(b)=5
#Map
var m map[string]Vertex
m = make(map[string]Vertex)
Mapリテラル
最終行もカンマ必須
var m = map[string]int{
"Bell Labs": 1,
"Google": 2 ,
}
アクセッサ
m[key] = elem
elem = m[key]
delete(m, key)
キーの有無チェック
elem, ok = m[key]//存在すればok=true
#変数の宣言
var x, y int
初期値が与えられた場合、型宣言不要
var x, y, z = 0, 0.1, "str"
関数内でのみ宣言不要(暗黙的な宣言)
func f(){
x := a
}
#定数の宣言
const <name> = <val>
const (
<name1> = <val1>
<name2> = <val2>
)
#ループ
for文のみ whileなし
for i := 0; i < 10; i++ {
}
whileと同等
for i < 10 {
}
無限ループ
for {
}
要素の繰り返し
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
for i, v := range pow {
}
indexの破棄
for _, v := range pow {
}
#条件分岐
if x < 0 {
}
if文内でのみ有効な変数の宣言
if v := math.Pow(x, n); v < lim {
return v
}
else文
if v < lim {
} else {
}
##switch文
自動でbreakする
caseに式が使える
switch time.Saturday {
case today + 0:
fmt.Println("Today.")
case today + 1:
fmt.Println("Tomorrow.")
case today + 2:
fmt.Println("In two days.")
default:
fmt.Println("Too far away.")
}
条件のないswitch=if-elseと同等
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
#関数
func <method>(<arg> <type>, ...) <type>{}
func add(x int, y int) int {
return x + y
}
引数が同じ型の場合、最初を省略できる。
func add(x, y int) int {
return x + y
}
戻り値を複数返すことが可能
func double_string() (string, string){
return "a", "b"
}
戻り値のパラメータ化が可能。
戻り値に名前を付けるとreturn文で明示しなくてよい。
func f()(s string){
s = "aaa"
return
}
変数に代入できる
hypot := func(x, y float64) float64 {
}
Goの関数はクロージャー
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
#構造体
type Vertex struct {
X int
Y int
}
初期化
Vertex{1, 2}
アクセス
v = Vertex{1, 2}
v.X
ポインタ
p := Vertex{1, 2}
q := &p
q.X
フィールドの一部のみ初期化(Name構文)
Vertex{X: 1}
newを使用した初期化。ポインタが渡される
フィールドは暗黙的な初期化が行われる。
var v *Vertex = new(Vertex)
v := new(Vertex)
##メソッド
GoにはClassがないが構造体にメソッドをつけられる
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := &Vertex{3, 4}
fmt.Println(v.Abs())
}
構造体以外の任意の型も可能
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
f := MyFloat(-math.Sqrt2)
f.Abs()
#インターフェース
type Abser interface {
Abs() float64
}
実装側でインターフェース名を明示する必要なし
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
var a Abser
a = MyFloat(-math.Sqrt2)
#エラーハンドリング
type error interface {
Error() string
}
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func Sqrt(f float64) (float64, error) {}
#キャスト
z := float64(1)
#モジュールのインポート
import(
"module1"
"moduel2"
)
#モジュールのエクスポート
名前を大文字で始める。
- pi:エクスポートされない
- Pi:エクスポートされる
#Web servers
package http
type Handler interface {
ServeHTTP(w ResponseWriter, r *Request)
}
package main
import (
"fmt"
"net/http"
)
type Hello struct{}
func (h Hello) ServeHTTP(
w http.ResponseWriter,
r *http.Request) {
fmt.Fprint(w, "Hello!")
}
func main() {
var h Hello
http.ListenAndServe("localhost:4000", h)
}
#Goroutines
別スレッド実行
go f(x, y, z)
同期処理(Channels)
ch <- v // v をチャネル ch へ送る。
v := <-ch // ch から受信し、
// 変数を v へ割り当てる
以上です。マルチスレッディングが文法レベルでサポートされてるのはいいですね。