Experimenting with Go Mobile
- Marcus Wu
- Engineering , Software
- October 30, 2023
Building an app with Go Mobile
I recently used Go Mobile to build the business logic of an app as an experiment. The result is StructEd . The Go Mobile code is public at msgpack and the Android code is at StructEd . The app itself will be on the play store .
The Go Project Structure
The mobile
folder contains some basic interfaces and definitions that help form the structure for the shape the business logic of an app should take. This is all very lightweight and only provides loose structure. The intent is that a more experienced engineer would help define codebase pattern and would guide and coach other engineers as opposed to having a rigid framework to work within.
The app
folder contains app specific needs and implementation. Any functionality not providable by Go needs an interface that would require a platform-specific implementation. An example of this is Firebase Remote Config. app/firebase/remote_config.go
defines an interface to provide a means for Go to retrieve remote config values and a method to fetch and activate the configuration itself. This definition is very basic and could be expanded on, but it is all this small app needs and would suffice for many larger applications as well.
Due to limitations in what types can be shared between Go and the target platform with Go Mobile, notice that the FetchAndActivate interface method receives a struct with a callback function defined on it rather than a direct function parameter.
Business / domain logic is kept in the logic
folder. In this case, some structures for managing array and map values are defined here. These are necessary because no map or dictionary values can be shared between Go and iOS or Android and the only array-like values allowed are byte slices ([]byte
).
The view models are kept in the viewmodel
folder. They simply define actions the UI can provide. Each action may affect state which then notifies any observers which may update the UI.
A top-level application
struct instance is also defined to make it easy for platforms to set and access components such as the router or configuration.
The Android project structure
For the most part, the Android app is a typical Jetpack Compose project. Because the project is fairly small, the organization is fairly simple with most of the composables sitting within the ui
package.
The Splash screen and Home screen do not rely much on the Go view models. The viewer / editor does rely more heavily on the Go view model, but it is wrapped within an Android ViewModel to provide more natural connectivity with Compose.
An AppConfig
class implements the Go firebase/remote_config.go
interface.
A LocalViewModelStoreOwner
allows all instances of the browser to share the same ViewModel instance for better memory management and so that changes anywhere in the heirarchy are maintained.
A custom save dialog allows a user to save to a different file format or file name as well as closing without saving or resuming browsing and editing of the file.
Conclusions
I found Go Mobile to be an effective way of keeping a separation of business / domain logic and UI. While I have not yet introduced any testing, this approach would allow for much easier testing. One could even create a CLI tool where the tool acts as a platform and is scriptable to test app flows. Thus each platform only needs to have its UI tested.
This approach can also be an effective way of developing business logic once while utilizing it on more than one platform. The result would be more parity between iOS and Android implementations and potentially faster feature iteration since the logic is implemented once instead of once per platform.
The main negatives lie with debugging. I have only just started looking into how to debug the Go logic, but it seems like it may be a bit tricky. Hopefully more to come on that.