我的项目中有以下代码:
mod := srt.PrimaryModule()
if mod != nil {
mods[mod.Name()] = mod
}
当它执行时,我得到:
PANIC: runtime error: invalid memory address or nil pointer dereference
堆栈就在第三行。 (是的,它是 mod 取消引用, map mods 是在上面一行创建的...)
那么,什么时候 nil 值不等于 nil?为什么?
srt.PrimaryModule()
返回一个接口(interface)类型,Module,带有定义的 Name() 方法返回 string。
在这种特殊情况下,srt 的类型为 StdReflectedType,它是一个接口(interface)类型,具有函数 PrimaryModule() 返回类型 模块。 srt 的实际实现是一个从其字段返回未初始化的 Module 值的结构。
更进一步,如果我这样做
reflect.ValueOf(mod)
结果是零 reflect.Value。
来自反射包文档:
ValueOf returns a new Value initialized to the concrete value stored in the interface i. ValueOf(nil) returns the zero Value
这似乎是正确的,除了上一行刚刚确定了 mod != nil。那么是什么给了?
我似乎无法在一个最小的示例中重现这一点 - 是否有任何明智的行为可能导致这些行执行此操作 - 我是否不理解关于接口(interface)值和 nil 指针的重要内容?
最佳答案
如果接口(interface)中存储了任何具体值,接口(interface)将不会是nil。但是,接口(interface)中存储的具体值可以是一个nil指针。
比如fmt.Println(mod)输出,具体值,nil?
if mod != nil {
fmt.Println(mod)
mods[mod.Name()] = mod
}
srt.PrimaryModule() 是否返回指向 mod 的 nil 指针?如果是这样,mod.Name() 将 panic nil pointer dereference。
引用资料:
The Go Programming Language Specification : Interface types
Go Data Structures: Interfaces
Why is my nil error value not equal to nil?
此修订版代码的输出是什么?
mod := srt.PrimaryModule()
if mod != nil {
fmt.Printf("%T %v\n", mod, mod)
if mod.(Module) != nil {
fmt.Println(mod.Name())
mods[mod.Name()] = mod
}
}
关于go - 奇怪的零/非零行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33336998/
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
在Ruby1.9.3(可能还有更早的版本,不确定)中,我试图弄清楚为什么Ruby的String#split方法会给我某些结果。我得到的结果似乎与我的预期相反。这是一个例子:"abcabc".split("b")#=>["a","ca","c"]"abcabc".split("a")#=>["","bc","bc"]"abcabc".split("c")#=>["ab","ab"]在这里,第一个示例返回的正是我所期望的。但在第二个示例中,我很困惑为什么#split返回零长度字符串作为返回数组的第一个值。这是什么原因呢?这是我所期望的:"abcabc".split("a")#=>["bc"
两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio
我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。
假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje
我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject
有没有人用ruby解决这个问题:假设我们有:a=8.1999999我们想将它四舍五入为2位小数,即8.20,然后乘以1,000,000得到8,200,000我们是这样做的;(a.round(2)*1000000).to_i但是我们得到的是8199999,为什么?奇怪的是,如果我们乘以1000、100000或10000000而不是1000000,我们会得到正确的结果。有人知道为什么吗?我们正在使用ruby1.9.2并尝试使用1.9.3。谢谢! 最佳答案 每当你在计算中得到时髦的数字时使用bigdecimalrequire'bi
defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就
当我写下面的代码时:x=[1,2,3]x我得到这个输出:[1,2,3,[...]][1,2,3,[...]][1,2,3,[...]]我不应该只得到[1,2,3,[1,2,3]]吗?解释是什么? 最佳答案 这没什么奇怪的。数组的第四个元素就是数组本身,所以当你求第四个元素时,你得到的是数组,当你求第四个元素的第四个元素时,你得到的是数组,当你求第四个元素时,你得到的是数组。第四个元素的第四个元素的第四个元素的元素......你得到了数组。就这么简单。唯一有点不寻常的是Array#to_s检测到这样的递归,而不是进入无限循环,而是返回
在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol