Go入門

## はじめに

[Golangて何？](https://qiita.com/kyawphyonaing/items/da78b99e7d6b99aa249d)
この記事に書いてるオンライン開発環境を立てあげて、
さっそくGo言語 (golang)を使って学習したいと思います。

## プログラムの構造

+ hello.goの作成
+ 内容
    + コメント
    + Println
 
```
// コメント
/*
コメント
コメント
*/
package main 

import "fmt"

func main() {
    fmt.Println("hello world")
}
```

+ 動作確認

```
$ go run hello.go
Hello, World!
```

##  変数

+ variables.goの作成
+ 内容
    + 変数
    + 宣言
    + 代入
    + 命名規則

```
// 変数名: 1文字目に注意

package main 

import "fmt"

func main() {
    // var msg string
    // msg = "hello world"
    // var msg = "hello world"
    msg := "hello world"
    fmt.Println(msg)

    // var a, b int
    // a, b = 10, 15
    // a, b := 10, 15

   /* 
    var (
        c int
        d string
    )
    c = 20
    d = "hoge"
    */
  
   var a, b, c = 3, 4, "foo"  
	
   fmt.Println(a)
   fmt.Println(b)
   fmt.Println(c)
   fmt.Printf("a is of type %T\n", a)
   fmt.Printf("b is of type %T\n", b)
   fmt.Printf("c is of type %T\n", c)
}
```

+ 動作確認

```
$ go run variables.go
hello world
3
4
foo
a is of type int
b is of type int
c is of type string
```

参考 : [Go - Variables](https://www.tutorialspoint.com/go/go_variables.htm)

## 基本データ型

+ datatypes.goの作成
+ 内容
    + 基本データ型
    + Printf

```
// 基本的なデータ型
/*
string      "hello"
int         53
float64     10.2
bool        false true
nil

var s string // ""
var a int // 0
var f bool // false
*/

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 datatypes.go
a: 10, b:12.300000, c:hoge, d:false
```

参考 : [Go - Data Types](https://www.tutorialspoint.com/go/go_data_types.htm)


## 定数

+ constants.goの作成
+ 内容
    + 定数
    + iota

```
package main 

import "fmt"

func main() {
    // const name = "kyaw"
    // name = "fkoji"
    // fmt.Println(name)

    const (
        sun = iota // 0
        mon // 1
        tue // 2
    )
    fmt.Println(sun, mon, tue)


    const LENGTH int = 10
    const WIDTH int = 5   
    var area int

    area = LENGTH * WIDTH
    fmt.Printf("value of area : %d", area) 

}
```

+ 動作確認

```
$ go run constants.go
0 1 2
value of area : 50
```

参考 : [Go - Constants](https://www.tutorialspoint.com/go/go_constants.htm)


## 基本的な演算

+ operators.goの作成
+ 内容
    + 数値の演算
    + 文字列の連結
    + 論理値の演算

```
// 演算
/*
数値 + - * / %
文字列 +
論理値 AND(&&) OR(||) NOT(!)
*/

package main 

import "fmt"

func main() {
    // var x int
    // // x = 10 % 3
    // // x += 3 // x = x + 3
    // x++ // x = x++ ++x
    // fmt.Println(x)

    // var s string
    // s = "hello " + "world" 
    // fmt.Println(s)

     a := true
    b := false
    // fmt.Println(a && b)
    fmt.Println(a || b)
    fmt.Println(!a)
}
```

+ 動作確認

```
$ go run operators.go
true
false
```

参考 : [Go - Operators](https://www.tutorialspoint.com/go/go_operators.htm)


## 条件分岐

+ decisions.goの作成
+ 内容
    + if ... else if ... else ...
    + 変数の定義
    + 比較演算子
    + switch

```
package main

import "fmt"

func main() {

    score1 := 43

    if score1 := 43; score1 > 80 {
        fmt.Println("Great!")
    } else if score1 > 60 {
        fmt.Println("Good!")
    } else {
        fmt.Println("so so...")
    }

    fmt.Println(score1)

    // 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")
    // }

    score2 := 83
    switch {
    case score2 > 80:
        fmt.Println("Great!")
    default:
        fmt.Println("so so ...")
    }
    fmt.Println(score2)
}
```

+ 動作確認

```
$ go run decisions.go
so so...
43
Great!
83
```

参考 : [Go - Decision Making](https://www.tutorialspoint.com/go/go_decision_making.htm)

## forでループ処理

+ loops.goの作成
+ 内容
    + for
    + break
    + Continue

```
package main 

import "fmt"

func main() {

    // for i := 0; i < 10; i++ {
    //     // if i == 3 { break }
    //     if i == 3 { continue }
    //     fmt.Println(i)
    // }

    // i := 0
    // for i < 10 {
    //     fmt.Println(i)
    //     i++
    // }

    i := 0
    for {
        fmt.Println(i)
        i++
        if i == 3 { break }
    }

}
```

+ 動作確認

```
$ go run loops.go
0
1
2
```

参考 : [Go - Loops](https://www.tutorialspoint.com/go/go_loops.htm)


## 関数

+ functions.goの作成
+ 内容
    + 関数の宣言
    + 引数
    + 返り値
    + 複数の返り値
    + 関数リテラル
    + 即時関数

```
package main 

import "fmt"

// func hi(name string) string {
//     // fmt.Println("hi!" + name)
//     msg := "hi!" + name
//     return msg
// }

func hi(name string) (msg string) {
    // fmt.Println("hi!" + name)
    msg = "hi!" + name
    return
}

func main() {
    // hi("kyaw")
    fmt.Println(hi("kyaw"))
}
```

+ 動作確認

```
$ go run functions.go
hi!kyaw
```

```
package main 

import "fmt"

// 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)
    }("kyaw")

}
```

+ 動作確認

```
$ go run functions.go
kyaw
```

参考 : [Go - Functions](https://www.tutorialspoint.com/go/go_functions.htm)


## ポインタ

+ pointers.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 pointers.go
0xc000014080
5
```

参考 : [Go - Pointers](https://www.tutorialspoint.com/go/go_pointers.htm)

## 配列

+ arrays.goの作成
+ 内容
    + 配列の宣言
    + 配列要素
    + len()

```
/*
var a1 int
var a2 int

*/

package main 

import "fmt"

func main() {
    // var a [5]int // a[0] - a[4]
    // a[2] = 3
    // a[4] = 10
    // fmt.Println(a[2])
    // b := [3]int{1, 3, 5}
    b := [...]int{1, 3, 5}
    fmt.Println(b)
    fmt.Println(len(b))

    var n [10]int /* n is an array of 10 integers */
    var i,j int

    /* initialize elements of array n to 0 */         
    for i = 0; i < 10; i++ {
       n[i] = i + 100 /* set element at location i to i + 100 */
    }
   
    /* output each array element's value */
    for j = 0; j < 10; j++ {
       fmt.Printf("Element[%d] = %d\n", j, n[j] )
    }
}
```

+ 動作確認

```
$ go run arrays.go
[1 3 5]
3
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
```

参考 : [Go - Arrays](https://www.tutorialspoint.com/go/go_arrays.htm)


## スライス

+ slices.goの作成
+ 内容
    + スライスの要素
    + len()
    + cap()
    + make()
    + append()
    + copy()

```
package main 

import "fmt"

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)
    fmt.Println(len(s))
    fmt.Println(cap(s))

    b := []int{1, 3, 5}
    // append
    b = append(b, 8, 2, 10)
    // copy
    t := make([]int, len(b))
    n := copy(t, b)
    fmt.Println(b)
    fmt.Println(t)
    fmt.Println(n)
}
```

+ 動作確認

```
$ go run slices.go
[2 10 8 12 4]
[8 12]
2
3
[1 3 5 8 2 10]
[1 3 5 8 2 10]
6
```

参考 : [Go - Slices](https://www.tutorialspoint.com/go/go_slice.htm)


## マップ

+ maps.goの作成
+ 内容
    + マップの宣言
    + 要素へのアクセス
    + len()
    + delete()
    + 存在チェック

```
package main 

import "fmt"

func main() {
    // m := make(map[string]int)
    // m["kyaw"] = 200
    // m["phyo"] = 300
    m := map[string]int{"kyaw":100, "phyo":200}
    fmt.Println(m)
    fmt.Println(len(m))
    delete(m, "kyaw")
    fmt.Println(m)
    v, ok := m["phyo"]
    fmt.Println(v)
    fmt.Println(ok)

   /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}
   
   fmt.Println("Original map")   
   
   /* print map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* delete an entry */
   delete(countryCapitalMap,"France");
   fmt.Println("Entry for France is deleted")  
   
   fmt.Println("Updated map")   
   
   /* print map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
}
```

+ 動作確認

```
$ go run maps.go
map[kyaw:100 phyo:200]
2
map[phyo:200]
200
true
Original map
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted
Updated map
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
```

参考 : [Go - Maps](https://www.tutorialspoint.com/go/go_maps.htm)

## range

+ range.goの作成
+ 内容
    + range

```
package main

import "fmt"

func main() {

    // s := []int{2, 3, 8}
    // for i, v := range s {
    //     fmt.Println(i, v)
    // }
    // for _, v := range s {
    //     fmt.Println(v)
    // }
    m := map[string]int{"kyaw":200, "phyo":300}
    for k, v := range m {
        fmt.Println(k, v)
    }

   /* create a slice */
   numbers := []int{0,1,2,3,4,5,6,7,8} 
   
   /* print the numbers */
   for i:= range numbers {
      fmt.Println("Slice item",i,"is",numbers[i])
   }
   
   /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo"}
   
   /* print map using keys*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* print map using key-value*/
   for country,capital := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",capital)
   }
}
```

+ 動作確認

```
$ go run range.go
phyo 300
kyaw 200
Slice item 0 is 0
Slice item 1 is 1
Slice item 2 is 2
Slice item 3 is 3
Slice item 4 is 4
Slice item 5 is 5
Slice item 6 is 6
Slice item 7 is 7
Slice item 8 is 8
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of France is Paris
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
```

参考 : [Go - Range](https://www.tutorialspoint.com/go/go_range.htm)

## 構造体

+ structures.goの作成
+ 内容
    + 構造体の定義
    + 構造体の宣言

```
package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
type user struct {
    name string
    score int
}
func main() {
   var Book1 Books    /* Declare Book1 of type Book */
   var Book2 Books    /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700
 
   /* print Book1 info */
   printBook(Book1)

   /* print Book2 info */
   printBook(Book2)

    // u := new(user)
    // (*u).name = "kyaw"
    // u.name = "kyaw"
    // u.score = 20

    // u := user{"kyaw", 50}
    u := user{name:"kyaw", score:50}
    fmt.Println(u)
}
func printBook( book Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}
```

+ 動作確認

```
$ go run structures.go
Book title : Go Programming
Book author : Mahesh Kumar
Book subject : Go Programming Tutorial
Book book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700
{kyaw 50}
```

参考 : [Go - Structures](https://www.tutorialspoint.com/go/go_structures.htm)

## メソッド

+ recursion.goの作成
+ 内容
    + メソッドの宣言
    + 値渡しと参照渡し

```
package main 

import "fmt"

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 fibonaci(i int) (ret int) {
   if i == 0 {
      return 0
   }
   if i == 1 {
      return 1
   }
   return fibonaci(i-1) + fibonaci(i-2)
}

func main() {
    u := user{name:"kyaw", score:50}
    // fmt.Println(u)
    u.hit()
    u.show()

   var i int
   for i = 0; i < 10; i++ {
      fmt.Printf("%d ", fibonaci(i))
   }
}
```

+ 動作確認

```
$ go run recursion.go
name:kyaw, score:51
0 1 1 2 3 5 8 13 21 34
```

参考 : [Go - Recursion](https://www.tutorialspoint.com/go/go_recursion.htm)


## インターフェース

+ interfaces_1.goの作成
+ 内容
    + インターフェースの定義
    + 使い方

```
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 interfaces_1.go
Konnnichiwa!
Hello!
```

参考 : [Go - Interfaces](https://www.tutorialspoint.com/go/go_interfaces.htm)


## 空のインターフェース

+ interfaces_2.goの作成
+ 内容
    + 空のインターフェース型
    + 型アサーション
    + 型スイッチ

```
package main

import "fmt"

func show(t interface{}) {
    // 型アサーション
    // _, ok := t.(japanese)
    // if ok {
    //     fmt.Println("i am japanese")
    // } else {
    //     fmt.Println("i am not japanese")
    // }

    // 型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 interfaces_2.go
Konnnichiwa!
i am japanese
Hello!
i am not japanese
```

## goroutine

+ routine.goの作成
+ 内容
    + 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)
}
```

+ 動作確認

```
$ go run routine.go
task2 finished!
task1 finished!
```

## チャネル

+ channel.goの作成
+ 内容
    + Goroutine+channel(並行処理)

```
package main

import (
    "fmt"
    "time"
)

func task1(result chan string) {
    time.Sleep(time.Second * 2)
    // fmt.Println("task1 finished!")
    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 channel.go
task2 finished!
task1 result
```

## エラー処理

+ error.goの作成
+ 内容
    + エラー処理

```
package main

import "errors"
import "fmt"
import "math"

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}
func main() {
   result, err:= Sqrt(-1)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
   
   result, err = Sqrt(9)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
}
```

+ 動作確認

```
$ go run error.go
Math: negative number passed to Sqrt
3
```

参考 : [Go - Error Handling](https://www.tutorialspoint.com/go/go_error_handling.htm)


## Webサーバー

+ web.goの作成
+ 内容
    + Webサーバーの作成

```
package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello Go User %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}
```

+ 動作確認

```
$ go run web.go
後はブラウザで確認しましょう。。。
Codeanywhere でテストしてるならば、　
http://port-8080.Go--xxxxx.codeanyapp.com
このリンクで確認出来ます。
```

※自分のURLを確認したいときは[こちら](https://qiita.com/kyawphyonaing/items/da78b99e7d6b99aa249d#%E8%87%AA%E5%88%86%E3%81%AEurl%E3%82%92%E7%A2%BA%E8%AA%8D)に確認してください。