Rubyから始めるGo ~ 文法 ~

# はじめに

Rubyを知っている状態で、Goを勉強してみました。

GoはGoogleが開発したプログラミング言語で実行速度が速いのが持ち味らしいです。

# バージョン

| Ruby  | Go     |
| :---- | :----- |
| 2.7.1 | 1.16.5 |

# 基本形

```go:main.go
package main

import "fmt" // コンソールに出力する用のパッケージ

func main() {
    // コンソールに出力
    fmt.Println("Hello World")
}
```

# Rubyで解釈

## 変数定義(例：文字列型)

```ruby:ruby
message = "Hello World"
```

```go:go
// 通常系
var message string = "Hello World"
// 省略形 その１
var message = "Hello World 2"
// 省略形 その2
message := "Hello World 3"
```

### 論理値型

```ruby:ruby
flag = true
```

```go:go
var flag bool = true
```

### 数値型

```ruby:ruby
num = 255
p num.class # => Integer
```

```go:go
// 符号なし整数型
var unum1 uint8 = 255
var unum2 byte = 255
var unum3 uint16 = 65535
var unum4 uint32 = 4294967295
var unum5 uint64 = 18446744073709551615
fmt.Printf("%T => %d ~ %d\n", unum1, 0, math.MaxUint8) // uint8 => 0 ~ 255
fmt.Printf("%T => %d ~ %d\n", unum2, 0, math.MaxUint8) // uint8 => 0 ~ 255
fmt.Printf("%T => %d ~ %d\n", unum3, 0, math.MaxUint16) // uint16 => 0 ~ 65535
fmt.Printf("%T => %d ~ %d\n", unum4, 0, math.MaxUint32) // uint32 => 0 ~ 4294967295
fmt.Printf("%T => %d ~ %d\n", unum5, 0, uint64(math.MaxUint64)) // uint64 => 0 ~ 18446744073709551615

// 符号付整数型
var num1 int8 = 127
var num2 int16 = 32767
var num3 int32 = 2147483647
var num4 int64 = 9223372036854775807
fmt.Printf("%T => %d ~ %d\n", num1, math.MinInt8, math.MaxInt8) // int8 => -128 ~ 127
fmt.Printf("%T => %d ~ %d\n", num2, math.MinInt16, math.MaxInt16) // int16 => -32768 ~ 32767
fmt.Printf("%T => %d ~ %d\n", num3, math.MinInt32, math.MaxInt32) // int32 => -2147483648 ~ 2147483647
fmt.Printf("%T => %d ~ %d\n", num4, math.MinInt64, math.MaxInt64) // int64 => -9223372036854775808 ~ 9223372036854775807
```

### 浮動小数点型

```ruby:ruby
num = 1.1
p num.class # => Float
```

```go:go
var fnum1 float32 = 1.1
var fnum2 float64 = 1.1
fmt.Printf("%T => %d ~ %f\n", fnum1, 0, float32(math.MaxFloat32)) // float32 => 0 ~ 340282346638528859811704183484516925440.000000
fmt.Printf("%T => %d ~ %f\n", fnum2, 0, float64(math.MaxFloat64)) // float64 => 0 ~ 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
```

### 配列型

```ruby:ruby
# 通常系
arr = ["Hello", "World"]

# %記法
arr = %w(Hello World)

# 要素追加
arr << 'HOGE'
arr += ['FUGA']

p arr # => ["Hello", "World", "HOGE", "FUGA"]
```

```go:go
// 通常系
var arr[2] string
arr[0] = "Hello"
arr[1] = "World"

// 省略形 その１
var arr[2] string = [2]string {"Hello", "World"}

// 省略形 その2
arr := [2]string {"Hello", "World"}

// 要素数省略
arr := [...] string {"Hello", "World"}

// slice
// arrayは要素の個数が決まっているので、sliceで要素の追加等を行う
// sliceの定義は、arrayの定義方法とほぼ同じで、要素数を書かなければ、sliceとなる
s := [] string {"Hello", "World"}
s = append(s, "HOGE")
s = append(s, "FUGA")
fmt.Println(s) // => [Hello World HOGE FUGA]
```

### 連想配列(map)

- Rubyで言うハッシュ

```ruby:ruby
hash = { hoge: 'HOGE', huga: 'HUGA' }
```

```go:go
// make関数を使って宣言
hash := make(map[string]string)
hash["hoge"] = "HOGE"
hash["fuga"] = "FUGA"
fmt.Println(hash) // => map[fuga:FUGA hoge:HOGE]
fmt.Println(object["hoge"]) // => HOGE

// 初期値を指定して宣言
hash := map[string]string{"hoge": "HOGE", "fuga": "FUGA"}
fmt.Println(hash) // => map[fuga:FUGA hoge:HOGE]
fmt.Println(hash["fuga"]) // => FUGA
```

