iOS
Using Go from iOS Apps
February 19th, 2016
The gomobile tool lets you compile your Go code so that you can call it from an iOS app. Using gomobile, you could easily share code between Android, iOS, and your server.
This article will go over how to do this using Xcode 7.2. If you do not have Xcode, you can download it from the Xcode Download Page. It is free, and also you can install apps directly on your phone without a paid developer account.
Creating an App in Xcode
Open Xcode and select Create a new Xcode project from the splash screen. Choose the type iOS->Application->Game and name it whatever you want. For Language select Objective-C and for Game Technology select OpenGL ES. Once you have the app created, run the app by selecting Product->Run. You should see the iPhone simulator pop up with two cubes orbiting each other.
Putting Go in Your iOS
The first thing to do is to get the simplest possible library running on iOS:
download
package example

func Add(x int, y int) int {
	return x + y
}
go get goroutines.com/ios-example
Setup the gomobile tool:
go get golang.org/x/mobile/cmd/gomobile
gomobile init
Compile your library into a .framework file:
go get goroutines.com/ios-example
gomobile bind -target ios goroutines.com/ios-example
This will create a file named Example.framework in the current directory. Drag that file into your Xcode project and make sure Copy items if needed is checked. Open AppDelegate.m and add the following lines:
// at the top of the file
#import <Example/Example.h>

// inside - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
NSLog(@"add: %d", GoExampleAdd(1, 2));
When you run the app, you will see this output add: 3 to the console. Now you can call all the Go code you want from iOS. Well maybe not all the code you want. There are type restrictions. Functions can return a pointer to a struct, for instance, but not the entire struct.
Drawing Triangles
NSLog() is okay, but let's draw some triangles using OpenGL.
download
var blue float32 = 0.8
var delta float32 = 0.03

func Frame() {
	// change the background color a little bit each frame
	C.glClearColor(1.0, 0.3, C.GLfloat(blue), 1.0)
	if blue+delta < 0.0 {
		delta = 0.03
	}
	if blue+delta > 1.0 {
		delta = -0.03
	}
	blue += delta

	// clear the screen to the background color
	C.glClear(C.GL_COLOR_BUFFER_BIT | C.GL_DEPTH_BUFFER_BIT)

	// draw some triangles
	C.glDrawArrays(C.GL_TRIANGLES, 0, 24)
}
go get goroutines.com/ios-triangles
Install this example and build it:
go get goroutines.com/ios-triangles
gomobile bind -target ios goroutines.com/ios-triangles
Copy Triangles.framework into your project. Make sure to remove Example.framework since multiple Go frameworks don't seem to work well together.
Replace the contents of the file GameViewController.m with this:
#import "GameViewController.h"
#import <OpenGLES/ES2/glext.h>
#import <Triangles/Triangles.h>

@implementation GameViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    if (!context) {
        NSLog(@"Failed to create ES context");
        return;
    }

    GLKView *view = (GLKView *)self.view;
    view.context = context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

    [EAGLContext setCurrentContext:context];

    GoTrianglesSetup();
}

- (BOOL)prefersStatusBarHidden {
    return YES;
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    GoTrianglesFrame();
}

@end
This sets up the OpenGL context used by the Go code. It calls GoTrianglesSetup() to setup the OpenGL state and 30 times per second it calls GoTrianglesFrame() to draw the current frame.
Run the code on your simulator or device and you should see a screen like this:
In Setup(), the Go code compiles shaders, sets the OpenGL state, and gives OpenGL a buffer of vertices. On each frame it calls Frame(), which clears the screen (to a slightly different color from the previous frame) and draws the same shape made out of a few triangles.
Xcode comes with a rather nice OpenGL debugger that is able to capture the calls from the Go code, so if you make any errors it helps a lot with finding them.
Calling Objective-C Functions from Go
When writing an iOS app, you often need to call iOS library functions that are written in Objective-C. There are some cgo features that let you do this from Go:
download
package objc

/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation -framework UIKit
#import <UIKit/UIKit.h>

void PrintIOSVersion(void) {
	NSLog(@"ios version: %@", [[UIDevice currentDevice] systemVersion]);
}
*/
import "C"

func CallPrintIOSVersion() {
	C.PrintIOSVersion()
}
go get goroutines.com/ios-objc
Calling GoObjcCallPrintIOSVersion() from your iOS app will call the C function PrintIOSVersion() which calls the Objective-C function [[UIDevice currentDevice] systemVersion].
Running Go on an Actual Phone
Running the app on an actual phone is annoying, but possible. Plug your phone into your computer. Go to Product->Destination and select your phone from the list of devices. Then select Product->Run. Xcode will tell you Failed to code sign, so click Fix Issue. It will then say Could not launch. Take out your iPhone and go to Settings->General->Device Management->(your apple id email address) and select the Trust button so that your app is given permission to launch on the phone. To run Go code on your device you will also need to set Enable Bitcode to No under the Build Settings for your app.
Building the Entire App in Go
In theory you can write the entire app in Go and compile it with the gomobile build command, but this is an experimental feature at this time and getting the code signing to work correctly can be a drag.
goroutines is a series of articles related somehow to the Go programming language
all code samples on this site are in the public domain