Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Programmer Technical Selection: Write Go or Java?


May 31, 2021 Article blog


Table of contents


The article comes from the public number: Architecture Headline Author: John Griffin Translator |: No

Based on his experience, the author compares the differences between Go and Java usage in detail, giving developers a pertinent reference.

To be honest, I love Java. D uring my years at Spiral Scout, I used back-end technologies such as EJB2, DB2, and Oracle to gain a lot of software development expertise. O ver the past few years, I've turned to natural language-based robotics projects involving Spring Boot, Redis, RabbitMQ, Open NLP, IBM Watson, and UIMA. The language I've chosen has always been Java, which has always been efficient and sometimes finds it interesting.

1. First encounter with Go

In early 2017, I took over a very interesting project, an automated programming system for monitoring and growing hydroponic plants. The project's original code contained a gateway that was developed using CGo to support three different systems (Windows, MacOS, and ARM).

Because I'm not familiar with Go, I learn and use it to implement functionality. B ecause the structure of the existing code base is very complex, it is even more difficult for me. P rograms developed with Go to support three different operating systems mean that maintenance needs to be deployed, tested, and run for three different systems. I n addition, the code uses a single-case design pattern, resulting in a system that is heavily interdependent, difficult to predict, and difficult to understand. Finally, I chose to use Java for the new version, but it turned out to be very ugly and confusing.

After joining Spiral Scout, I tried to stop using Java. I decided to embrace Go and use It as much as possible to develop it. I found it to be an innovative and comprehensive language that our team still uses every day in a variety of projects.

But, like any programming language, Go has its drawbacks, and I don't want to lie -- sometimes I really miss Java.

If my programming experience has taught me anything, it must be that there is no silver bullet in software development. In this article, I'll share in detail my experiences with a traditional language and a new language.

2. Simplicity

Both Go and Java are C family languages, so they have similar syntax. A s a result, Java developers can easily read Go code and vice versa. Go does not need to use a semicolon at the end of the statement ('; o nly a few exceptions. For me, Go's line separation is clearer and easier to read.

Both Go and Java use one of my favorite features, the Garbage Collector (GC), to help prevent memory leaks. U nlike C, programmers in the C family need to deal with memory leaks. Garbage collectors are a feature of automated memory management, reducing the burden on programmers.

Go's GC doesn't use the "weak generation hypothesis," but it's still doing very well and the STW (Stop-the-World) time is very short. In version 1.5, STW dropped more and was stable, while in version 1.8 it dropped below 1 millisecond.

 Programmer Technical Selection: Write Go or Java?1

Go's GC has only a few options, which are GOGC variables for setting the initial garbage collection target percentage. Java has four different garbage collectors, each with a large number of options.

Although both Java and Go are considered cross-platform, Java requires Java virtual machines (JVMs) to interpret the compiled code, which is a binary that compiles the code into the target platform. B ut I think Java is less dependent on the platform than Go, because Go needs to compile binaries for the new platform every time. F rom a test and DevOps perspective, compiling binaries on different platforms is time-consuming, and cross-platform Go compilation does not work in some cases, especially when using CGo. F or Java, you can use the same jar anywhere you have JVM installed. Go requires less RAM and does not require the installation and management of virtual machines.

reflection. J ava's reflections are easier, more popular, and more common, while Go's reflections seem more complex. J ava is an object-oriented programming language, so everything except the original type is treated as an object. If you want to use reflection, you can create a class and get the information you need from the class, as follows:

Class cls = obj.getClass();
Constructor constructor = cls.getConstructor();
Method[] methods = cls.getDeclaredFields();

This allows you to access constructors, methods, and properties, and then call or assign values to them.

Go has no class concept, and the structure contains only declared fields. Therefore, we need to use the "reflection" package to get the information we need:

type Foo struct {
  A int `tag1:"First Tag"
  tag2:"Second Tag"`
  B string
}


f := Foo{A: 10, B: "Salutations"}
fType := reflect.TypeOf(f)
switch t.Kind(fType)
    case reflect.Struct:
        for i := 0; i < t.NumField(); i++ {
          f := t.Field(i)
          // ...
        }
}

I don't think that's a big deal, but because there are no constructors for structures in Go, many of the original types have to be handled separately and pointers need to be taken into account. I n Go, we can pass pointers or values. G o's structure can use a function as a field. All of this complicates Go's reflection.

