英文:
parsing TOML without a known structure
问题
与这个关于rust的问题类似,我想解析一个TOML文件,但是对整个TOML结构没有很强的了解。所以,我根据这个reddit的讨论尝试了以下代码:
# Configuration of Server Control 
[config]
control_server_ipaddr = "0.0.0.0"
control_server_port = 7077
[[module]]
filename = "filename_test1"
execcmd = "execcmd_test1"
[[module]]
filename = "filename_test2"
execcmd = "execcmd_test2"
package main
import (
	"fmt"
	"github.com/BurntSushi/toml"
)
type tomlConfig struct {
	Conf map[string]any
}
func check(e error) {
    if e != nil {
        panic(e)
    }
}
func main() {
	var c tomlConfig
	if _, err := toml.DecodeFile("config.toml", &c); err != nil {
		fmt.Println(err)
		return
	}
        fmt.Printf("%#v\n",c.Conf)
	for k, v := range c.Conf {
		fmt.Printf("%s\n", k)
		switch c := v.(type) {
    			case string:
        			fmt.Printf("Item %q is a string, containing %q\n", k, c)
    			case float64:
        			fmt.Printf("Looks like item %q is a number, specifically %f\n", k, c)
    			default:
        			fmt.Printf("Not sure what type item %q is, but I think it might be %T\n", k, c)
    		}
	}	
}
但是这样生成了一个空输出:
map[string]interface {}(nil)
英文:
Similar to this question for rust, I want to parse a TOML without having a strong knowledge of the entire structure of the TOML. So, my first attempt based on this reddit discussion was something like this:
# Configuration of Server Control 
[config]
control_server_ipaddr = "0.0.0.0"
control_server_port = 7077
[[module]]
filename = "filename_test1"
execcmd = "execcmd_test1"
[[module]]
filename = "filename_test2"
execcmd = "execcmd_test2"
package main
import (
	"fmt"
	"github.com/BurntSushi/toml"
)
type tomlConfig struct {
	Conf map[string]any
}
func check(e error) {
    if e != nil {
        panic(e)
    }
}
func main() {
	var c tomlConfig
	if _, err := toml.DecodeFile("config.toml", &c); err != nil {
		fmt.Println(err)
		return
	}
        fmt.Printf("%#v\n",c.Conf)
	for k, v := range c.Conf {
		fmt.Printf("%s\n", k)
		switch c := v.(type) {
    			case string:
        			fmt.Printf("Item %q is a string, containing %q\n", k, c)
    			case float64:
        			fmt.Printf("Looks like item %q is a number, specifically %f\n", k, c)
    			default:
        			fmt.Printf("Not sure what type item %q is, but I think it might be %T\n", k, c)
    		}
	}	
}
but that generated an empty output:
map[string]interface {}(nil)
答案1
得分: 1
作为一个可能的解决方案,我提供了以下代码:
package main
import (
	"os"
	"fmt"
	"github.com/BurntSushi/toml"
)
type tomlConfig struct {
	Conf map[string]interface{}
}
	
func check(e error) {
    if e != nil {
        panic(e)
    }
}
func isType(a, b interface{}) bool {
    return fmt.Sprintf("%T", a) == fmt.Sprintf("%T", b)
}
func PrintDict(k1 string, v1 interface{}) {
    fmt.Printf("Key:%s\n",k1)
    if isType(v1,  make(map[string]interface{})) {
        data := v1.(map[string]interface{})
        for k2, v2 := range data {
          PrintDict(k2, v2)
        }
    } else {
       fmt.Printf("Value:%s\n",v1)
    }
}
func main() {
	var Conf map[string]interface{}
        data, err := os.ReadFile("config.toml")
        if err != nil {
                fmt.Printf("ERROR: reading (config.toml).")
                os.Exit(1)
        }
        err=toml.Unmarshal(data, &Conf)
        for k, v := range Conf {
                PrintDict(k, v)
        }
}
对于生成的 config.toml 文件,它会输出以下内容:
Key:config
Key:control_server_ipaddr
Value:0.0.0.0
Key:control_server_port
Value:%!s(int64=7077)
Key:module
Value:[map[execcmd:execcmd_test1 filename:filename_test1] map[execcmd:execcmd_test2 filename:filename_test2]]
英文:
As a possible solution, I came up with was this below,
package main
import (
	"os"
	"fmt"
	"github.com/BurntSushi/toml"
)
type tomlConfig struct {
	Conf map[string]any
}
	
func check(e error) {
    if e != nil {
        panic(e)
    }
}
func isType(a, b interface{}) bool {
    return fmt.Sprintf("%T", a) == fmt.Sprintf("%T", b)
}
func PrintDict(k1 string, v1 interface{}) {
    fmt.Printf("Key:%s\n",k1)
    if isType(v1,  make(map[string]any)) {
        data := v1.(map[string]interface{})
        for k2, v2 := range data {
          PrintDict(k2, v2)
        }
    } else {
       fmt.Printf("Value:%s\n",v1)
    }
}
func main() {
	var Conf map[string]any
        data, err := os.ReadFile("config.toml")
        if err != nil {
                fmt.Printf("ERROR: reading (config.toml).")
                os.Exit(1)
        }
        err=toml.Unmarshal(data, &Conf)
        for k, v := range Conf {
                PrintDict(k, v)
        }
}
for the config.toml it generated the following output:
Key:config
Key:control_server_ipaddr
Value:0.0.0.0
Key:control_server_port
Value:%!s(int64=7077)
Key:module
Value:[map[execcmd:execcmd_test1 filename:filename_test1] map[execcmd:execcmd_test2 filename:filename_test2]]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论