如何检查是否已设置int变量?

max*_*low 1 go

让我们说我有一个变量num.

在我评估if语句之前,我需要先检查是否已设置此变量.通常我会用两种-1,0math.MaxInt32/math.MinInt32但对于这个任务,我需要检查,如果我的计划已经将其值设置.

我试过nums := nil,在我的if陈述中,我有类似的东西if nums == nil || ....

但是在创建nums变量时,我很惊讶地得到了错误cannot convert nil to type int.我怎么能实现我想做的事情?

为了说清楚:这是一个leetcode 问题而且没有输入的控制权,他们把各种数字放在里面包括math.MaxInt32,math.MinInt32

完整代码:

func thirdMax(nums []int) int {

    dict := make(map[int]int, 0)

    varmaxOne := math.MinInt32
    maxTwo := math.MinInt32
    maxThree := math.MinInt32


    for _, value := range nums {

        if value >= maxOne && dict[value] < 1 {

            maxThree = maxTwo
            maxTwo = maxOne
            maxOne = value

        }else if value >= maxTwo && dict[value] < 1{
            maxThree = maxTwo
            maxTwo = value
        } else if value >= maxThree && dict[value] < 1 {
            maxThree = value
        }

        dict[value] += 1
    }

    if maxThree == math.MinInt32 {
        return maxTwo
    }
    return maxThree

}

func max(a int, b int) int {
    if a > b {
        return a
    }
    return b
}
Run Code Online (Sandbox Code Playgroud)

测试

func TestThirdMax(t *testing.T) {
    //array := []int{2, 3, -1, -9, 11, 4, 3, 0, -100}
    //array := []int{2, 2, 3, 1}
    array := []int{1,2,-2147483648}
    //array := []int{3,2,1}
    result := thirdMax(array)

    if result != 2 {
        t.Errorf("Expected 2, but it was %d instead.", array)
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码使用math.MinInt32,但在给定输入时失败.我的想法是nil反过来并对if声明进行检查,但如上所述失败.

thr*_*eve 9

正如评论所示,Go中所有int类型的零值是0.如果0是数字的可能值,并且您需要检查它是否已分配,那么您可能希望使用附加了某些元数据的Struct类型,而不是基本类型.

像往常一样,这些问题在标准库中有先例.

看一下database/sql包的Null类型. 这些类型也可以通过实现来证明Scanner,但是您可以在需要检查原始值是否应该真正等于Null而不是它的零值时使用相同的想法.

  • @maxflow你有两个选择:指针或自定义类型. (3认同)
  • @maxflow,如果你对这种情况应用一些思考,你会得出一个(显而易见的)结论,为了跟踪变量是否已被分配给编译器和/或运行时必须以某种方式保持这一事实.这基本上意味着在某处存储一个标志值,然后在每次设置配对变量时设置它(所以我们有两个内存存储,而不是一个)或检查它是否已经初始化(因此我们有一个内存读取除了商店)… (3认同)
  • ...或者用更昂贵的方式来做 - 比如用一个(否则是"透明的")指针替换一个整数值,并在每次访问时"追逐"指针值,以便在第一个访问时(当该指针为"nil"时,实际分配该值并写入指针.现在请停下来再多想一想.基本上,您将要求编译器/运行时为所有变量支付此成本 - 即使99.9%的变量不需要这样做... (3认同)
  • “那么您可能会想要使用附加了一些元数据的 Struct 类型,而不是原始类型。” - - 严重地??所有这些只是为了检查程序是否已分配变量? (2认同)
  • ...; 现在考虑为了使对Go的内存模型(例如,整数变量不能半初始化)透明访问这样的"防护"变量,编译器/运行时需要对每次访问使用内存访问同步变量.这是一个疯狂的代价.好吧,可能不是那种疯狂的脚本语言,程序的速度预先定义为吮吸,但不是在Go,这是合理的"接近金属",并给你足够的控制内存布局和访问你的数据. (2认同)

eug*_*ioy 5

如评论中所述,您无法检查是否int已设置.

并使用math.MinInt32作为信号值如果你在输入会失败.

因此,如果您想以这种方式实现它,唯一的选择是使用指针(*int).

使用指针,您可以检查它们是否已设置,因为它们nil以您期望的值开头.

但是,当您需要使用指针和引用时,逻辑会变得更加复杂.

请参阅下面的可能实现,尝试使用您发布的相同逻辑,仅更改为使用指针.

另一种选择可能是对数组进行排序并使用已排序的元素来查找第三个元素.

游乐场链接:https://play.golang.org/p/ro_NIrDEo_s

func thirdMax(nums []int) int {

    dict := make(map[int]int, 0)

    // these will start with "nil values"
    var maxOne *int
    var maxTwo *int
    var maxThree *int


    for _, value := range nums {

        if maxOne == nil || value >= *maxOne && dict[value] < 1 {

            maxThree = maxTwo
            maxTwo = maxOne
            maxOne = new(int)
            *maxOne = value

        }else if maxTwo == nil || value >= *maxTwo && dict[value] < 1{
            maxThree = maxTwo
            maxTwo = new(int)
            *maxTwo = value
        } else if maxThree == nil || value >= *maxThree && dict[value] < 1 {
            maxThree = new(int)
            *maxThree = value
        }

        dict[value] += 1
    }

    if maxOne == nil {
        panic("does not work with empty input array!")
    }
    if maxTwo == nil {
        return *maxOne
    }
    if maxThree == nil {
        return *maxTwo
    }
    return *maxThree

}
Run Code Online (Sandbox Code Playgroud)