問題
Go言語のmap
では、キーとバリューにそれぞれ型が指定できる。
var myMap = map[int]string{ 60: "還暦", 70: "古希", 77: "喜寿", }
当然、定義したtype
やその参照でも指定できる。
type User struct { Name string Lang string } var myMap = map[string]*User{ "otiai10": &User{Name:"otiai10",Lang:"Go"}, }
一方、Go言語ではラムダ式を即時実行したり、変数に格納したりできる。これによって、関数を返す関数などの定義できたり、並行処理に便利なgoroutine
の記述が簡単になったりする。
func(name string){ fmt.Printf("Hello, %s\n", name) }("otiai10")
今回きになったのは、「文字列→ラムダ式」をmapにしたいときどうすんだ的な。
調査
ラムダ式の"型名"をチェックしてみた
package main import "reflect" func main() { hoge := func(){ println("りっちゃんぺろぺろ!!") } println(reflect.TypeOf(hoge).String()) // "func()" fuga := func() string { return "田井中律 is my wife." } println(reflect.TypeOf(fuga).String()) // "func() string" }
どうやら普通に"func()"
って書けばいいっぽい雰囲気ある
解決
package main var funcMap = map[string]func(int) int { "double": func(i int) int { return i * 2 }, } func main() { // ラムダ式を名前で呼び出し println(funcMap["double"](12)) // 24 }
いろいろやってみる
無い名前を参照したりとか、返り値を超えてみたりとか。
package main var funcMap = map[string]func(int) int { "double": func(i int) int { return i * 2 } } func main() { // 無い名前を呼んでみる // println(funcMap["square"](12)) これはぬるぽ // mapに入れる funcMap["square"] = func(i int) int { return i * i } // 今度は呼べる println(funcMap["square"](12)) // 144 // funcMapで制限した型を超える範囲渡したらどうなんの println(funcMap["square"](1000000)) // -727379968 // <- オーバーフローして符号反転してるっぽいけど、動く }
いろいろやってみるその2
interfaceって指定できるの?
package main import "fmt" type Greeter interface { Greet() } // JapaneseはGreeterを満たす type Japanese struct { Name string } func (j Japanese) Greet() { fmt.Printf("こんにちは、%sです。\n", j.Name) } // AmericanはGreeterを満たす type American struct { Name string } func (a American) Greet() { fmt.Printf("Hello! I'm %s!!\n", a.Name) } var userPool = map[int]Greeter{ 1: Japanese{"otiai10"}, } func main() { userPool[1].Greet() userPool[2] = American{"Mike"} userPool[2].Greet() } // こんにちは、otiai10です。 // Hello! I'm Mike!!
お、いい感じだ。
雑感
interface使いこなしたい
DRY