読者です 読者をやめる 読者になる 読者になる

DRYな備忘録

Don't Repeat Yourself.

Go言語のラムダ式のmapの中での型名【golang】【lambda】【type】

go lambda reflect

問題

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使いこなしたい

f:id:otiai10:20140524185635j:plain

DRY