Accessibility. J ava has private, protected, and public modifiers that provide different access scopes for data, methods, and objects. G o has export/unexported like Java's public and private, but there are no modifiers. Everything that begins with a capital letter is exported, visible to other packages, and variables or functions that are not exported (lowercase) are visible only in the current package.

3. Go is very different from Java

Go is not an object-oriented programming language. G o does not have a Java-like inheritance mechanism because it does not implement traditional polymorphism through inheritance. I n fact, it has no objects, only structures. I t simulates some object-oriented properties by interfaces and by having the structure implement interfaces. I n addition, you can embed structures in structures, but internal structures cannot access the data and methods of external structures. Go uses composition instead of inheritance to combine some behaviors and data.

Go is a imperative language, and Java is a declarative language. G o doesn't rely on injection, we need to explicitly wrap everything together. T herefore, try to use things like Magic as little as possible when using Go. A ll code should be obvious to code reviewers. Go programmers should understand how Go code uses memory, file systems, and other resources.

Java requires developers to pay more attention to the business logic of the program and know how to create, filter, modify, and store data. E verything at the bottom of the system and in the database is done through configuration and annotations (e.g. through common frameworks such as Spring Boot). W e try to leave the boring things to the framework. This is convenient, but control is reversed, limiting our ability to optimize the entire process.

The order in which the variables are defined. In Java, you can define variables this way:

String name;

And in Go, you have to write this:

name string

When I first started using Go, it was also a confusing place for me.

4. Go's good side

Simple and elegant concurring. G o has a powerful concurring model called a "communication sequential process" or CSP. G o uses the n-to-m analyzer, which allows m concurresion to be performed in n system threads. Starting a concurrent routine is as simple as using one keyword from Go, such as:

go doMyWork()

This allows doMyWork() to be performed concurrently.

Communication between processes can be done by sharing memory (not recommended) and channels. W e can use as many cores as the environmental variable GOMAXPROCS defines the number of processes and bring very robust and fluid parallelity. By default, the number of processes is equal to the number of cores.

Go provides a special mode to run binaries and can detect execution conditions. In this way, we can test and prove that our program is not concurrently safe.

go run -race myapp.go

The application will run in state detection mode.

