英文:
Evaluate nil values from gomobile bind
问题
在Android Java中,评估Go函数返回的nil值的正确方法是什么?
这是我尝试过的方法:
// ExportedGoFunction返回一个指向GoStruct的指针,如果失败则返回nil
public static GoStruct ExportedGoFunction() {
return null;
}
然后,我使用gomobile生成一个.aar文件:
gomobile bind -v --target=android
在我的Java代码中,我尝试将nil作为null进行评估,但它不起作用。Java代码如下:
GoStruct goStruct = GoLibrary.ExportedGoFunction();
if (goStruct != null) {
// 这个代码块不应该被执行,但实际上执行了
Log.d("GoLog", "goStruct is not null");
}
免责声明:来自Go库的其他方法运行正常。
英文:
What's the right way to evaluate nil returned values from Go functions in Android Java?
Here's what I've tried:
// ExportedGoFunction returns a pointer to a GoStruct or nil in case of fail
func ExportedGoFunction() *GoStruct {
return nil
}
Then I generate a .aar file via gomobile using:
gomobile bind -v --target=android
In my Java code I tried to evaluate nil as null but it's not working. Java Code:
GoLibrary.GoStruct goStruct = GoLibrary.ExportedGoFunction();
if (goStruct != null) {
// This block should not be executed, but it is
Log.d("GoLog", "goStruct is not null");
}
Disclaimer: Other methods from the go library work flawless
答案1
得分: 2
为了可能的将来参考,截至2015年9月,我提出了两种解决这个问题的方法。
第一种方法是在Go代码中返回一个错误,并在Java中使用try/catch捕获错误。以下是一个示例:
// ExportedGoFunction 在失败的情况下返回一个指向GoStruct的指针,否则返回nil
func ExportedGoFunction() (*GoStruct, error) {
result := myUnexportedGoStruct()
if result == nil {
return nil, errors.New("Error: GoStruct is Nil")
}
return result, nil
}
然后在Java中使用try/catch捕获错误:
try {
GoLibrary.GoStruct myStruct = GoLibrary.ExportedGoFunction();
}
catch (Exception e) {
e.printStackTrace(); // myStruct is nil
}
这种方法既符合Go的习惯用法,也符合Java的习惯用法,但即使它可以防止程序崩溃,它会导致代码中充斥着try/catch语句,并增加额外的开销。
因此,根据用户@SnoProblem的答案,我提出了一种非习惯用法的解决方法,可以正确处理空值:
// NullGoStruct 如果value为nil则返回false,否则返回true
func NullGoStruct(value *GoStruct) bool {
return (value == nil)
}
然后在Java中检查代码:
GoLibrary.GoStruct value = GoLibrary.ExportedGoFunction();
if (GoLibrary.NullGoStruct(value)) {
// 只有当value在Go中具有nil值时才执行此块
Log.d("GoLog", "value is null");
}
英文:
For possible future reference, as of 09/2015 I've come up with two ways of dealing with the problem.
The first one is to return an error from the Go code and try/catch-ing the error in Java. Here's an example:
// ExportedGoFunction returns a pointer to a GoStruct or nil in case of fail
func ExportedGoFunction() (*GoStruct, error) {
result := myUnexportedGoStruct()
if result == nil {
return nil, errors.New("Error: GoStruct is Nil")
}
return result, nil
}
And then try/catch the error in Java
try {
GoLibrary.GoStruct myStruct = GoLibrary.ExportedGoFunction();
}
catch (Exception e) {
e.printStackTrace(); // myStruct is nil
}
This approach is both idiomatic Go and Java, but even if it works on preventing the program to crash, it ends up bloating the code with try/catch statements and causing yet more overhead.
So, based on user @SnoProblem answers the non-idiomatic way of solving it and properly handle null values I came up with was:
// NullGoStruct returns false if value is nil or true otherwise
func NullGoStruct(value *GoStruct) bool {
return (value == nil)
}
And then check the code in Java like:
GoLibrary.GoStruct value = GoLibrary.ExportedGoFunction();
if (GoLibrary.NullGoStruct(value)) {
// This block is executed only if value has nil value in Go
Log.d("GoLog", "value is null");
}
1: https://stackoverflow.com/users/4638952/snoproblem "@SnoProblem"
答案2
得分: 1
在查看Go移动测试包时,看起来你需要将空值转换为相应的类型。
从SeqTest.java文件中可以看到:
public void testNilErr() throws Exception {
Testpkg.Err(null); // 返回nil,没有异常
}
编辑:还有一个非异常的例子:
byte[] got = Testpkg.BytesAppend(null, null);
assertEquals("Bytes(null+null) should match", (byte[])null, got);
got = Testpkg.BytesAppend(new byte[0], new byte[0]);
assertEquals("Bytes(empty+empty) should match", (byte[])null, got);
可能只需要这样简单的处理:
GoLibrary.GoStruct goStruct = GoLibrary.ExportedGoFunction();
if (goStruct != (GoLibrary.GoStruct)null) {
// 这个代码块不应该被执行,但实际上执行了
Log.d("GoLog", "goStruct is not null");
}
编辑:关于实用方法的建议:
你可以在库中添加一个实用函数来获取具有特定类型的nil
值。
func NullVal() *GoStruct {
return nil
}
虽然有点巧妙,但它应该比多个包装器和异常处理的开销要小。
英文:
Looking through the testing package for go mobile, it looks like you need to cast the null value to the type.
From the SeqTest.java file:
public void testNilErr() throws Exception {
Testpkg.Err(null); // returns nil, no exception
}
Edit: A non-exception example, too:
byte[] got = Testpkg.BytesAppend(null, null);
assertEquals("Bytes(null+null) should match", (byte[])null, got);
got = Testpkg.BytesAppend(new byte[0], new byte[0]);
assertEquals("Bytes(empty+empty) should match", (byte[])null, got);
It may be as simple as:
GoLibrary.GoStruct goStruct = GoLibrary.ExportedGoFunction();
if (goStruct != (GoLibrary.GoStruct)null) {
// This block should not be executed, but it is
Log.d("GoLog", "goStruct is not null");
}
EDIT: Suggestion for utility method:
You could add a utility function to the library to give you the typed nil
value.
func NullVal() *GoStruct {
return nil
}
Still a bit hacky, but it should be less overhead than multiple wrappers and exception handling.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论