0

如果我有一个假设的结构:

type Config struct {
        Server struct {
                Host string
                Port uint16
                Timeout uint32
        }
}

我想知道主机和端口是否已设置或默认(主机为“”,端口或超时为 0)。有没有一种有效的方法来做到这一点?可能使用反射库?

另外,我假设 "" 和 0 是有效条目。

一些背景知识:我正在使用 gcfg 库来读取 INI 样式的配置文件,并想知道是否有人没有设置配置条目之一。

4

5 回答 5

2

你不能那样做。至少如果我对您的问题的理解是正确的:

您想知道例如是否有人故意设置Timeout = 0或 Timeout 是否为零,因为运行时将 Timeout 初始化为 uint32 的零值?

如果 0 存储在此 uint32 中,则您无法区分“此 0 是由某些用户通过执行设置的Timeout = 0”。和“这个 0 是在初始化结构时由运行时设置的。” 只有一个 0,这个 0 没有历史。

如果您需要区分差异,您可以更改Timeout uint32Timeout *uint32:运行时将 Timeout 初始化为 nil。如果 Timeout 不为零,则它已设置。(但这伴随着明显的零检查代价,额外的错误处理和复杂的处理。)

于 2013-05-30T09:10:48.863 回答
2

我猜你正在使用gcfg - 当我开始使用 gcfg 时,我遇到了一个非常相似的问题。我的解决方案是显式加载我的默认值,然后在它们上加载文件。

这是我的;请享用。

于 2013-05-30T19:58:18.613 回答
0

不是直接答案,而是此类问题的常见替代方法:

使用零指针来表示对未初始化结构的引用。如果您打算将结构传递给 ini 解析器,则无论如何都需要一个指针

ini 解析器(或任何使用反射的解析器)不会触及传递的指针,除非它可以解析某些内容,在这种情况下,它将创建指向类型的新实例并更改指针以定位新解析的数据结构。

http://play.golang.org/p/VkkXSuqbhi

package main

import "fmt"

type Config struct {
    Server struct {
        Host    string
        Port    uint16
        Timeout uint32
    }
}

func main() {
    var c *Config
    fmt.Println(nil == c)
    c = &Config{}
    fmt.Println(nil == c)
}
于 2013-05-30T09:22:31.047 回答
0

以下可能会增加比您想要的更多的复杂性,但是,只是为了让您了解所有选项:

Gcfg 的文档声称(我自己实际上并没有这样做)它通过 fmt.Scanner 接口提供了另一种选择。您声明的任何命名类型都可以从 INI 文件中解析,只要它实现 fmt.Scanner。

考虑到这一点,如果您愿意,可以按照以下方式做一些事情:

package main
import (
    "fmt"
    "strconv"
    "strings"
)
type OptionalInt struct {
    IsSet bool
    Value int
}

//This method definition is rather impromptu and may not be the best way to scan an int
func (optInt *OptionalInt) Scan (state fmt.ScanState, verb rune) (err error) {
    var token []byte
    var n int
    token, err = state.Token(true, nil)
    if err==nil {
        n, err = strconv.Atoi(string(token))
        if err==nil{
            optInt.Value = n
            optInt.IsSet = true
        }
    }
    return
}

type Config struct {
    Port OptionalInt
    TimeOut OptionalInt
}

func main(){
    //whatever...
}

如果你这样做,一旦你将所有数据从 INI 文件加载到你的 Config 结构中,数据将出现在一组 OptionalInt 字段中。对于每个这样的字段,您将能够检查 IsSet 以及里面的 Value。

如果这种方法对您有吸引力并且您最终尝试了它,也许您可​​以在这里发表评论,以便我们其他人知道它是如何工作的。

于 2013-05-31T02:47:06.970 回答
-1

摆脱 gcfg 并使用带有iniflags的标准 go 标志。这将允许您删除其他答案中提到的一堆骇人听闻的代码,并使您的 go 代码更加地道,同时支持开箱即用的每个配置值的默认值和描述。

于 2014-08-15T09:50:12.177 回答