You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Go语言中数值与单位的拆分逻辑

不使用正则表达式拆分带单位的浮点数值

我有一组字符串值,示例如下:

values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"}

注意这些值里,数值和计量单位(比如ms、%)之间可能有空格,也可能没有,甚至可能有多个空格。我需要把每个有效值拆分成浮点数字符串和计量单位两部分。

目前我用正则表达式实现了需求,代码如下:

package main

import (
    "fmt"
    "regexp"
    "strings"
)

func main() {

    regexFloatNumbers := regexp.MustCompile(`[-]?\d[\d,]*[\.]?[\d{2}]*`)

    values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"}

    for _, value := range values {

        if regexFloatNumbers.MatchString(value) {
            floatValue := regexFloatNumbers.FindString(value)
            fmt.Printf("ORIGINAL VALUE: %q\n", value)
            fmt.Printf("UNIT: %q\n", strings.TrimSpace(regexFloatNumbers.Split(value, -1)[1]))
            fmt.Printf("FLOAT VALUE: %v\n\n", floatValue)
        } else {
            fmt.Printf("float value for %v has not being found!", value)
        }

    }
}

现在想知道有没有更简洁的实现方式,比如不用正则表达式?


无正则的实现方案

方案一:遍历字符确定拆分点

通过遍历字符串的每个字符,找到第一个不属于数值组成部分(数字、负号、小数点)的位置,以此拆分数值和单位。这种方法逻辑直观,适合自定义规则。

package main

import (
	"fmt"
	"strings"
	"unicode"
)

func splitValue(s string) (floatStr, unit string, ok bool) {
	if s == "" {
		return "", "", false
	}

	// 定位数值部分的结束位置
	splitIdx := 0
	for i, r := range s {
		if unicode.IsDigit(r) || r == '.' || r == '-' {
			splitIdx = i + 1
		} else {
			break
		}
	}

	// 处理无效数值情况(比如单独的-或.)
	if splitIdx == 0 || (splitIdx == len(s) && (s == "-" || s == ".")) {
		return "", "", false
	}

	floatStr = s[:splitIdx]
	unit = strings.TrimSpace(s[splitIdx:])

	// 可选:如果需要严格验证浮点数格式,可在此处调用strconv.ParseFloat检查floatStr
	return floatStr, unit, true
}

func main() {
	values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"}
	for _, v := range values {
		floatStr, unit, ok := splitValue(v)
		if ok {
			fmt.Printf("ORIGINAL VALUE: %q\n", v)
			fmt.Printf("UNIT: %q\n", unit)
			fmt.Printf("FLOAT VALUE: %v\n\n", floatStr)
		} else {
			fmt.Printf("float value for %v has not been found!\n", v)
		}
	}
}

方案二:借助标准库解析确定长度

利用strconv.ParseFloat的返回值,它会返回成功解析的字符数,以此精准定位数值部分的长度,同时自带数值有效性验证,逻辑更简洁可靠。

package main

import (
	"fmt"
	"strconv"
	"strings"
)

func splitValue(s string) (floatStr, unit string, ok bool) {
	s = strings.TrimSpace(s)
	if s == "" {
		return "", "", false
	}

	// 解析浮点数,获取成功解析的字符数
	_, parsedLen, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return "", "", false
	}

	floatStr = s[:parsedLen]
	unit = strings.TrimSpace(s[parsedLen:])
	return floatStr, unit, true
}

func main() {
	values := [5]string{"32.5ms", "32.5 ms", "32.5%", "32.5 %", "none"}
	for _, v := range values {
		floatStr, unit, ok := splitValue(v)
		if ok {
			fmt.Printf("ORIGINAL VALUE: %q\n", v)
			fmt.Printf("UNIT: %q\n", unit)
			fmt.Printf("FLOAT VALUE: %v\n\n", floatStr)
		} else {
			fmt.Printf("float value for %v has not been found!\n", v)
		}
	}
}

内容的提问来源于stack exchange,提问作者Possenti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:35:22