RET

Reflection English Technology

年末年始からこつこつGoいじってみた

Goの概要

Rubyと比べたGoの特徴

Ruby

Go

  • コンパイラ言語
  • 静的型付け言語
  • クラスや継承の概念がないがオブジェクト指向プログラミング(っぽいこと)が可能
    • 構造体やインターフェースをうまいこと使う
    • 正直理解がいまいちなので、ここら辺は別記事でいつか詳しくまとめたい
  • マイクロサービスアーキテクチャの中で使われる
  • 書いていて冗長でコードが長くなるという人もいるらしい
    • 「シンプルで要素が少なく、読みやすく、学びやすいことの裏返し」 by 実用Go言語

※1 クラウドネイティブ

クラウドネイティブは、クラウドコンピューティング環境で最新のアプリケーションを構築、デプロイ、および管理するソフトウェアアプローチです。

https://aws.amazon.com/jp/what-is/cloud-native/

クラウドを活用したアプリケーション開発のアプローチ。このアプローチで開発されたアプリをクラウドネイティブアプリケーションという。

クラウドネイティブアプリケーションは、マイクロサービスと呼ばれる相互に依存する複数の小規模なサービスで構成されるソフトウェアプログラムです。(引用元は上と同様)

この引用を見ると、クラウドネイティブアプリケーションはコンテナを使ったマイクロサービスアーキテクチャを採用するものであると考えられるが、文脈によって意味が変わってくるかも知れない。

クラウドネイティブ化(マイクロサービス)の利点としては

  • サービスごとの負荷分散が可能
  • ある一つのサービスに障害が起きても、影響を局所化できる

などがあるらしい。

(この辺りの話が色々書いてありそうな本があるので、後々読みたい)

www.amazon.co.jp

www.amazon.co.jp

Goの長所

Goの短所

マイクロサービスとGo

  • httpサーバー機能がデフォルトで実装されている
  • goroutine という軽量スレッドのおかげで並行処理が最適化される

これらの特徴に加えて文法もシンプルなので他の言語と比べて簡単にマイクロサービス実装可能

https://jp.quora.com/Goがマイクロサービスと相性が良いと言われているの

その他参考

Rubyとの違いを意識しながらTour of Goやってみた

細かい内容には触れず、「へぇ〜Goではそうやって書くんだ〜」と思ったところを軽く書いてみる。

戻り値を複数持てる

func swap(x, y string) (string, string) {
    return y, x
}

戻り値に名前をつけることができる(named return value)

func add(x, y int) (sum int) {
  sum = x + y
  return
}

GoのNamed return valueについてメリデメを考える

変数に初期値を与えずに宣言すると、勝手に初期値が入る(zero values)

var b boolfalse

定数は型の宣言が不要(型がない)

暗黙的な型変換を許さないことによる不便さを解消したい。

var num1 int = 3
var num2 float32 = 1.1

func main() {
    fmt.Println(num1 + num2)
}
 => invalid operation: a + b (mismatched types int and float32)

普通に3 + 1.1したいだけなのに、型が違うだけで拒否られる

const num1 = 3
const num2 = 1.1

func main() {
    fmt.Println(num1 + num2)
}
=> 4.1

このように定数の型を定義しなくてもいいことによって、柔軟さが生まれる

Go の定数の話 - Qiita

簡易文付きif

以下のvalueのようにif文の中でしかない変数を定義できる

func three(num int) string {
  if value := num % 3; value == 0 {
    return "3の倍数"
  } else {
    return "3の倍数ではない"
  }
}

func main() {
    fmt.Println(three(3))
}

例が雑だが以下のようにvalueを参照できない

func three(num int) string {
  if value := num % 3; value == 0 {
    "3の倍数"
  } else {
    "3の倍数ではない"
  }
  
  return value;
}

switch文でbreakがいらない

上から下にcaseが評価され、条件が一致したらそこで終了

func fruit(f string) string {
  var value string
  switch f {
    case "apple":
      value = "りんご"
    default:
      value = "果物を入力せよ"
  }
  
  return value
}

func main() {
  fmt.Printf(fruit("apple"))
}

ポインタ

package main

import "fmt"

func main() {
    i := 30
  fmt.Println(i);
    // ==> 30
    fmt.Println(&i)
    // ==> 0xc00001a090

    p := &i
    fmt.Println(*p)
    // ==> 30
    *p = 100
    fmt.Println(i)
}

slices

配列は固定長なのに対して、スライスは可変調。配列よりも一般的に使われているらしい。

package main

import "fmt"

type Dog struct {
    Name string
    Age int
}

func main() {
    var slice = []int{1, 2, 3, 4 ,5}
    fmt.Println(slice[1])

    var array = [5]int{1, 2, 3, 4, 5 }
    var s = array[1:4]
    fmt.Println(s)
}

goの連想配列(ハッシュ)はmap

var m = map[string]int{"age": 28, "height": 175}

組み込み関数のmakeを使っても連想配列を作れる

var l = make(map[string]int)
l["hoge"] = 3

methods

型に対してメソッドを定義できる。

package main

import "fmt"

type Dog struct {
    Name string
    Age int
}

func (a Dog) hello(){
    fmt.Printf("My name is %s\n", a.Name)
}

func main() {
  d := Dog{Name: "dog", Age: 13}
    d.hello()
}

逆引きGolang (マップ)

感想

Rubyだとpメソッドだけで済むのをimport "fmt”; fmt.Printf()とか書くのめんどくさいなあというのが正直な第一印象。 でも触るにつれどんどん「確かにシンプルなのかもなあ」と思ったり。まあチューリアルこなしただけだとまだまだ全然よくわかってないので、とりあえず今後Goで何かしらAPI作ってみるところまでやってみたい。