在具有接口{}值的地图上实现String()

时间:2014-07-07 23:58:45

标签: dictionary go

如何在Go(Golang)中编写一个打印地图对象的函数?现在我有这个,但它没有编译。它返回cannot convert value (type interface {}) to type reflect.Kind: need type assertion

package main

type MyDictionary map[string]interface{}

func (d MyDictionary) String() string {
    var stringBuffer bytes.Buffer

    for key, value := range d {
        stringBuffer.WriteString(key)
        stringBuffer.WriteString(": ")

        valueType := reflect.Kind(value)

        switch valueType {
        case reflect.String:
            log.Println("string") // just to check if this block gets executed
            // Add to stringBuffer

        case reflect.Float64:
            log.Println("float64") // just to check if this block gets executed
            // Add to stringBuffer

        default:
            log.Println("Error: type was", valueType)
        }
    }

    return stringBuffer.String()
}

func main() {
    var dict MyDictionary = make(MyDictionary)
    dict["hello"] = "world"
    dict["floating"] = 10.0
    dict["whole"] = 12

    fmt.Println(dict)
}

我希望String()返回类似hello: world\nfloating: 10.0\nwhole: 12\n的字符串。然后我可以传递给fmt.Println()来打印它。在Java中,我会使用StringBuilder来实现此目的。

hello: world
floating: 10.0
whole: 12

我还尝试使用value.(type)case string:切换case float64,但后来我不知道如何将这些值写入stringBuffer

3 个答案:

答案 0 :(得分:5)

这是一个惯用的解决方案。

func (d MyDictionary) String() string {
    var buf bytes.Buffer

    for k, v := range d {
        buf.WriteString(k + ": ")

        // v is an interface{} here
        switch v := v.(type) {
        // The inner v is typed. It shadows the outer interface{} v. That's
        // the idiomatic part.
        case string:
            buf.WriteString(v + "\n") // v is a string
        case int:
            buf.WriteString(fmt.Sprintln(v)) // v is an int
        case float64:
            buf.WriteString(fmt.Sprintln(v)) // v is a float64
        }
    }

    return buf.String()
}

答案 1 :(得分:1)

您可以将其简化为此(playground):

func (d MyDictionary) String() string {
    var result string

    for key, value := range d {
        result += fmt.Sprintf("%s: %v\n", key, value)
    }

    return result
}

打印哪些:

hello: world
floating: 10
whole: 12
显然,"整体"浮点数已删除小数(如果将其设置为10.5,它将正确打印)。如果需要,那么您需要启用float并指定精度(playground):

func (d MyDictionary) String() string {
    var result string

    for key, value := range d {
        switch value.(type) {
        case float64:
            result += fmt.Sprintf("%s: %.2f\n", key, value)
        default:
            result += fmt.Sprintf("%s: %v\n", key, value)
        }
    }

    return result
}

打印哪些:

floating: 10.00
whole: 12
hello: world

答案 2 :(得分:-1)

您需要获取接口的类型,然后打开类型的类型。

valueType := reflect.TypeOf(value).Kind()

工作示例:http://play.golang.org/p/a-7SePUzZ-

package main

import (
    "bytes"
    "fmt"
    "log"
    "reflect"
)

type MyDictionary map[string]interface{}

func (d MyDictionary) String() string {
    var stringBuffer bytes.Buffer

    for key, value := range d {
        stringBuffer.WriteString(key)
        stringBuffer.WriteString(": ")

        valueType := reflect.TypeOf(value).Kind()

        switch valueType {
        case reflect.String:
            log.Println("string")
        default:
            log.Println("Type was:", valueType)
        }
    }

    return stringBuffer.String()
}

func main() {
    var dict MyDictionary = make(MyDictionary)
    dict["hello"] = "world"
    dict["floating"] = 10.0
    dict["whole"] = 12

    fmt.Println(dict)
}

输出

2009/11/10 23:00:00 string
2009/11/10 23:00:00 Type was: float64
2009/11/10 23:00:00 Type was: int
hello: floating: whole: