Help us understand the problem. What is going on with this article?

Golangの基本文法をおさえてみる

More than 5 years have passed since last update.

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 へ割り当てる

以上です。マルチスレッディングが文法レベルでサポートされてるのはいいですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした