Golang中如何将变量名转换为字符串名
Golang中如何将变量名转换为字符串名 我正在为一个有些复杂的项目实现配置文件。目前,我有一个庞大的“if-then”代码块,其中来自文件的切分字符串与结构体的不同元素相关联,类似这样:
if strings.Contains(tmpStr[0], "option1"){
optionsStruct.Option1 = tmpStr[1]
}else if strings.Contains(tmpStr[0], "option2"){
optionsStruct.OptionTwo = tmpStr[1]
} // 以此类推...
我想要更简洁的方式,更接近这样:
for _, part := range splittedUpString{
varnamestring = varNameString(part)
optionsStruct.varnamestring = part
} // 或者类似这样的代码
这样,我就不会重蹈“新平均系统”梗的覆辙。我不知道如果“optionsStruct”没有匹配的元素会是什么情况。
如果我在这里完全搞错了方向,请告诉我。很可能我从一开始就完全走错了路。
更多关于Golang中如何将变量名转换为字符串名的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我记得当时想用映射(map),但我不记得为什么最终没有采用它。
更多关于Golang中如何将变量名转换为字符串名的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
也许该再给 map 一次机会了…… 
我正在构建一个分布式视频监控系统。在树莓派上运行着“眼球”进程。这些进程会将数据以“帧”结构体的形式,通过gob编码后,传递给分类器、运动检测器和后端存储进程。这些进程可以运行在树莓派上,也可以运行在其他机器上。我有一个包,它读取一个公共配置文件,用于设置不同进程监听的端口、发送端口,并提供分类器XML文件的位置等信息。
除了@skillian的建议,如果配置文件是或者可以做成标准配置格式(如YAML、TOML、JSON等),您就可以使用现有的包来为您解析。(请在pkg.go.dev上搜索。)
此外,选项变量必须是结构体吗?如果您改用map[string]string,就可以毫不费力地存储从配置文件读取器传来的配置键和值。
func main() {
fmt.Println("hello world")
}
根据你在这里展示的用例,我会这样做:Go Playground - The Go Programming Language
然而,这有点像“不稳定平衡”的解决方案:任何关于你在做什么,尤其是为什么要这么做的额外细节和上下文,几乎肯定会改变我的答案!
我选择这种显式的映射方式,是因为你将 "option2" 映射到了一个名为 OptionTwo 的字段。如果你的结构体字段名称直接映射到选项字符串,或者字段的标签包含了选项字符串名称,那么你可以使用 reflect 包来自动匹配所有内容,而无需显式地使用一个由设置函数组成的切片。我选择使用切片而不是映射,是因为如果你必须遍历每个元素来检查某个字符串是否包含键,那么使用映射就没有意义。如果你告诉我可能有成千上万甚至更多的键,那么我可能会对如何组织数据提出另一个建议。
看着你这里的代码,我在想当一个键包含 "option1option2" 时应该发生什么,但也许这种情况永远不会发生。就像我说的:有了任何额外的细节,我可能会建议一个完全不同的解决方案

我之所以提出这些,完全是因为你说过:
如果我完全搞错了方向,请告诉我。
如果你想要的只是将子字符串映射到设置字段的代码,那么这似乎是一种合理的方式,但如果你“退一步”告诉我们你为什么这样做,那么我们可能会有一个更好的答案。例如,如果这个 tmpStr 是从 JSON 解析出来的,那么我敢打赌,这可以通过一些结构体标签和一个函数调用来解决!
在Go语言中,可以通过反射(reflect)来实现将结构体字段名与字符串进行匹配。以下是一个示例实现:
package main
import (
"fmt"
"reflect"
"strings"
)
type Config struct {
Option1 string `config:"option1"`
OptionTwo string `config:"option2"`
ServerHost string `config:"server_host"`
Port int `config:"port"`
}
func SetFieldByTag(config interface{}, key, value string) error {
v := reflect.ValueOf(config).Elem()
t := v.Type()
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
tag := field.Tag.Get("config")
if tag == key {
fieldValue := v.Field(i)
switch fieldValue.Kind() {
case reflect.String:
fieldValue.SetString(value)
case reflect.Int:
// 这里需要添加类型转换和错误处理
// 简化示例,假设value是有效的int
var intVal int
fmt.Sscanf(value, "%d", &intVal)
fieldValue.SetInt(int64(intVal))
}
return nil
}
}
return fmt.Errorf("field with tag %s not found", key)
}
func main() {
config := &Config{}
// 模拟从配置文件读取的数据
configLines := []string{
"option1:value1",
"option2:value2",
"server_host:localhost",
"port:8080",
}
for _, line := range configLines {
parts := strings.Split(line, ":")
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
err := SetFieldByTag(config, key, value)
if err != nil {
fmt.Printf("Warning: %v\n", err)
}
}
}
fmt.Printf("Config: %+v\n", config)
}
另一种方法是使用map来存储配置,然后使用encoding/json或mapstructure库进行解码:
package main
import (
"fmt"
"github.com/mitchellh/mapstructure"
)
type Config struct {
Option1 string `mapstructure:"option1"`
OptionTwo string `mapstructure:"option2"`
}
func main() {
configMap := map[string]interface{}{
"option1": "value1",
"option2": "value2",
}
var config Config
err := mapstructure.Decode(configMap, &config)
if err != nil {
panic(err)
}
fmt.Printf("Config: %+v\n", config)
}
如果不想使用第三方库,可以使用标准库的encoding/json:
package main
import (
"encoding/json"
"fmt"
)
type Config struct {
Option1 string `json:"option1"`
OptionTwo string `json:"option2"`
}
func main() {
jsonStr := `{"option1": "value1", "option2": "value2"}`
var config Config
err := json.Unmarshal([]byte(jsonStr), &config)
if err != nil {
panic(err)
}
fmt.Printf("Config: %+v\n", config)
}
对于配置文件解析,也可以考虑使用viper这样的配置管理库:
package main
import (
"fmt"
"github.com/spf13/viper"
)
type Config struct {
Option1 string
OptionTwo string
}
func main() {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("fatal error config file: %w", err))
}
var config Config
err = viper.Unmarshal(&config)
if err != nil {
panic(err)
}
fmt.Printf("Config: %+v\n", config)
}
这些方法都可以避免使用大量的if-else语句,并提供更清晰、可维护的配置解析方案。

