Go 如何检查int变量是否已设置?
假设我有一个变量Go 如何检查int变量是否已设置?,go,Go,假设我有一个变量num 在计算if语句之前,我需要首先检查是否已设置了此变量。通常我会使用-1、0或math.MaxInt32/math.MinInt32,但对于此任务,我需要检查我的程序是否已设置其值 我尝试了nums:=nil,在我的if语句中,我得到了类似if nums==nil | |…… 但是当创建nums变量时,我惊讶地发现错误无法将nil转换为int类型。我怎样才能实现我想做的事 为了明确起见:这是一个leetcode,不能控制输入,他们在里面放了各种数字,包括math.MaxIn
num
在计算if
语句之前,我需要首先检查是否已设置了此变量。通常我会使用-1
、0
或math.MaxInt32/math.MinInt32
,但对于此任务,我需要检查我的程序是否已设置其值
我尝试了nums:=nil
,在我的if
语句中,我得到了类似if nums==nil | |……
但是当创建nums
变量时,我惊讶地发现错误无法将nil转换为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
}
上面的代码使用了math.MinInt32
,但输入失败。想法是使用nil
,并在if
语句中进行检查,但如上所述失败。正如注释所示,Go中所有int类型的零值都是0
。如果0
是一个可能的数字值,并且您需要检查它是否已被赋值,那么您可能希望使用附加了一些元数据的结构类型,而不是原语类型
像往常一样,对于这类问题,在标准库中也有先例
这些类型也可以通过实现Scanner
来证明,但在需要检查原语值是否真的应该等于Null而不是零值时,您可以使用相同的想法。如注释中所述,您无法检查是否设置了int
如果您在输入中得到该值,则使用math.MinInt32
作为信号值将失败
因此,如果您想以这种方式实现它,唯一的选择就是使用指针(*int
)
使用指针,您可以检查它们是否已设置,因为它们以nil
值开始,正如您所期望的那样
但是,由于需要使用指针和引用,因此实现的逻辑会变得更加复杂
请参阅下面一个可能的实现,尝试使用与您发布的相同的逻辑,只是更改为使用指针
另一种选择可能是对数组进行排序,然后使用已排序的元素查找第三个元素
游乐场连接:
func thirdMax(nums[]int)int{
dict:=make(映射[int]int,0)
//这些将以“零值”开始
var maxOne*int
var maxTwo*int
变量maxThree*int
对于u,值:=范围nums{
如果maxOne==nil | | value>=*maxOne&&dict[value]<1{
maxThree=maxTwo
max2=maxOne
maxOne=new(int)
*maxOne=值
}如果maxtow2==nil | | value>=*maxtow2&&dict[value]<1,则为else{
maxThree=maxTwo
maxTwo=新(int)
*maxTwo=值
}否则,如果maxThree==nil | | value>=*maxThree&&dict[value]<1{
maxThree=新(int)
*maxThree=值
}
dict[value]+=1
}
如果maxOne==nil{
死机(“不适用于空输入数组!”)
}
如果maxTwo==nil{
return*maxOne
}
如果maxThree==nil{
return*max2
}
return*maxThree
}
set是什么意思?非初始化变量将保留其类型的零值。整数只能保留整数值。如果要检查其他可能的状态,则需要另一种类型,可能是*int
?有趣的。那么每种类型都有自己的“零”?让我试试,是的,每种类型都有一个。是的,每种类型都有一个“零值”。对于int
来说,毫不奇怪,“零值”是0
“那么您可能希望使用附加了一些元数据的结构类型,而不是原语类型。”---真的吗??所有这些都只是为了检查程序是否分配了变量???@maxflow,如果您对这种情况进行一些思考,您会得出一个(明显的)结论,为了跟踪是否分配了变量,编译器和/或运行时必须以某种方式保持对该事实的跟踪。这基本上意味着在某个地方存储一个标志值,然后在每次设置其成对变量时设置它(因此我们有两个内存存储,而不是一个),或者检查它是否已经初始化(因此除了存储之外,我们还有一个内存读取)……或者以更昂贵的方式进行,比如用一个“透明”)指针指向堆分配的整数值,并在每次访问时“追逐”该指针值,以便在第一次访问时(当该指针为nil
)实际上,分配值和写指针。现在请停止并给出更多的思考。基本上,你会要求编译器/运行时支付所有变量的成本,即使99.9%的变量是不需要的……现在考虑一下,以便访问这种“保护”。“变量透明对于Go的内存模型(例如,整数变量不能被半初始化),编译器/运行时需要在每次访问此类变量时使用内存访问同步。这是一个疯狂的代价。嗯,在脚本语言中可能没有那么疯狂,在脚本语言中,程序的速度预先定义为糟糕,但在围棋中则没有,围棋是合理的“接近金属”,让您能够充分控制内存布局和数据访问。
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)
}
}
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
}