Go has better ecological support and a smaller binary size than Kotlin Native.

Why Use Go Mobile

Go has better ecological support and a smaller binary size than Kotlin Native.

Although the Go Mobile maintainers are suspected of running away, we have support for Apple Silicon and Catalyst through third-party Fork.

Here’s a SDK with the same NASA API as in Developing Cross-Platform Library with Kotlin Native to see how it works.

Create Go Module

You can download the completed project from gomobile-lib-demo

First define the GOPATH, I chose the golang folder in user zhoukaiwen’s directory.

1
export GOPATH=/Users/zhoukaiwen/golang

Find a place outside of GOPATH and create the module folder.

1
2
3
mkdir go_lib_demo
cd go_lib_demo
go mod init Hello

Edit go.mod to add a better HTTP library resty dependency, and a third-party gomobile github.com/ydnar/gomobile that addresses Catalyst and Apple Silicon.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
module Hello

go 1.16

require (
    github.com/go-resty/resty/v2 v2.6.0
    golang.org/x/mobile v0.0.0-20210614202936-7c8f154d1008 // indirect
)

replace golang.org/x/mobile v0.0.0-20210614202936-7c8f154d1008 => github.com/ydnar/gomobile v0.0.0-20210301201239-fb6ffafc9ef9

Get Dependencies

1
2
3
go get github.com/go-resty/resty/v2
go get golang.org/x/mobile/cmd/gomobile
go get golang.org/x/mobile/bind

Initialize gomobile

1
gomobile init

Create API

Use NASA’s API to get the JSON data for Astronomy Picture of the Day.

1
https://api.nasa.gov/planetary/apod?api_key={API_KEY}

src/hello/Nasa.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package hello

import (
    "encoding/json"
    "fmt"

    "github.com/go-resty/resty/v2"
)

type APOD struct {
    Date           string `json:"date"`
    Explanation    string `json:"explanation"`
    HDurl          string `json:"hdurl"`
    MediaType      string `json:"media_type"`
    ServiceVersion string `json:"service_version"`
    Title          string `json:"title"`
    Url            string `json:"url"`
}

type NasaPath string

const (
    nasaBaseURL NasaPath = "https://api.nasa.gov"
)

var (
    apodPath NasaPath = "/planetary/apod"
)

func (m NasaPath) fullPath() string {
    return fmt.Sprint(nasaBaseURL + m)
}

type NasaClient struct {
    ApiKey string
}

func (nasaClient *NasaClient) GetAPOD() (*APOD, error) {
    url := apodPath.fullPath()

    client := resty.New()

    resp, err := client.R().
        SetQueryParams(map[string]string{
            "api_key": nasaClient.ApiKey,
        }).
        Get(url)

    if err != nil {
        return nil, err
    }

    var apod APOD
    if err := json.Unmarshal([]byte(resp.Body()), &apod); err != nil {
        return nil, err
    }

    return &apod, nil
}

Compile out the xcframework

1
gomobile bind -target ios ./src/hello 

Create Swift Package

In the same way as Developing Cross-Platform Libraries with Kotlin Native, you can go to go_lib_swift_package_demo to see the completed project.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import PackageDescription

let package = Package(
    name: "go_lib_swift_package_demo",
    products: [
        .library(
            name: "go_lib_swift_package_demo",
            targets: ["go_lib_swift_package_demo", "HappyNasa"]),
    ],
    targets: [
        .target(
            name: "go_lib_swift_package_demo",
            dependencies: []),
        .binaryTarget(
                    name: "HappyNasa",
                    path: "Sources/hello.xcframework"),
        .testTarget(
            name: "go_lib_swift_package_demoTests",
            dependencies: ["go_lib_swift_package_demo"]),
    ]
)

Use in iOS

You can check out the completed project at go_lib_ios_demo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import UIKit
import Hello

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let client = HelloNasaClient()
        client.apiKey = "{API_KEY}"

        do {
            let apod = try client.getAPOD()
            print(apod.title)
            print(apod.explanation)
        } catch let error {
            print(error.localizedDescription)
        }
    }
}

Summary

Compared to Kotlin Native, Go compiles a much smaller SDK, but unfortunately go func is not available in Go Mobile. If you use go func in a function, it will be automatically removed after compilation.