如果我们看一下下面的代码,我们如何用从一段字符串中获取的值填充一个结构变量? https://go.dev/play/p/KkcPzr5r28w
package main
import (
"fmt"
"os"
"strings"
)
type Config struct {
Operation string
Stop string
Start string
File string
}
func ParseConfig(list []string) Config {
var c Config
for _, elem := range list {
if strings.Contains(elem, "op:") {
subList := strings.SplitAfterN(elem, ":", 2)
c.Operation = subList[1]
} else if strings.Contains(elem, "stop:") {
subList := strings.SplitAfterN(elem, ":", 2)
c.Stop = subList[1]
} else if strings.Contains(elem, "start:") {
subList := strings.SplitAfterN(elem, ":", 2)
c.Start = subList[1]
} else if strings.Contains(elem, "file:") {
subList := strings.SplitAfterN(elem, ":", 2)
c.File = subList[1]
}
}
return c
}
func main() {
c := ParseConfig(os.Args[1:])
fmt.Println(c) // {count the quick /tmp/file1.txt}
}
此程序在使用这些参数调用时不会返回正确的响应:
go run scan.go op:count start:quick stop:the file:/tmp/file1.txt
我想知道怎么了?重构代码以解决问题的最佳方法是什么?
代码的一个可能问题是您正在使用 strings.SplitAfterN 将列表的元素按“:”拆分,但此函数将在每个 pair1 的第一个子字符串中包含分隔符。例如,如果您有 op:count,它会将其拆分为 op: 和 count。这意味着您的结构字段将在开头有一个额外的冒号,这可能不是您想要的。
一个可能的解决方案是改用 strings.SplitN,这将从两个子字符串中排除分隔符2。例如,如果您有 op:count,它会将其拆分为 op 和 count。这样,您的结构字段将只有没有任何冒号的值。
代码的另一个可能问题是,在将值分配给结构字段之前,您没有从值中删除任何空格。如果您的输入列表中有空格或换行符,这可能会导致一些意外行为。例如,如果您有“文件:/tmp/file1.txt ", 它将分配 " /tmp/file1.txt " 到 c.File,这可能不是有效的文件名。
一个可能的解决方案是使用 strings.TrimSpace 在将每个值分配给您的结构字段2之前从每个值中删除任何前导或尾随空格。例如,如果您有“文件:/tmp/file1.txt ",它会在修剪后将"/tmp/file1.txt"分配给c.File。
好的,这是使用 strings.SplitN 和 strings.TrimSpace 重构代码的可能方法:
包主
进口( “调频” “操作系统” “字符串” )
类型配置结构{ 操作字符串 停止字符串 起始字符串 文件字符串 }
func ParseConfig(list []string) 配置{
var c Config
for _, elem := range list {
if strings.Contains(elem, "op:") {
subList := strings.SplitN(elem, ":", 2)
c.Operation = strings.TrimSpace(subList[1])
} else if strings.Contains(elem, "stop:") {
subList := strings.SplitN(elem, ":", 2)
c.Stop = strings.TrimSpace(subList[1])
} else if strings.Contains(elem, "start:") {
subList := strings.SplitN(elem, ":", 2)
c.Start = strings.TrimSpace(subList[1])
} else if strings.Contains(elem, "file:") {
subList := strings.SplitN(elem, ":", 2)
c.File = strings.TrimSpace(subList[1])
}
}
return c
}
函数主(){
c := ParseConfig(os.Args[1:])
fmt.Println(c) // {count quick the /tmp/file1.txt}
}