Go provides a number of basic out-of-the-box and useful features (https://golang.org/dl/), such as concurrent "sync" packages (https://golang.org/pkg/sync/). A single example of the "Once" type can be written like this:

package singleton 
import ("sync")
type singleton struct { }
var instance *singleton 
var once sync.Once 
func GetInstance() *singleton {    
  once.Do(func() {        
    instance = &singleton{}    
  })    
  return instance 
}

The sync package also provides a structure for concurrent map implementations, mutually exclusive locks, conditional variables, and WaitGroup. The atomic package (https://golang.org/pkg/sync/atomic/) supports concurrent security conversion and mathematical operations -- they are basically everything you need to write concurrent code.

pointer. P ointers give Go more control over how memory is allocated, garbage collector loads, and other performance tunings that are not possible in Java. Go is more of a low-level language than Java and supports easier, faster performance optimization.

Duck Typing. " If it walks like a duck and barks like a duck, it must be a duck." T his is the case in Go: there is no need to define whether a structure implements a given interface, as long as the structure has the same method signature as a given interface, it implements the interface. T his is useful because, as the call side of the code base, you can define any interface required by the external library structure. In Java, objects must explicitly declare which interfaces are implemented.

Performance analyzer. G o's performance analysis tools make performance issue analysis easy and easy. G o's analyzer reveals the program's memory allocation and CPU usage, and displays it in visualizations, making performance optimization easy. Java also has very performance analyzers, such as Java VisualVM, but they are more complex than Go and rely on the operation of the JVM, so the statistics they provide are related to the operation of the garbage collector.

CGO。 G o can be integrated with the C language, so you can develop applications with C snippets in your Go project. D evelopers can use CGo to create Go packages that call C code. Go provides a variety of build options for C snippets of a given platform for exclude/include.

Use the function as an argument. A Go function can be passed as a variable to another function or as a field of a structure. T his versatility is refreshing. Java 8 introduces lambda, but they are not real functions, they are just single-function objects.

Clear code style guidelines. The Go community provides many examples and instructions:

https://golang.org/doc/effective_go.html

This is also useful when a function can return multiple arguments.

package main 
import "fmt" 
func returnMany() (int, string, error) {     
  return 1, "example", nil 
}
func main() {     
  i, s, err := returnMany()     
  fmt.Printf("Returned %s %s %v", i, s, err) 
}

5. Go's bad side

There is no polymorphism (unless implemented through an interface). I n Go, if two functions in the same package have different parameters but have the same meaning, you must give them a different name. For example, this code:

func makeWorkInt(number int) {   
  fmt.Printf(“Work done number %d”, number) 
}
func makeWorkStr(title string) {   
  fmt.Printf(“Work done title %s”, title) 
}

That way, you get a lot of ways to do the same thing, but with different names and looking "ugly."

In addition, Go does not inherit polymorphism. S tructures embedded in structures know only their own methods and know nothing about the methods of the "host" structure. This is especially challenging for developers like me because we are transitioning from other OOP languages( one of the most basic concepts is inheritance) to Go.

Over time, however, I began to realize that this approach to polymorphism was just another way of thinking, and that it made sense because combinations were more reliable than inheritance and running time was variable.

Error handling. I n Go, it's up to you to decide what errors to return and how to return them, so as a developer, you're responsible for returning and passing errors. T here is no doubt that mistakes can be hidden, which is a pain point. Always remember to check for errors and pass them on, which is a bit annoying and unsafe.

Of course, you can use linter to check for hidden errors, but it's just an aid, not a real solution. I n Java, handling exceptions is much easier. If it's RuntimeException, you don't even have to add it to the signature of the function.

public void causeNullPointerException() {
  throw new NullPointerException("demo");
}
/*
...
*/
try {
  causeNullPointerException();
} catch(NullPointerException e) {
  System.out.println("Caught inside fun().");
  throw e; // rethrowing the exception
}

There are no generics. W hile generics are convenient, they add complexity and are expensive in terms of type systems and runtimes. When building Go code, you need to work with a variety of different types or use code generation.

There are no comments. A lthough you can replace some compile-time annotations with code generation, runtime annotations cannot be replaced. T his makes sense because Go is not declarative and should not contain any "magic" in the code. I like to use annotations in Java because they make the code more elegant, simple, and simple.

Annotations are useful when generating swagger files for HTTP server endpoints. C urrently, you need to manually write swagger files in Go, or provide special comments for endpoints. E very time the API changes, it's painful. However, annotations in Java are like magic, and people don't usually have to worry about how they're implemented.

Go's dependency management. I 've previously written an article about how to use vgo and dep for dependency management in Go. G o's evolution from management dependency is fraught with ups and downs. I nitially, there was no reliance on management tools other than Gopgk, and an experimental "Vendor" was later released, replaced by "vgo" and then replaced by version 1.10 of "go mod". Today, we can modify go.mod file descriptors manually or using various Go commands, such as "go get", but this also makes dependencies unstable.

Java has declarative tools such as Maven and Gradle for dependency management, as well as for building, deploying, and handling other CD/CI tasks. However, in Go, we have to customize the dependency management required for building using Makefile, docker-composes, and bash scripts, which only complicates the process and stability of the CD/CI.

The name of the package includes the managed domain name. For example:

import "github.com/pkg/errors"

This is really strange and inconvenient because you can't replace someone else's implementation with your own without modifying the project code base import.

In Java, imports typically begin with a company name, such as:

import by.spirascout.public.examples.simple.Helper;

The difference is that in Go, go get gets resources from by.spirascout.public. In Java, package names and domain names are not necessarily associated.

I hope that all issues relating to dependence management will be temporary and will be properly resolved in the future.

6. Write at the end

One of the most interesting things about Go is the code naming rules it follows -- based on code readability psychology:

https://medium.com/@egonelbre/psychology-of-code-readability-d23b1ff1258a

You can write clear and maintainable code in a variety of ways, and although Go is a multi-word programming language, the code is still clear.

Go W eb development experience has shown me that Go is fast, powerful, and easy to understand, and it's ideal for small services and concurrent processing. Java is still king for large, complex systems, complex services, and single-server systems.

Original English

https://dzone.com/articles/when-to-use-go-vs-java-one-programmers-take-on-two

Here's W3Cschool编程狮 About Programmer Technology Selection: Write Go or Java? Related to the introduction, I hope to help you.