nyarn.tech

にゃーん

Go言語でメソッド定義 & Go Tour のExercise (Stringers)

構造体型にメソッドを定義する方法

type Vertex struct {
    X, Y float64
}

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())
}

funcのうしろにレシーバと型を宣言します。レシーバはメソッドを呼ぶときの、呼ばれたメソッドのオブジェクトです。(めっちゃわかりにくいですね)
上のサンプルだと v.Abs()したときのvがレシーバです。

class Human
  def initialize(name)
    @name = name
  end

  def say_name
    puts "I am " + self.name
  end
end

h = Human.new("tanaka")
h.say_name  // "I am tanaka"

rubyですが、この例だとsay_nameしたときのオブジェクト(= h)がレシーバです。

rubyでは上のように def ~ endメソッドが定義できるのですが、goではどこでもいいから

type Human struct {
  name string
}

func (h Human) say_name() {
  fmt.Println("I am", h.name)
}

func main() {
    s := Human{ name: "suzuki" }
    s.say_name()
}

のように書くとHumanにsay_nameメソッドが追加できます。

ということで、毎度のGo TourのExcersiseをやってみました。

A Tour of Go

IPAddr 型を実装してみましょう IPアドレスをドットで4つに区切った( dotted quad )表現で出力するため、 fmt.Stringer インタフェースを実装してください。
例えば、 IPAddr{1, 2, 3, 4} は、 "1.2.3.4" として出力するようにします。

package main

import "fmt"

type IPAddr [4]byte

func (addr IPAddr) String() string {
  var str string
  for i := 0; i < len(addr); i++ {
    str += ( fmt.Sprint(addr[i]) + "." )
  }
  return string(str[:len(str) - 1])
}

func main() {
  addrs := map[string]IPAddr{
    "loopback":  {127, 0, 0, 1},
    "googleDNS": {8, 8, 8, 8},
  }
  for n, a := range addrs {
    fmt.Printf("%v: %v\n", n, a)
  }
}

rangeを使えばlen(addr)しなくてもいけるみたいなので、rangeの方もかいてみました。

for _, v := range addr {
  str += ( fmt.Sprint(v) + "." )
}

こちらの方が少しだけすっきりかけますね。
_で捨ててるのもgoっぽい?

最後の文字を取り除くためには、今回は全角文字が含まれないのでそのまま

str[:len(str) - 1]

で大丈夫です。

文字列のスライスはマルチバイト文字列だとruneっていうのを使わないといけないようです。  

str := "モーニング娘。"

をスライスしていときはruneを使います。 こちらの記事と逆引きgolangを参考にしました!

qiita.com

逆引きGolang (文字列)

package main

import "fmt"

func main() {
  str := "モーニング娘。"
  strRune := []rune(str)
  fmt.Println(string(strRune[:len(strRune) - 1]))  // "モーニング娘"
}

そろそろgo tourも終わりそうです!!