Idiomatic way to cast a string to any other primitive type

时间:2019-01-07 13:11:59

标签: string parsing go types

I'm trying to create a function that can cast a given string to the given reflect type.

I'm using the cast package:

package main

import (
    "fmt"
    "reflect"
    "strings"

    "github.com/spf13/cast"
)

type functions struct{}

func (f functions) Float64(v string) float64 {
    return cast.ToFloat64(v)
}

func toTarget(v string, target reflect.Kind) interface{} {
    n := strings.Title(fmt.Sprintf("%s", target))
    method := reflect.ValueOf(functions{}).MethodByName(n)
    // Call.
    return method.Call([]reflect.Value{reflect.ValueOf(v)})[0].Interface()
}

func main() {
    originalValue := "10.0"
    floatingValue := toTarget(originalValue, reflect.Float64)

    fmt.Println(floatingValue)
}

In the above example I'm keeping simple (it only works for string -> float64 conversion), but on my code, it will work for all the other primitives as well.

I prefer using this solution over a giant and ugly switch statement, but as a new go developer, I'm not sure if there is a better approach.

Thank you for your help.

1 个答案:

答案 0 :(得分:2)

您要避免的“大开关”语句已经在标准库中编写。使用fmt包可以轻松地从字符串(特别是fmt.Sscan()fmt.Sscanf()函数)中解析原始值。

fmt.Sscan()需要一个字符串值来从中解析出某些内容,并需要一个变量的地址来将解析后的值放入其中。指向变量的类型还决定了从字符串中解析出什么以及如何解析。 fmt.Sscan()将返回成功解析的值的数量,以及一个可选的错误(如果出现问题)。

一个简单的例子:

var i int
if _, err := fmt.Sscan("12", &i); err != nil {
    fmt.Println("Error:", err)
}
fmt.Println(i)

var f float32
if _, err := fmt.Sscan("12.2", &f); err != nil {
    fmt.Println("Error:", err)
}
fmt.Println(f)

输出(在Go Playground上尝试):

12
12.2

还请注意,您可以使用fmt.Sscan()一步解析多个值,例如:

var i int
var f float32

fmt.Println(fmt.Sscan("12 12.2", &i, &f))
fmt.Println(i, f)

这将打印(在Go Playground上尝试):

2 <nil>
12 12.2

第一行包含fmt.Sscan()的返回值:告诉它解析了2个值,并且没有返回错误(nil错误)。第二行包含if的解析值。

有关更多选项,请阅读:Convert string to integer type in Go?