Go, often referred to as GoLang, is a statically typed, compiled programming language designed by Google. Known for its simplicity, concurrency support, and performance, Go is widely used in backend systems, cloud-native applications, and microservices. With its robust standard library and features like goroutines and channels, Go excels in writing scalable, efficient programs. Many developers use it to complement other languages like Java in polyglot systems. In this article we will discuss how to invoke a GoLang function from Java.
1. Dependencies
To invoke a Go function from Java, you’ll need the following dependencies:
- Java Development Kit (JDK) installed (version 11 or higher is recommended).
- Go compiler installed and configured on your system.
- Java Native Interface (JNI): For integrating native libraries with Java.
- cgo: A Go tool for creating C-compatible binaries.
- javac and java: Java compiler and runtime environment.
2. Invoking Go Function from Java
The process involves writing a Go function, compiling it into a shared library, and using JNI to invoke it from Java.
2.1 Writing the Go Function
Here’s a Go function that takes two integers as input and returns their sum:
package main
import "C"
//export AddNumbers
func AddNumbers(a, b int) int {
// This function receives two integers as input,
// computes their sum, and returns the result.
return a + b
}
// The main function is required for building the shared library,
// even though it does nothing in this case.
func main() {}
2.1.1 Code Explanation
The package main declaration defines the entry point for the Go program. This is mandatory for any Go program that needs to be compiled as an executable or shared library. In this context, it is used to compile the shared library that contains the exported function.
The import "C" statement enables interoperability between Go and C. It allows the Go program to use C syntax and conventions, which is critical for creating functions that can be exported as C-compatible symbols.
The //export AddNumbers directive tells the Go compiler to make the AddNumbers function available for external use as a C-compatible function. This is necessary for the function to be callable from Java or other languages that can interface with shared libraries.
The AddNumbers function itself takes two integer parameters, a and b, computes their sum, and returns the result. This is a simple example of a computational function that showcases how parameters can be passed and values returned.
The func main() function is required for building the shared library, even though it does not perform any operations in this case. Without a main function, the Go compiler will not create an executable or shared library. Here, it acts as a placeholder to fulfill this requirement.
2.2 Compiling Go Code into a Shared Library
Compile the Go code into a shared library using the following command:
go build -o libadd.so -buildmode=c-shared main.go
The -buildmode=c-shared flag tells the Go compiler to create a shared library (.so file) that can be loaded by other programs. The output file, libadd.so, contains the compiled Go code.
2.3 Writing the Java Code
Create a Java program to load the shared library and invoke the Go function:
public class GoInvoker {
static {
// The System.loadLibrary method loads the shared library created by Go.
// Ensure the library is in your system's library path or specify its full path.
System.loadLibrary("add"); // Load the shared library
}
// Declare a native method corresponding to the Go function.
// The method signature must match the Go function's parameters and return type.
public native int AddNumbers(int a, int b);
public static void main(String[] args) {
GoInvoker invoker = new GoInvoker();
// Call the native method and pass two integers.
int result = invoker.AddNumbers(10, 20);
// Print the result received from the Go function.
System.out.println("Result from Go Function: " + result);
}
}
2.3.1 Code Explanation
The class GoInvoker contains the logic to load the shared library and interact with the Go function. The static block (static { ... }) is executed when the class is first loaded by the JVM. Inside this block, the System.loadLibrary method is called to load the shared library named add. This library is generated from the Go code and must be available in the system’s library path, or its full path must be provided.
The native keyword is used to declare a method that is implemented in native code (in this case, Go). The method AddNumbers is defined to accept two integers as parameters and return their sum as an integer. The method signature must exactly match the Go function’s parameter types and return type for successful integration.
In the main method, an instance of the GoInvoker class is created. The AddNumbers method is then called on this instance, passing the integers 10 and 20 as arguments. This call bridges the gap between Java and Go, invoking the Go function exported in the shared library.
The result returned by the Go function is stored in the variable result. Finally, the program prints the result to the console using System.out.println. This demonstrates the successful communication between the Java program and the Go function via the shared library.
2.4 Compiling and Running the Java code
Compile the Java program using the following command:
javac GoInvoker.java
Run the Java program using:
java GoInvoker
Ensure that the shared library is in the library path (e.g., the current directory or a directory specified in LD_LIBRARY_PATH on Linux or PATH on Windows). The output of the program will be:
Result from Go Function: 30
3. Handling Complex Data Types
To handle more complex data types, such as structs, you can use C-style structures in Go and map them using JNI in Java. This approach requires serialization and deserialization between Go and Java. Let’s define a Person struct, serialize it into JSON format, and expose a function that returns this JSON string.
3.1 Exporting Structs as JSON
package main
import (
"C"
"encoding/json"
"fmt"
)
// Define a struct in Go
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
// Export a function to convert the struct to a JSON string
//export GetPersonJSON
func GetPersonJSON() *C.char {
person := Person{Name: "John Doe", Age: 30}
jsonData, err := json.Marshal(person)
if err != nil {
fmt.Println("Error marshaling data:", err)
return nil
}
return C.CString(string(jsonData))
}
// The main function is required for building the shared library
func main() {}
In this Go code:
- We define a
Personstruct withNameandAgefields. - The
GetPersonJSONfunction is exported to return the struct serialized as a JSON string using Go’sjson.Marshalfunction. - The
mainfunction is empty but required for compiling the Go program into a shared library.
The exported Go function GetPersonJSON will be called from Java to get the JSON representation of the Person struct.
3.2 Handling JSON and Invoking Go Function
In Java, we use JNI to load the shared library created from the Go code and invoke the function that returns the JSON string. Once we receive the JSON string in Java, we can parse it using a JSON library like org.json.
public class GoInvoker {
static {
// Load the Go shared library
System.loadLibrary("add"); // Make sure to adjust the library name as needed
}
// Native method to call the Go function and receive JSON string
public native String GetPersonJSON();
public static void main(String[] args) {
GoInvoker invoker = new GoInvoker();
// Call the Go function that returns a JSON string
String jsonResult = invoker.GetPersonJSON();
// Parse the JSON string in Java
try {
// Use the org.json library or another JSON parsing library
org.json.JSONObject personObject = new org.json.JSONObject(jsonResult);
String name = personObject.getString("name");
int age = personObject.getInt("age");
// Print the parsed result
System.out.println("Name: " + name);
System.out.println("Age: " + age);
} catch (Exception e) {
e.printStackTrace();
}
}
}
In this Java code:
- The
System.loadLibrarymethod loads the shared library produced by the Go code. - The
GetPersonJSONmethod is declared as anativemethod to call the Go function. - The
mainmethod callsGetPersonJSON, receives the JSON string, and parses it using theorg.jsonlibrary.
The parsed data is then printed to the console, showcasing how complex data types can be passed between Go and Java.
3.3 Compiling and Running the code
To compile and run this example, follow these steps:
- First, compile the Go code into a shared library using the following command:
go build -o libadd.so -buildmode=c-shared main.go
- Next, compile the Java code:
javac GoInvoker.java
- Finally, run the Java program:
java GoInvoker
After running the Java program, the output of the program will be:
Name: John Doe Age: 30
This confirms that the complex data (the Go struct) was correctly serialized to JSON in Go, passed to Java, and parsed successfully in Java.
4. Conclusion
Integrating Go and Java through shared libraries allows developers to harness the strengths of both languages. Go’s performance and simplicity combined with Java’s versatility provide a robust solution for modern applications.
Thank you!
We will contact you soon.
Yatin BatraDecember 19th, 2024Last Updated: December 16th, 2024

This site uses Akismet to reduce spam. Learn how your comment data is processed.