Skip to content

Go 言語速攻チェック表 (Cheat Sheet)

Go(別名 Golang)は、Google の Robert Griesemer、Rob Pike、および Ken Thompson によって開発された、静的型付けのコンパイル言語です。Go 言語の構文は C 言語に似ていますが、メモリ安全性、GC(ガベージコレクション)、構造的型付け、および CSP スタイルの並行計算などの機能を備えています。

Hello world

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) (string) {
  return "Hello, " + name + "!"
}
$ go build

変数

変数宣言

var msg string
msg = "Hello"

略記法

msg := "Hello"

定数

const Phi = 1.618

定数は、文字、文字列、ブール値、または数値にすることができます。

基本型

文字列 (Strings)

str := "Hello"
str := `複数行の
文字列`

文字列の型は string です。

数値

代表的な型

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (uint8 のエイリアス)

その他の型

var u uint = 7        // uint (符号なし)
var p float32 = 22.7  // 32ビット浮動小数点数

ポインタ

func main () {
  b := *getPointer()
  fmt.Println("Value is", b)
}
 
func getPointer () (myPointer *int) {
  a := 234
  return &a
}

ポインタは、変数のメモリ位置を指します。Go は完全なガベージコレクション機能を備えています。

配列 (Arrays)

// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

配列のサイズは固定です。

スライス (Slices)

slice := []int{2, 3, 4}
slice := []byte("Hello")

配列とは異なり、スライスは動的なサイズを持ちます。

制御構文

条件分岐 (If)

if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}

if 内のステートメント

if _, err := getResult(); err != nil {
  fmt.Println("Uh oh")
}

if 文は、条件式の前に簡単なステートメントを実行できます。

Switch

switch day {
  case "sunday":
    // デフォルトでは "fall through" しません!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

関数

ラムダ (関数の値)

myfunc := func() bool {
  return x > 10000
}

関数は第一級オブジェクトです。

複数の戻り値

a, b := getMessage()
func getMessage() (a string, b string) {
  return "Hello", "World"
}

名前付き戻り値

func split(sum int) (x, y int) {
  x := sum * 4 / 9
  y := sum - x
  return
}

戻り値の名前に変数を宣言することで、return(引数なし)はそれらの名前の変数を返します。

パッケージ

インポート

import "fmt"
import "math/rand"
import (
  "fmt"        // fmt.Println を提供
  "math/rand"  // rand.Intn を提供
)

どちらも同じです。

エイリアス

import r "math/rand"
 
r.Intn()

公開名 (Exported names)

func Hello () {
  ···
}

公開名は、大文字で始めます。

パッケージ宣言

package hello

各パッケージファイルは package から始まる必要があります。

並行性 (Concurrency)

ゴルーチン (Goroutines)

func main() {
  // チャネルの作成
  ch := make(chan string)

  // 並行ルーチンの開始
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // 3 つの結果を読み取る
  // (ゴルーチンは並行であるため、
  // 順序は保証されません!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

チャネルは、ゴルーチン間で使用される並行セーフな通信オブジェクトです。

バッファ付きチャネル

ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// fatal error:
// all goroutines are asleep - deadlock!

バッファ付きチャネルは、保持できるメッセージの数を制限します。

チャネルのクローズ

チャネルをクローズする

ch <- 1
ch <- 2
ch <- 3
close(ch)

クローズされるまでチャネルを反復処理する

for i := range ch {
  ···
}

ok == false の場合はクローズされています

v, ok := <- ch

遅延実行 (Defer)

Defer

func main() {
  defer fmt.Println("Done")
  fmt.Println("Working...")
}

関数の実行を、それを囲む関数が終了するまで遅延させます。引数は即座に評価されますが、関数呼び出しは最後まで実行されません。

ラムダを使用した Defer

func main() {
  defer func() {
    fmt.Println("Done")
  }()
  fmt.Println("Working...")
}

遅延ブロックにはラムダ(匿名関数)が適しています。

構造体 (Structs)

定義

type Vertex struct {
  X int
  Y int
}

func main() {
  v := Vertex{1, 2}
  v.X = 4
  fmt.Println(v.X, v.Y)
}

リテラル

v := Vertex{X: 1, Y: 2}
// フィールド名を省略可能
v := Vertex{1, 2}
// Y は暗黙的
v := Vertex{X: 1}

フィールド名を指定することもできます。

構造体へのポインタ

v := &Vertex{1, 2}
v.X = 2

v がポインタの場合、v.X(*v).X は同じです。

メソッド

レシーバ

type Vertex struct {
  X, Y float64
}
func (v Vertex) Abs() float64 {
  return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
 
v := Vertex{1, 2}
v.Abs()

クラスはありませんが、レシーバを使用して型に関数を定義できます。

ポインタレシーバ

func (v *Vertex) Scale(f float64) {
  v.X = v.X * f
  v.Y = v.Y * f
}
 
v := Vertex{6, 12}
v.Scale(0.5)
// `v` が更新される