Why you should use a Go backend in Flutter
Tags: go, flutter, webdev, mobile
Published: 2022-05-18 14:24:21

**Written by [Shalitha Suranga](https://blog.logrocket.com/author/shalithasuranga/)✏️**

Flutter is a popular open source framework for creating cross-platform applications for release on Android, iOS, Linux, macOS, Windows, Fuchsia, web, and others. Flutter is growing more popular every day because of its performance and inbuilt platform-independent UI widgets.

Go is a compiled, statically typed, high-performance language with a simple syntax.

Flutter and Go became popular in the developer community after Google initiated both open source projects. Nowadays, many developers choose to use Go and Flutter together. Using a Go backend for a Flutter frontend specifically brings many advantages.

In this article, we’ll discuss these advantages and verify them practically by building a full-stack application.

*   [Advantages of using a Go backend for Flutter apps](#advantages-using-go-backend-flutter-apps)
    *   [Community, popularity, and trends](#community-popularity-trends)
    *   [Go and Flutter are performance-first technologies](#go-flutter-performance-first-technologies)
    *   [Similarities in development environment](#similarities-development-environment)
    *   [Reusing Go backend logic in Flutter](#reusing-go-backend-logic-flutter)
    *   [Using Go for serving the Flutter web app](#using-go-serving-flutter-web-app)
*   [Tutorial: Building a Flutter app with a Go backend](#tutorial-building-flutter-app-go-backend)
    *   [Developing a Go RESTful backend](#developing-go-restful-backend)
    *   [Testing the Go backend](#testing-go-backend)
    *   [Creating the application frontend with Flutter](#creating-application-frontend-flutter)
    *   [Serving the Flutter web app with Go](#serving-flutter-web-app-go)
*   [Reusing Go code in the Flutter app](#reusing-go-code-flutter-app)

## Advantages of using a Go backend for Flutter apps <a name="advantages-using-go-backend-flutter-apps"></a>

Application frontends usually communicate with the server-side modules with various network communication concepts, such as REST, WebSocket, SOAP, and gRPC.

The above communication concepts are tech stack-agnostic, so the backend technology doesn’t affect the frontend and vice versa. However, Go-based backends bring numerous nontechnical and hidden benefits for Flutter frontends. Further, you can avoid time-consuming business logic rewrites by directly using Go modules in the Flutter app.

### Community, popularity, and trends <a name="community-popularity-trends"></a>

Both Go and Flutter are Google open source projects. The Google open source community backs both projects by offering free community-based developer support, contributing code, and creating resources. You can discuss your Go development problems in the official [Go mailing thread](https://groups.google.com/g/golang-nuts) and Flutter-related problems in the official [Flutter mailing list](https://groups.google.com/g/flutter-dev).

[Google released Go v1](https://go.dev/doc/go1) in 2012 and [introduced Flutter v1](https://docs.flutter.dev/development/tools/sdk/release-notes/release-notes-0.0.21-1.0.0) in 2018, but both technologies experienced rapid growth for cloud-based business applications in late 2019\. Both projects are now growing in popularity every day and come with an excellent reputation, community support, and up-to-date, Google-engineered technology.

### Go and Flutter are performance-first technologies <a name="go-flutter-performance-first-technologies"></a>

Nowadays, some developers tend to overlook application performance due to powerful computer hardware components. For example, many individuals use powerful computers and mobile devices, so hybrid apps don't show performance issues despite those apps generally performing slower than native apps. Additionally, many web developers rarely need to optimize web backend performance due to strong cloud computing infrastructure.

Both Go and Flutter projects strive to solve the primary technical problem by carefully considering performance factors.

Flutter offers near-native performance with a rendering canvas powered by [Skia](https://github.com/google/skia) and the native platform channels concept.

The Go compiler produces fast and optimized native binaries and makes Go quick and agile, similar to other modern, popular, enterprise-level programming languages like C#, Java, and JavaScript (Node.js).

A Go backend offers fast and efficient native server-side services for Flutter applications to achieve better native performance.

### Similarities in development environment <a name="similarities-development-environment"></a>

Flutter uses Dart as the cross-platform application development language. Dart and Go offer features to solve different technical problems. However, Go/Dart syntax, developer tools, and third-party libraries have considerable similarities. Therefore, the same full-stack development team can work on both backend and frontend projects without any productivity issues. Flutter developers can also get started with Go backend development comfortably thanks to Go’s minimal syntax.

Moreover, Go development tools work perfectly on all Flutter development tools’ operating systems. As a result, you can configure a productive Go development environment on your Flutter development computer.

### Reusing Go backend logic in Flutter <a name="reusing-go-backend-logic-flutter">

Sometimes we have to reuse backend code directly in a frontend application. If you use Node.js for the backend and React Native for the frontend, you can easily share common business logic by creating a JavaScript package.

However, Dart’s server-side support is still growing and is not comparable with the Go ecosystem yet, so you need to think twice before using Dart for writing the backend.

If you use C#, Java, or Node.js for developing your backend, you may have to rewrite the same existing business logic in Dart on the Flutter frontend. The [Go mobile](https://github.com/golang/mobile) project offers a way to call Go code from the platform-specific mobile development environments, i.e., Java and Android.

Therefore, we can connect Go mobile with Flutter and build an efficient way to reuse Go-based business logic.

### Using Go for serving the Flutter web app <a name="using-go-serving-flutter-web-app"></a>

As you may already know, users can access the Flutter app from a web browser with Flutter web support. But how can you serve your Flutter web app from your cloud environment? You either need to use a prebuilt static server or write one with a preferred backend language.

It’s possible to write a fast and complete static file server in Go with a few lines of code. You can even serve your Flutter web app from the Go RESTful backend without many configurations.

## Tutorial: Building a Flutter app with a Go backend <a name="tutorial-building-flutter-app-go-backend"></a>

Now that we know the benefits of using a Go backend for a Flutter application , let’s develop a Go RESTful web service and a Flutter frontend to verify the above advantages. We are going to build a full-stack product list application with a Go REST API and Flutter frontend. The Go-based RESTful web service will [return a product list in JSON format](https://blog.logrocket.com/using-json-go-guide/) and the Flutter app will display a product list by calling the web service.

We will also [convert the Flutter app into a web app](https://blog.logrocket.com/build-cross-platform-web-app-flutter/) and serve it using the same RESTful web service. Finally, I will demonstrate how to share Go code with the Flutter app by using the Go mobile project.

### Developing a Go RESTful backend <a name="developing-go-restful-backend"></a>

We are going to create a RESTful backend to produce a JSON-formatted product list. First, install the latest Go development tools if your computer doesn’t have the Go compiler. Next, create a new Go module with the following commands to get started:

```bash
mkdir go_backend
cd go_backend
go mod init go_backend
```

We need an HTTP routing library for developing RESTful web services. The [Gin web framework](https://blog.logrocket.com/gin-binding-in-go-a-tutorial-with-examples/) offers almost all HTTP-based backend development features, such as routing, JSON binding, and validation. Add the Gin framework package to the current project with the following command:

```bash
go get -u github.com/gin-gonic/gin
```

We also need to enable CORS since we are going to use Flutter web in this tutorial. Download the Gin CORS middleware package into your project with the following command:

```bash
go get github.com/gin-contrib/cors
```

Now, create a file named `main.go` and add the following code:

```go
package main
import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/cors"
)
type Product struct {
    Id int `json:"id"`
    Name string `json:"name"`
    Price int `json:"price"`
    Description string `json:"description"`
}
func productsHandler(c *gin.Context) {
    products := []Product {
        Product {100, "BassTune Headset 2.0", 200, "A headphone with a inbuilt high-quality microphone"},
        Product {101, "Fastlane Toy Car", 100, "A toy car that comes with a free HD camera"},
        Product {101, "ATV Gear Mouse", 75, "A high-quality mouse for office work and gaming"},
    }
    c.JSON(200, gin.H{
        "products": products,
    })
}
func main() {
    r := gin.Default()
    r.Use(cors.Default())
    r.GET("/products", productsHandler)
    r.Run(":5000")
}
```

The above code implements the `GET /products` endpoint for returning a JSON-formatted product list. Here we construct a static product list by creating a `Product` struct slice with the `[] Product` syntax. We use a hardcoded product list for demonstration purposes, but you can use any preferred database connection to fetch stored product details.

### Testing the Go backend <a name="testing-go-backend"></a>

Let’s test the above Go backend. First, start the web service with the following command:

```bash
go run main.go
```

The above command starts the Gin RESTful server for accepting HTTP requests from the port `5000`. You can test the product list endpoint with the well-known Postman tool, as shown below.

![Testing the Go RESTful backend with the postman tool](https://blog.logrocket.com/wp-content/uploads/2022/05/testing-go-restful-backend-postman-tool.gif)

### Creating the application frontend with Flutter <a name="creating-application-frontend-flutter"></a>

Let’s create a product list with Flutter and display data from the above Go backend. If you haven’t already installed Flutter, you can easily do so from the official Flutter binary [releases page](https://docs.flutter.dev/get-started/install).

First, create a new Flutter application with the following command:

```bash
flutter create flutter_frontend
```

Once the project is created, run it with the `flutter run` command and test it on Chrome or your mobile device to verify that everything works as expected. We need to create Dart classes for each primary JSON object to make the codebase maintainable and readable. Add the following code to the `lib/product_model.dart` file to define the product model:

```dart
class Product {
  final int id;
  final String name;
  final String description;
  final int price;

  const Product({
    required this.id,
    required this.name,
    required this.description,
    required this.price,
  });

  factory Product.fromJson(Map&lt;String, dynamic> json) {
    return Product(
      id: json['id'],
      name: json['name'],
      description: json['description'],
      price: json['price']
    );
  }
}
```

Next, we can create a Dart service to communicate with the Go backend. We will use the [Dio HTTP client library](https://pub.dev/packages/dio), so add it to your Flutter project with the following command:

```bash
flutter pub add dio
```

Now, create the product service implementation in the `lib/product_service.dart` file with the following Dart source:

```dart
import 'package:dio/dio.dart';
import 'package:flutter_frontend/product_model.dart';

class ProductService {
  final String productsURL = 'http://localhost:5000/products';
  final Dio dio = Dio();

  ProductService();

  Future<List<Product>> getProducts() async {
    late List<Product> products;
    try {
      final res = await dio.get(productsURL);

      products = res.data['products']
        .map<Product>(
          (item) => Product.fromJson(item),
        )
        .toList();
    }
    on DioError catch(e) {
      products = [];
    }

    return products;
  }
}
```

Here, we created the `getProducts` asynchronous function to get products as instances of the `Product` model by calling the Go backend via the Dio client. The above source code offers business data via a Dart service, but if you work with many HTTP endpoints [you can use the repository pattern](https://blog.logrocket.com/implementing-repository-pattern-flutter/) to organize the code better.

Finally, we can create the product list application frontend by importing the above product service. Replace the existing code in the `lib/main.dart` file with the following code:

```dart
import 'package:flutter/material.dart';
import 'package:flutter_frontend/product_service.dart';
import 'package:flutter_frontend/product_model.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final _productService = ProductService();

  @override
  Widget build(BuildContext context) {
    const title = 'Product List';

    return MaterialApp(
      title: title,
      theme: new ThemeData(scaffoldBackgroundColor: const Color(0xffdddddd)),
      home: Scaffold(
        appBar: AppBar(
          title: const Text(title),
        ),
        body: FutureBuilder<List<Product>>(
          future: _productService.getProducts(),
          builder: (context, snapshot) {
            var products = snapshot.data ?? [];

            if(!snapshot.hasData) {
              return const Center(child: CircularProgressIndicator());
            }

            return ListView.builder(
              itemCount: products.length,
              itemBuilder: (context, index) {
                var product = products[index];
                return ListTile(
                  title: Text(products[index].name),
                  subtitle: Text('#${product.id} ${product.description}'),
                  trailing: Text('\${product.price}')
                );
              },
            );
          },
        ),
      ),
    );
  }
}
```

In the above code snippet, we used the `FutureBuilder` class to display a loading animation until the frontend fetches all products from the backend. Run the application on your mobile device or Chrome by entering the `flutter run` command. Make sure to replace `localhost` with your computer’s local IP address if you are running the app on a Flutter device other than Chrome.

You will see the working product list application interface, as shown below.

![Our product list application is running in Chrome](https://blog.logrocket.com/wp-content/uploads/2022/05/product-list-application-running-chrome.png)

### Serving the Flutter web app with Go <a name="serving-flutter-web-app-go"></a>

Now we are going to expose our Flutter application as a web app via the Go backend . Then, we can access the app with any modern web browser. We can easily add static file serving support to the existing web service via the [Gin static middleware](https://github.com/gin-contrib/static). Install the static middleware package from the project directory.

```bash
go get github.com/gin-contrib/static
```

Next, add the following package import to the main Go source file.

```
"github.com/gin-contrib/static"
```

Finally, ask the Gin framework to serve static web content with the following code line:

```go
r.Use(static.Serve("/", static.LocalFile("./static", false)))
```

Make sure that the final web service source looks like this:

```go
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/cors"
    "github.com/gin-contrib/static"
)

type Product struct {
    Id int `json:"id"`
    Name string `json:"name"`
    Price int `json:"price"`
    Description string `json:"description"`
}

func productsHandler(c *gin.Context) {
    products := []Product {
        Product {100, "BassTune Headset 2.0", 200, "A headphone with a inbuilt high-quality microphone"},
        Product {101, "Fastlane Toy Car", 100, "A toy car that comes with a free HD camera"},
        Product {101, "ATV Gear Mouse", 75, "A high-quality mouse for office work and gaming"},
    }
    c.JSON(200, gin.H{
        "products": products,
    })
}

func main() {
    r := gin.Default()
    r.Use(cors.Default())
    r.Use(static.Serve("/", static.LocalFile("./static", false)))

    r.GET("/products", productsHandler)

    r.Run(":5000")
}
```

We can now build the Flutter web app to get static web resources. Enter the following command and generate Flutter web app resources:

```bash
flutter build web
```

Create a new directory named `static` inside the Golang project and copy all generated Flutter web app resources from the `./build/web` directory to the `static` directory.

Start the Go backend server and go to the `http://localhost:5000` URL from your web browser. You will see the working Flutter web application, as shown below.

![Our product list in Flutter](https://blog.logrocket.com/wp-content/uploads/2022/05/product-list-flutter.png)

You can deploy the Go project into your cloud environment with Flutter web resources by using a container system like [Docker](https://docs.docker.com/language/golang/build-images/). Then everyone can access your full-stack Flutter web app from web browsers.

## Reusing Go code in the Flutter app <a name="reusing-go-code-flutter-app"></a>

The Go mobile project offers tools to generate native Android and iOS libraries from Go source files. The Flutter project uses platform-specific host applications, aka embedders, to initialize the Flutter engine on each platform. Therefore, we can use Go modules in Flutter with the Go mobile project and Flutter platform channel APIs. This approach is helpful for developers who want to reuse Go backend code within the Flutter app without rewriting Go modules in Dart.

Now, we are going to modify the well-known Flutter demo application by displaying a random number   instead of incrementing the existing number with each tap on the floating action button. We will generate this random number via a Go module. In the following example, I will explain how to embed a Go module in an Android app. You can use a similar approach to embed Go modules in iOS apps, too.

Before you continue with the tutorial, make sure that your computer has the following components, which can be easily installed via Android Studio:

*   Android SDK
*   Android NDK
*   Clang compiler and Make

First, we need to install the Go mobile CLI with the following command:

```bash
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
```

If the `gomobile` command doesn’t work after the installation process ,  you can solve the issue by adding the Go mobile binary to the `PATH` environment variable, as shown below.

```bash
export PATH=$PATH:~/go/bin
```

Let’s create a new Go module to generate a random number. First, create a new Go project in your working directory.

```bash
mkdir gomobilelib
cd gomobilelib
go mod init gomobilelib
```

Next, create a new file named `gomobilelib.go` and add the following source code.

```go
package gomobilelib

import "math/rand"

type (
    GoMobileLib struct {}
)

func (p *GoMobileLib) RandomNumber() int {
    return rand.Intn(100);
}
```

We can generate native platform-specific libraries for each mobile operating system with Go mobile’s binding feature. Before using it, we need to install the Go mobile [bind package](https://pkg.go.dev/golang.org/x/mobile/bind).

```bash
go get golang.org/x/mobile/bind
```

Now we can generate an Android library file using the following command:

```bash
gomobile bind --target android
```

After running the above command, you can see the `gomobilelib.aar` file in the Go module directory. The .aar file contains the Go runtime libraries and the above `gomobilelib` module in platform-specific binary format for each mobile CPU architecture.

Let’s use the Android library by creating a new Flutter project. Create a new Flutter project with a Java-based host app.

```bash
flutter create gomobilefrontend -a java
```

Copy the `gomobilelib.aar` file to the `./gomobilefrontend/android/app/src/main/libs` directory. Link the newly created library with the Android host app by adding the following configuration to the `./gomobilefrontend/android/app/build.gradle` file.

```gradle
repositories {
    flatDir{
         dirs 'src/main/libs'
    }
}
dependencies {
    api(name:'gomobilelib', ext:'aar')
}
```

Next, replace the existing code in the `MainActivity.java` file with the following code:

```java
package com.example.gomobilefrontend;

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import gomobilelib.GoMobileLib;

public class MainActivity extends FlutterActivity {
  private static final String CHANNEL = "example.com/gomobilelib";

  @Override
  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {

    GoMobileLib goMobileLib = new GoMobileLib();

    super.configureFlutterEngine(flutterEngine);
      new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
        .setMethodCallHandler(
          (call, result) -> {
            if(call.method.equals("getRandomNumber")) {
              result.success(goMobileLib.randomNumber());
            }
            else {
              result.notImplemented();
            }
          }
        );
  }
}
```

The above code exposes the Android library’s `randomNumber` function as `getRandomNumber` to the Flutter app via the platform channels API. Now we can invoke `getRandomNumber` from the Flutter app to receive a new random number.

You can now create an asynchronous Dart function to call the exported Android library function. For example, the following Dart function updates the `_counter` variable with the random number generated by the Go module:

```dart
static const platform = MethodChannel('example.com/gomobilelib');
int _counter = 0;

Future<void> _getRandomNumber() async {
  int randomNumber;
  try {
    randomNumber = await platform.invokeMethod('getRandomNumber');
  } on PlatformException catch (e) {
    randomNumber = 0;
  }

  setState(() {
    _counter = randomNumber;
  });
}
```

Note that we need to use the same platform channel identifier in the Flutter app and Android host app to get everything working properly. Look at the following complete source code of the modified demo application that displays random numbers:

```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'GoMobileFlutter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter with Go Mobile'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const platform = MethodChannel('example.com/gomobilelib');
  int _counter = 0;

  Future<void> _getRandomNumber() async {
    int randomNumber;
    try {
      randomNumber = await platform.invokeMethod('getRandomNumber');
    } on PlatformException catch (e) {
      randomNumber = 0;
    }

    setState(() {
      _counter = randomNumber;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'The following number was generated by Go:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _getRandomNumber,
        tooltip: 'Get a random number',
        child: const Icon(Icons.add),
      ),
    );
  }
}
```

If you run the Android application with the above source code using the `flutter run` command, you can generate a new random number by clicking on the floating action button, as shown in the following preview.

![Our Go-powered Flutter app is now running in Android](https://blog.logrocket.com/wp-content/uploads/2022/05/go-powered-flutter-app-running-android.gif)

Similar to the above example application, you can reuse your Go modules in your Flutter applications without rewriting them in Dart. Therefore, if you select Go for writing backend web services, you can productively use the core business logic modules directly with the Flutter frontend. Learn more about platforms channels from the [official Flutter documentation](https://docs.flutter.dev/development/platform-integration/platform-channels?tab=android-channel-java-tab).

This project’s source code is available at [my GitHub repository](https://github.com/codezri/flutter-gomobile).

## Conclusion

In this article, we discussed the advantages of using Go for Flutter applications with a sample RESTful web service. Many developers use the RESTful web service pattern for modern cloud-oriented applications, but the RESTful approach doesn’t solve every technical requirement. For bidirectional asynchronous communications, for example, you may have to use the WebSockets protocol; for lightweight and high-speed streaming calls, you can consider using the gRPC protocol.

The Go package ecosystem provides packages for both WebSockets and gRPC protocols, so you can use Go to implement backends for your Flutter frontends with any preferred communication protocol.

As we discussed, Go backends bring many benefits for Flutter apps. There are many similarities in Go and Flutter development environments, and both technologies have the same popularity level and reputation, developer support, and growing package ecosystem.

---

## [LogRocket](https://logrocket.com/signup/): Full visibility into your web apps

[![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://www2.logrocket.com/react-performance-monitoring)

[LogRocket](https://logrocket.com/signup/) is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

[Try it for free](https://logrocket.com/signup/).