## 変数の自己代入

```ruby:ruby
n = 10

n += 10
n -= 5
n *= 3
n /= 2
n %= 2

n += 1
n -= 1
```

```go:go
n := 10

n += 10
n -= 5
n *= 3
n /= 2
n %= 2

n++
n--
```

## if文

```ruby:ruby
x = 100
y = 9

if x >= 100
elsif x >= 90
else
end

if y < 10
elsif y < 9
else
end
```

```go:go
x := 100
y := 9

if x >= 10 {
} else if x >= 90 {
} else {
}

if y < 10 {
} else if y < 9 {
} else {
}
```

## 比較演算子

```ruby:ruby
1 == 1
1 != 2
1 < 2
1 <= 1
2 > 1
1 >= 1
```

```go:go
1 == 1
1 != 2
1 < 2
1 <= 1
2 > 1
1 >= 1
```

## 論理演算子

```ruby:ruby
true && true
true || false
!false
```

```go:go
true && true
true || false
!false
```

## switch文

```ruby:ruby
n = 3

case n
when 10
  p 10
when 5, 0
  p 5, 0
else
  p -1
end
```

```go:go
n := 3

switch n {
  case 10:
    fmt.Println(10)
  case 5, 0:
    fmt.Println(5, 0)
  default:
    fmt.Println(-1)
}
```

## for文

```ruby:ruby
for num in 1..3
  print "num = ", num, "\n"
end
```

```go:go
// for文の変数定義は var を使えないので、省略系で変数定義
for num := 1; num <= 3; num++ {
  fmt.Println("num =", num)
}
```

## Arrayのeach

```ruby:ruby
arr = %w(Hello World)

arr.each do |v|
  p v
end
```

```go:go
arr := [] string {"Hello", "World"}

for _, v := range arr {
  fmt.Println(v)
}
```

## 連想配列のeach

```ruby:ruby
hash = { hoge: 'HOGE', huga: 'HUGA' }

hash.each do |k, v|
  puts k, v
end
```

```go:go
hash := map[string]string{"hoge": "HOGE", "fuga": "FUGA"}

for k, v := range hash {
  fmt.Println(k, v)
}
```

## each_with_index

```ruby:ruby
%w(Hello World).each_with_index do |v, i|
  puts i, v
end
```

```go:go
for i, v := range []string {"Hello", "World"} {
  fmt.Println(i, v)
}
```

## 乱数

```ruby:ruby
rand 10
```

```go:go
// randパッケージをインポート
import "math/rand"
// timeパッケージをインポート
import "time"

~ 省略 ~

// 毎回異なる乱数を生成する為に必要
rand.Seed(time.Now().Unix())

rand.Intn(10)
```

## メソッド定義（引数、返り値）

```ruby:ruby
def sample(s)
  "Hello #{s}"
end

sample("World") #=> "Hello World"
```

```go:go
func main() {
  fmt.Printf(sample("World")) //=> "Hello World"
}

func sample(s string) string {
  return "Hello " + s  + "\n"
}
```

## ポインタ型変数

```ruby:ruby
require 'fiddle'

str = "ABC"
strP = Fiddle::Pointer[str]
p sprintf("%#x", strP.to_i) #=> 0x7fb81f892c58
strP[0, 3] = "DEF"
p str #=> DEF
```

```go:go
str := "ABC"
// 変数の頭に `&` をつけると、その変数のポインタが取得できる
fmt.Println(&str) //=> 0xc000010250
// ポインタ型の変数を定義する場合、 `*[変数の型]`で定義できる
var strP *string = &str
fmt.Println(strP) //=> 0xc000010250
// ポインタ型変数の頭に `*` をつけるとポインタが示す変数を取得できる
fmt.Println(*strP) //=> ABC
// ポインタで `str` の値更新
*strP = "DEF"
fmt.Println(str) //=> DEF
```

# 参考文献

- [Go言語：文法基礎まとめ - Qiita](https://qiita.com/HiromuMasuda0228/items/65b9a593275f769f6b69)
- [【Go】基本文法④(配列・スライス) - Qiita](https://qiita.com/k-penguin-sato/items/daad9986d6c42bdcde90)
- [【Go】基本文法⑤(連想配列・ Range) - Qiita](https://qiita.com/k-penguin-sato/items/a320072fa09502bde3e9)
- [Go言語 - 整数型 - blog](https://blog.y-yuki.net/entry/2017/04/27/000000)