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

huangapple go评论76阅读模式
英文:

How to reduce code duplication in function which converts basic types to string in Go

问题

我已经为您翻译了代码部分,如下所示:

// 当打印(指针)值时有用的小助手函数
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)函数相同的功能?

英文:

I've written a simple function in Go (1.18.1), which takes any (a.k. interface{}) type as input and returns the value as string, in case of a nil pointer, the function returns "nil"; in case the type is not supported, the function returns "?"

// 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 "?"
}

This does its job perfectly, but looking at the actual algorithm I'm irritated by the amount of code duplication, unfortunately a fallthrough doesn't work in a type switch statement (see https://stackoverflow.com/questions/11531264/why-isnt-fallthrough-allowed-in-a-type-switch).

Are there any more efficient ways (i.e. with less code duplication), to do the same thing as the above ToString(T any) function?

答案1

得分: 0

使用反射进行简化的代码:

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 "?"
	}
}

请注意,这是使用反射进行简化的代码。

英文:

Shorter code with reflect:

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 "?"
}
}

huangapple
  • 本文由 发表于 2022年5月14日 23:59:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/72241907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定