go - 如何减少在 Go 中将基本类型转换为字符串的函数中的代码重复

我在 Go (1.18.1) 中编写了一个简单的函数,它采用 any (a.k. interface{}) 类型作为输入并将 value 作为字符串返回,如果是 nil 指针,则函数返回 "nil";如果不支持该类型,则函数返回 "?"

// small helper funcion which is usefull when printing (pointer) values
func ToString(T any) string {
    switch v := T.(type) {
    case string:
        return v
    case *string:
        if v == nil {
            return "nil"
        } else {
            return *v
        }

    case int:
        return strconv.FormatInt(int64(v), 10)
    case int8:
        return strconv.FormatInt(int64(v), 10)
    case int16:
        return strconv.FormatInt(int64(v), 10)
    case int32:
        return strconv.FormatInt(int64(v), 10)
    case int64:
        return strconv.FormatInt(v, 10)
    case float32:
        return fmt.Sprintf("%f", v)
    case float64:
        return fmt.Sprintf("%f", v)

    case *int:
        if v == nil {
            return "nil"
        }
        return strconv.FormatInt(int64(*v), 10)
    case *int8:
        if v == nil {
            return "nil"
        }
        return strconv.FormatInt(int64(*v), 10)
    case *int16:
        if v == nil {
            return "nil"
        }
        return strconv.FormatInt(int64(*v), 10)
    case *int32:
        if v == nil {
            return "nil"
        }
        return strconv.FormatInt(int64(*v), 10)
    case *int64:
        if v == nil {
            return "nil"
        }
        return strconv.FormatInt(*v, 10)
    case *float32:
        if v == nil {
            return "nil"
        }
        return fmt.Sprintf("%f", *v)
    case *float64:
        if v == nil {
            return "nil"
        }
        return fmt.Sprintf("%f", *v)

    case *bool:
        if v == nil {
            return "nil"
        }
    case bool:
        if v == true {
            return "true"
        }
        return "false"
    }
    return "?"
}

这完美地完成了它的工作,但是看看实际的算法,我对代码重复的数量感到恼火,不幸的是 fallthrough 在类型切换语句中不起作用(参见 https://stackoverflow.com/questions/11531264/why-isnt-fallthrough-allowed-in-a-type-switch)。

有没有更有效的方法(即代码重复更少)来做与上述 ToString(T any) 函数相同的事情?

回答1

带有反射的更短代码:

func ToString(x any) string {
    v := reflect.ValueOf(x)
    if v.Kind() == reflect.Ptr {
        if v.IsZero() {
            return "nil"
        }
        v = v.Elem()
    }

    switch v.Kind() {
    case reflect.String:
        return v.String()
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return strconv.FormatInt(v.Int(), 10)
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
        return strconv.FormatUint(v.Uint(), 10)
    case reflect.Float32, reflect.Float64:
        return strconv.FormatFloat(v.Float(), 'f', -1, v.Type().Bits())
    case reflect.Bool:
        return strconv.FormatBool(v.Bool())
    default:
        return "?"
    }
}

相似文章

go - 为什么 Go 找不到这些源文件?

我正在尝试在树莓派上编译https://github.com/GoogleContainerTools/kaniko.git。我不在golang中编程,但几周前我能够在同一个树莓派上成功编译kanik...

随机推荐

最新文章