nemunemu_zzzの日記

備忘録的な何かになればいいな

golangのinterface{}の不思議

golangを触り始めて約3ヶ月

interface{}が便利なのでよく使います

 

ただ最初はinterface{}の挙動がよくわかってなくて使うたびに苦戦してたのでメモメモ_φ(・_・

 

package main

import(
  "fmt"
)

func main() {
  Output("string")
  Output(100)
  Output(true)
}

func Output(x interface{}) {
  fmt.Println(x)
}

=> string
100
true

特に型を宣言しなくてもなんでもこーい!なことができる

すごい便利

 

ただ, もし受け取った関数で型がしっかりと指定しないとダメなケースがある

大体がこのパターン, だから便利だけとメンドくささもある

例えば次のような場合

package main

import(
  "fmt"
)

func main() {
  Output(100)
}

func Output(x interface{}) {
  fmt.Println(x*2)
}

=> # command-line-arguments
./test.go:12:16: invalid operation: x * 2 (mismatched types interface {} and int)

interface{}型とint型では計算できませんよって怒られます

なんでも受け取ってくれるのに実は繊細なのかなって感じです

解決作

package main

import(
  "fmt"
)

func main() {
  Output(100)
}

func Output(x interface{}) {
  fmt.Println(x.(int)*2)
}

=> 200
 

変数の後ろにx.(int)と, interface{}型で受け取ったけど, この子はint型ですよーって書いてあげれば大丈夫

主にswitchを使って分岐処理をさせることが多いです

    package main

import(
  "fmt"
)

func main() {
  Output("aaaaaaa")
  Output(100)
  Output([]string{"a", "b", "c"})
}

func Output(x interface{}) {
  switch v := x.(type) {
  case string:
    fmt.Println(v)
  case int:
    fmt.Println(2*v)
  case []string:
    fmt.Println(v)
  }
}

=> aaaaaaa
200
[a b c]

こんな感じで変数の型(type)によって処理を分岐させます

あともう1つ詰まったところがあり, それが配列のinterface{}

[]interface{}ってやっとけば, stringだろうがintだろうがboolだろうがうけとってくれるやろーって

package main

import(
  "fmt"
)

func main() {
  Output([]string{"a", "b", "c"})
  Output([]int{100, 200, 300})
  Output([]bool{true, false})
}

func Output(x interface{}) {
  switch v := x.(type) {
  case []interface{}:
    fmt.Println(v)
  default:
    fmt.Println("ハズレ")
  }
}

=> ハズレ
ハズレ
ハズレ

そうはうまくいかないんですね

見事にスルーされてます(泣

実は[]interface{}型の配列であれば受け取ってもらえます

package main

import(
  "fmt"
)

func main() {
  Output([]interface{}{"test1", 100, true})
}

func Output(x interface{}) {
  switch v := x.(type) {
  case []interface{}:
    fmt.Println(v)
  default:
    fmt.Println("ハズレ")
  }
}

=> [test1 100 true]

interface{}型の配列が存在するために, 配列の型なんでもこーいって形で使用することができないのかなって感じです

というな感じで, interface{}と戯れてましたってお話でした

interface{}は便利