英文:
Golang: verify that string is a valid hex string?
问题
我有一个结构体:
type Name struct {
hexID string
age uint8
}
最简单的方法是检查hexID
字段是否是有效的十六进制字符串。如果不是,则引发错误。
例如:
var n Name
n.hexID = "Hello World >)" // 不是有效的十六进制
n.hexID = "aaa12Eb9990101010101112cC" // 有效的十六进制
或者可能存在结构体tag
的地方吗?
英文:
I have a struct:
type Name struct {
hexID string
age uint8
}
What is the easiest way to check that hexID
field is a valid hex string? And if not - rise an error.
For example:
var n Name
n.hexID = "Hello World >)" // not a valid hex
n.hexID = "aaa12Eb9990101010101112cC" // valid hex
Or maybe there are somewhere struct tag
exists?
答案1
得分: 2
迭代字符串的每个字符,并检查每个字符是否是有效的十六进制数字。
func isValidHex(s string) bool {
for _, r := range s {
if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f' || r >= 'A' && r <= 'F') {
return false
}
}
return true
}
进行测试:
fmt.Println(isValidHex("Hello World >)"))
fmt.Println(isValidHex("aaa12Eb9990101010101112cC"))
输出结果(在Go Playground上尝试):
false
true
注意:你可能会尝试使用hex.DecodeString()
并检查返回的错误:如果为nil
,则表示有效。但请注意,该函数期望字符串的长度为偶数(因为它从十六进制数字生成字节,而2个十六进制数字形成一个字节)。更不用说,如果你不需要结果(作为字节切片),这种方法会更慢并且会产生不必要的垃圾(需要垃圾回收)。
另一种解决方案是使用big.Int.SetString()
:
func isValidHex(s string) bool {
_, ok := new(big.Int).SetString(s, 16)
return ok
}
这将输出相同的结果,在Go Playground上尝试。但这种方法仍然较慢并且会使用内存分配(生成垃圾)。
英文:
Iterate over the characters of the string, and check if each is a valid hex digit.
func isValidHex(s string) bool {
for _, r := range s {
if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f' || r >= 'A' && r <= 'F') {
return false
}
}
return true
}
Testing it:
fmt.Println(isValidHex("Hello World >)"))
fmt.Println(isValidHex("aaa12Eb9990101010101112cC"))
Output (try it on the Go Playground):
false
true
Note: you'd be tempted to use hex.DecodeString()
and check the returned error: if it's nil
, it's valid. But do note that this function expects that the string has even length (as it produces bytes from the hex digits, and 2 hex digits forms a byte). Not to mention that if you don't need the result (as a byte slice), this is slower and creates unnecessary garbage (for the gc to collect).
Another solution could be using big.Int.SetString()
:
func isValidHex(s string) bool {
_, ok := new(big.Int).SetString(s, 16)
return ok
}
This outputs the same, try it on the Go Playground. But this again is slower and uses memory allocations (generates garbage).
答案2
得分: 2
不同的实现具有不同的性能。例如,
func isHexRock(s string) bool {
for _, b := range []byte(s) {
if !(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F') {
return false
}
}
return true
}
func isHexIcza(s string) bool {
for _, r := range s {
if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f' || r >= 'A' && r <= 'F') {
return false
}
}
return true
}
var rxNotHex = regexp.MustCompile("[^0-9A-Fa-f]")
func isHexOjacoGlobal(s string) bool {
return !rxNotHex.MatchString(s)
}
func isHexOjacoLocal(s string) bool {
notHex, err := regexp.MatchString("[^0-9A-Fa-f]", s)
if err != nil {
panic(err)
}
return !notHex
}
一些基准测试结果:
BenchmarkRock-4 36386997 30.92 ns/op 0 B/op 0 allocs/op
BenchmarkIcza-4 21100798 52.86 ns/op 0 B/op 0 allocs/op
BenchmarkOjacoGlobal-4 5958829 209.9 ns/op 0 B/op 0 allocs/op
BenchmarkOjacoLocal-4 227672 4648 ns/op 1626 B/op 22 allocs/op
英文:
> Comment: I'm completely confused now which one to use – armaka
Different inplementations have different performance. For example,
func isHexRock(s string) bool {
for _, b := range []byte(s) {
if !(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F') {
return false
}
}
return true
}
func isHexIcza(s string) bool {
for _, r := range s {
if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f' || r >= 'A' && r <= 'F') {
return false
}
}
return true
}
var rxNotHex = regexp.MustCompile("[^0-9A-Fa-f]")
func isHexOjacoGlobal(s string) bool {
return !rxNotHex.MatchString(s)
}
func isHexOjacoLocal(s string) bool {
notHex, err := regexp.MatchString("[^0-9A-Fa-f]", s)
if err != nil {
panic(err)
}
return !notHex
}
Some benchmark results:
BenchmarkRock-4 36386997 30.92 ns/op 0 B/op 0 allocs/op
BenchmarkIcza-4 21100798 52.86 ns/op 0 B/op 0 allocs/op
BenchmarkOjacoGlobal-4 5958829 209.9 ns/op 0 B/op 0 allocs/op
BenchmarkOjacoLocal-4 227672 4648 ns/op 1626 B/op 22 allocs/op
答案3
得分: 1
这是要翻译的内容:
这个正则表达式用于判断字符串中是否包含非法的十六进制字符。
英文:
What about this one
regexp.MatchString("[^0-9A-Fa-f]", n.hexID)
True if string contains HEX illegal characters
答案4
得分: 0
我认为ParseInt方法也可以解决这个问题 -
_, err := strconv.ParseInt("deadbeef", 16, 64)
if err != nil {
fmt.Println("不是一个十六进制字符串")
} else {
fmt.Println("是一个十六进制字符串")
}
英文:
I think ParseInt method can also tackle this -
_, err := strconv.ParseInt("deadbeef", 16, 64)
if err != nil {
fmt.Println("not a hex string")
} else {
fmt.Println("it is a hex string")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论