gogomobile

gomobile: error return values on iOS have both NSError and boolean return


When using gobind via gomobile on iOS for an interface type, a golang function returning an error results in 2 impacts to the class in Objective C (example below):

  • The inclusion of a NSError pointer passed in
  • The method returns a boolean

I can infer how to use the NSError pointer, it's a standard objective C practice. But what value should I be returning for the boolean? TRUE on error, FALSE on success? The opposite? Something else? I can't seem to find documentation anywhere.

Example

An interface like this:

type A interface {
  DoThing(data *DataType) error
}

Get's an objective C interface like this:

@interface PackageA : NSObject <goSeqRefInterface, PackageA> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;

// Important bit is here:
- (BOOL)doThing:(data* _Nullable)DataType error:(NSError* _Nullable* _Nullable)error;
@end

Solution

  • In Objective-C, it is standard for methods that perform actions which might result in an error to return a boolean indicating success or failure, with YES for success and NO for failure, and to accept an NSError ** parameter to provide error details when necessary.

    Applying this to the code generated by gomobile and gobind, you should handle the boolean return value in the same way.

    For your Go interface:

    type A interface {
      DoThing(data *DataType) error
    }
    

    gomobile will generate an Objective-C interface like (as you mention):

    @interface PackageA : NSObject
    - (BOOL)doThingWithData:(DataType *)data error:(NSError **)error;
    @end
    
    [ Go Interface ]          [ Gomobile Binding ]        [ Obj-C Interface ]
        A (DoThing)   --->      gobind (error)     --->   PackageA (doThing:error:)
    

    An Objective-C method would then be:

    - (BOOL)doThingWithData:(DataType *)data error:(NSError **)error {
        BOOL success = your-operation(); // Attempt to do the thing
        if (!success) {
            // An error occurred, populate the error if it is not NULL
            if (error != NULL) {
                *error = [NSError errorWithDomain:@"YourErrorDomain"
                                             code:YourErrorCode
                                         userInfo:@{NSLocalizedDescriptionKey: @"An error occurred"}];
            }
            return NO; // Return NO to indicate failure
        }
        return YES; // Return YES to indicate success
    }
    

    In this pattern, gomobile follows the same conventions as Apple's Objective-C methods, which is to return a boolean value indicating the success of the operation, with an optional NSError to detail any errors that occurred.