Book Review: Practical Vim

Practical Vim completely changed the way that I think about this editor. After just a couple of weeks of working through the “tips” in this book, I couldn’t imagine going back to writing code with a tool that doesn’t at least emulate Vim’s main features…

Read more

Simplify Time Intervals in Java With TimeUnit

How to use Java’s TimeUnit enum for simple and clean representation of time intervals, instead of using ugly multiplication to calculate millisecond values.

Read more

Hosted Continuous Integration Options for Java Projects

Trying out Travis CI, Codeship, Drone.io, and Shippable… to see if any of them can stack up to Jenkins for continuous integration with Java projects.

Read more

Should You Use Spring Boot in Your Next Project?

Spring Boot is the next-generation system for easy setup of new Spring applications. Should you be using it in your Spring projects?

Read more
gopher-head

Go for Java Programmers: Simple Types

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditEmail this to someone

Part of the Go for Java Programmers series

Before we get into custom types, and Go’s version of object-orientation, let’s cover the simple types that come out of the box.  Full details can be found in the (surprisingly readable) language spec, but here are some highlights that are important from a Java programmer’s perspective.

Booleans

Boolean variables are declared with type bool, and their value must be one of two constants, true or false.

gopher-head

...
var isActive bool
fmt.Printf("The value of 'isActive' is %t\n", isActive)
...

The output of this program would be:

The value of 'isActive' is false

Notice that Go’s bool, just like Java’s boolean primitive, initializes to false if you don’t supply any value.  However, unlike Java, Go does not have the separate concepts of “primitive” boolean and “object” Boolean.

Go does have the concept of “a type” vs. “a pointer to that type”, and we will have to worry about null pointers when we get there (a couple of articles in the future!).  For now, rest easy that when you’re not dealing with pointers, Go types operate much like Java primitives.  Go initializes them with sane defaults, and in fact the compiler won’t allow you to initialize one with nil (i.e. Go’s version of null).

Characters and Strings

In Java, the String type is a class… there is no concept of string as a primitive type.  Once again however, the line of demarcation in Go lies between “types” and “pointers-to-types”.  When you initialize a non-pointer type directly, it is similar to working with a Java primitive.

So no more null-check hassles with strings!  If you initialize a Go string without assigning a value, then by default it is given the empty-string value (“”), rather than nil.

Unicode support

Speaking of assigning values, Go strings are quite Unicode-friendly.  The file format for Go source code is UTF-8, and so any string literals declared in your code are likewise stored as UTF-8.  Strictly speaking, a Go string is a series of bytes rather than an array of characters, and so there are edge cases in which a string variable might contain binary data (see this interesting article on the official Go blog for more detail).  However, Go strings in practice are almost always UTF-8.

gopher-head

...
fmt.Printf("Escaped represention:\t %+q\n", "世界")
fmt.Printf("UTF-8 representation:\t %s\n", "\u4e16\u754c")
...

The output of this program would be:

Escaped represention:	 "\u4e16\u754c"
UTF-8 representation:	 世界

Characters and substrings

For storing single characters, Go has the data type rune.  The rune type is an alias for int32 (covered in the next section below), and is meant for storing one Unicode character (or “code point”).  You can extract from a string single runes, or a substring, by using a zero-indexed array syntax.  The built-in Go function len(s) gives you the length of a string, to help you avoid the Go equivalent of an ArrayIndexOutOfBoundsException:

gopher-head

...
testString := "This is just a test string"

fmt.Printf("This string has %d characters\n", len(testString))
fmt.Printf("The 3rd character is: %c\n", testString[2])

lastRuneIndex := len(testString) - 1
fmt.Printf("The last character is: %c\n", testString[lastRuneIndex])

fmt.Printf("The third word in the sentence is: '%s'\n", testString[8:12])
...

The output of this program would be:

This string has 26 characters
The 3rd character is: i
The last character is: g
The third word in the sentence is: 'just'

The testString[8:12] syntax used to extract a substring will make more sense when we cover arrays and slices in an upcoming article.  For now, just know that the number on the left-hand side of the colon is the starting index for the substring, and the number on the right-hand side is the ending index.

Standard Go string functions

In Java, the String class contains numerous methods for manipulating, formatting, and searching for characters within a string.  Other core classes contain methods for converting between String and other common data types (e.g. Integer.parseInt(s)).

With Go, string is effectively a built-in primitive type, with no methods.  Therefore, the Go standard library contains two packages to fill that gap:

  • strings – Search and manipulation functions.  Supported operations including splitting and joining, finding characters and substrings, converting to lower-case or upper-case, etc.
  • strconv – Functions for converting between string and other data types or output formats.

Numeric Types

Types vary between platforms

One of the tricky things about writing in C is that data types can vary from one platform to the next.  An int might take up 32 bits on one machine, and 64 bits on another.   The Java Virtual Machine, with its “write once, run anywhere” mantra, hides this from the programmer and enforces consistent data types on all platforms.

Go is a partial throwback, combining elements of both.  If you need a particular size, then you can declare a specific numeric type (e.g. int32, int64).  However, if you merely declare a variable as int, then its size can vary from 32 to 64 bits depending on the platform.

In practice, this doesn’t matter much.  Even in the worst-case, the range of a 32-bit int is sufficient for most normal tasks.  Also, the ambiguous int is the data type used to index arrays and slices (covered in an upcoming article).  So general best practice is to:

  • use an int when you need something that’s at least 32 bit, and you don’t care if it’s bigger
  • use a more specific type only when you really need a larger or smaller number range

Altogether, these are the integer and floating-point types available in Go, along with the range of possible values for each:

Go type Java equivalent Range
int8 byte -128 to 127
int16 short -32,768 to 32,767
int32 int -32,768 to 32,767
int64 long -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
float32 float 1.40129846432481707e-45 to 3.40282346638528860e+38, positive or negative
float64 double 4.94065645841246544e-324d to 1.79769313486231570e+308d, positive or negative

Go also provides complex64 and complex128 types, for advanced math operations involving imaginary numbers.  There is no direct equivalent in the Java library, although you can find similar data types in the Apache Commons Math project.

Notice that while Go has has an ambiguous int type, which might be 32-bit or 64-bits depending on the platform, there is no generic floating-point type.  You must specify float32 or float64.  Unlike integer types, which differ only in the range of numbers that they can hold, there are subtle differences in the way that 32-bit and 64-bit floats handle precision.  This is why Java developers typically use BigDecimal for financial transactions!  Speaking of which, Go’s standard library offers equivalent types in its “math/big” package.  The Go type Int is similar to Java’s BigInteger, and Go’s Rat (short for “rational”) is similar to Java’s BigDecimal.

Go has both signed and unsigned ints

All of the integer primitives in Java are signed.  This means that if Java is your only programming language, you may not even be aware of a difference between signed and unsigned numbers!  In essence, a signed integer can be either positive or negative, wheres an unsigned integer can only be zero and up.  So with unsigned types, you can get twice the range out the same memory space, so long you don’t need to store any negative values.

Go type Range
uint8 0 to 255
uint16 0 to 65,535
uint32 0 to 4,294,967,295
uint64 0 to 18,446,744,073,709,551,615

Conclusion

There are few quirks that you have to look out for with Go’s primitive types, such as the possibility of a string containing binary data, or the fact that integers vary in size between platforms.  Overall, however, many things about Go primitives might be a breath of fresh air to you as Java programmer.  There is none of Java’s bifurcation between “primitives” and “object wrappers”, and no autoboxing.  Moreover, unless you choose to create a pointer, there are no NullPointerException‘s!

In the next article we will look at creating custom types in Go, and how Go’s type system differs from object-orientation in Java.

Practical Vim Book Cover

Book Review: Practical Vim

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditEmail this to someone

Practical Vim Book CoverI picked up a copy of Drew Neil’s Practical Vim on a lark.  With Java being my main programming language for professional use, I spend most of my time coding within an IDE.  For over a decade that was Eclipse, and more recently it’s been IntelliJ, but I would definitely not use a plain text editor for non-trivial Java development.

I do use vi/Vim when I’m forced to edit something within a shell session.  However, for the most part I’ve always just installed gedit on my Linux boxes, and Notepad++ on my Windows boxes, and rarely used either one of them.  I read “editor war” threads on Hacker News or Slashdot with some mild, detached amusement.

However, over the past couple of years I’ve been doing a lot work with Go.  That sparked an interest in text editors, since the current generation of Go IDE’s is still rather immature.  A short-lived experiment with Emacs nearly killed my pinky finger, and I’m not paying $70 for a text editor no matter how popular Sublime might be!  So that left Vim as the only option with serious plugin support for Go.  But in the 21st-century, is this 1970’s relic really a serious option?

In a word… YES!  Practical Vim completely changed the way that I think about this editor.  After just a couple of weeks of working through the “tips” in this book, I couldn’t imagine going back to writing code with a tool that doesn’t at least emulate Vim’s main features.

Vim ships with a built-in tutorial, and I was expecting Practical Vim to be nothing more than an enhanced version of that.  Start with the basic home-row movement keys, and slowly crawl toward cut-n-pasting, etc.  Amazingly enough though, Neil makes it over one-third of the way through the book before he bothers covering “fundamentals” like cursor movement… and yet the book layout decisions actually feel natural and make a lot of sense.

The very first thing covered, using the period (.) and semicolon (;) keys to repeat actions, isn’t even in the Vim tutorial at all!  It turns out that repeatability is one of Vim’s most powerful features… and after two decades of using the editor, I had no idea that it even was a feature!

The material only goes up from there.  It’s a steady barrage of little “eureka!” moments.  For example, the main thing I always hated about Vim was its modal nature.  Having to constantly stop what you’re doing, and reach over to hit the <Esc> key, felt much more clunky and disruptive than switching between keyboard and mouse.  Less than 30 pages into the book, Neil casually mentions that <Ctrl>-[ is an equivalent for <Esc>.  Why have I never seen this shouted from the rooftops, or at least mentioned before?  It’s a million times more ergonomic than <Esc>, because you can just lean the side of your left hand onto the <Ctrl> key and press [ with your right hand… one fluid motion without leaving the home row.  Suddenly, toggling modes isn’t disruptive anymore!  Overcoming this resistance to modal editing helped open my mind to all of its advantages, which are legion.

I liked the way that Practical Vim is built around 121 “tips” (what most technical books call “recipes”).  You can read the book as a linear series of chapters, but the format makes it convenient to jump around and refer back to concepts later.  It also makes it easy to internalize the material through practice.  Pick two or three “tips” to practice with each day (each tip is only a couple of pages), and within a week or two you will be shocked at how fluid and effortlessly you’re able to edit.

Due to the nature of my work, I still spend most of my time in an IDE.  However, I’ve discovered that there usually are Vim-emulation plugins available (I recommend IdeaVim for IntelliJ and other JetBrains IDE’s, and Vrapper for Eclipse).  I’ve even discovered web browser plugins, that let you use Vim-like key bindings to “click” on links and navigate between pages or tabs without leaving the keyboard (VimFx for Firefox, and Vimium for Chrome).  At this point it feels unpleasant to use data entry tools that don’t offer a “Vim-mode”… such as word processors, or this WordPress editor!

“Editor wars” are silly.  If you’ve invested significant effort into learning how to maximize productivity in your chosen editor, then by all means go forth and enjoy that editor.  However, if you haven’t ever deeply explored an editor’s features… if you’ve spent your entire career working in default “Windows Notepad”-mode without thinking about it… then I highly recommend spending a little time digging into some text editor.  Vim is an excellent and hyper-productive choice, available virtually everywhere, and Practical Vim is probably the best resource for guiding you through it.

clock

Simplify Time Intervals in Java With TimeUnit

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditEmail this to someone

In Java, like most programming languages, it is fairly common to represent and pass around time interval lengths as a number of milliseconds.  This how most hardware thinks of time under the covers, anyway.  It’s very easy to get a millisecond representation from any Java date or time object, and you can always get the current time from System.currentTimeMillis().   Therefore, milliseconds are a “universal language” that is often used in API’s, to avoid worrying about who’s using the Java 8 time library vs. pre-Java 8 libraries vs. Joda-Time or whatever.

It is common to pass time intervals as a millisecond value, but it is less common for humans to think about time at that level of granularity.  If you want a scheduled task to execute once every ten minutes, then it’s a bit awkward to think of that in terms of “once every 600,000 millseconds”.  When intervals span periods of hours, days, weeks and beyond, the mental conversion starts to become ridiculous.

The Old Pattern

Therefore, this is a common pattern that you will often see in Java code:

Java code sample without TimeUnit

...
static final long EVERY_TWO_WEEKS_IN_MILLIS =
    2 * 7 * 24 * 60 * 60 * 1000;
...

Don’t do this!  Sure, this might be more intuitive and easier to change than 1,209,600,000.  However, it’s still very unwieldy, and is simply begging for someone to accidentally introduce an “off-by-an-order-of-magnitude” bug at some point.  Those are never any fun!

Using TimeUnit Instead

Java 5 introduced a better way of doing this, with the java.util.concurrent.TimeUnit enum.  Since that’s been around for years now, I’m always surprised during code reviews to encounter developers still using the old pattern.  I suppose this is something that everyone has to deal with once in awhile, but doesn’t come up often enough to think much about it.

The TimeUnit enum has constants for MILLISECONDS, SECONDS, HOURS, etc.  Pretty much every time unit you might reasonably use, up to the DAY level of granularity.

More importantly, TimeUnit contains toXXX() methods for converting from a given time unit to another.  There is a method corresponding to each constant (e.g. toMillis(), toSeconds(), toHours(), etc).

Putting these together, you can now represent the number of milliseconds in a time interval with greater readability and less chance of bugs, by using this pattern:

Java code sample with TimeUnit

...
static final long EVERY_TWO_WEEKS_IN_MILLIS =
    TimeUnit.DAYS.toMillis(14);
...

It’s visually obviously what’s happening here, and very easy to change later if a different interval is needed.  In fact, if this value is only used in one place then there’s really no need for assigning it to a class-level constant at all.  That approach is commonly used in old-school Java, so that the name of the constant could give some visual indication of the value.  With the TimeUnit construct, this information is already apparent.

 

travis-ci

Hosted Continuous Integration Options for Java Projects

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditEmail this to someone

Recently I’ve noticed a lot of GitHub projects containing .travis.yml files, indicating that the owner uses the Travis continuous integration service to periodically build their project and run unit tests.  Out of curiosity, I thought I might I try out some of the hosted offerings that are popular in the open source and startup communities.  In my professional Java developer life, the industry standard for years now has been Jenkins (formerly Hudson prior to the fork).  Can Travis CI or any of its similar competitors, mostly geared toward Ruby, Python, and JavaScript, measure up for Java continuous integration?

For this experiment, I used my FitnessJiffy project hosted on GitHub.  FitnessJiffy is a fairly straightforward diet and exercise tracker web application.  My own take on the classic “Java Pet Store“, I’ve written multiple implementations of this app whenever I want some experience with a new framework or language.  The linked version is a Spring Boot application, and has a library dependency on my fitnessjiffy-etl project (code for importing/exporting data, and migrating between various database types).

Travis continuous integration

A flexible build process for standalone projects…

The most immediately impressive thing about Travis is its flexibility.  Much like a continuous integration version of Heroku, the infrastructure is designed to run pretty much anything you throw at it.  There is currently language-specific documentation for 17 different programming languages.  Within each, you can specify environment parameters (e.g. which JDK implementation and version to use).  You can also simply override altogether the script command that is executed (e.g. use Gradle or Ant instead of Maven).

… but lacking support for dependencies between projects

However, I quickly ran into problems with the dependency relationship between my fitnessjiffy-spring and fitnessjiffy-etl projects.  With Jenkins, it is fairly simple to configure relationships between projects, so that when one is successfully built it causes the other build to kick off.  Travis seems to lack this concept.  Each git repository is basically atomic, in its own little world.  If you want separate projects to build in a particular order, then you have to work this out yourself through scheduling or through git push commands being run in the right order.

As it turns out, the problem is even more complicated than that.  Even if you have your separate projects building in the correct order, how does the dependent project receive the dependency artifact created by the first build?  Travis pulls Maven dependencies only from Maven Central, and your custom snapshot artifacts most certainly aren’t being published there.

To work around this, I tried setting up my own custom Maven repository on Bintray.  I updated my pom.xml files, so that fitnessjiffy-etl would deploy snapshots to this repo, and fitnessjiffy-spring would look there for the dependency.  No good!  After much digging, I discovered that not only does Travis pull from Maven Central alone, but it is actually configured to ignore any additional repos that you add to your POM files.  It looks like you simply can’t have Java projects dependent on separate git repositories, unless you pursue additional tricks (which at this point I was no longer motivated to try).

**UPDATE**  It appears that Travis does support the concept of private dependencies, but only for paid customers of their travis-ci.com commercial offering (note the .com rather than the usual .org).  That’s fine, but the paid offering starts at $129 a month, dramatically more expensive than every other option discussed in this article.  There is no way to try out this feature for free while evaluating their service.

Codeship  continuous integration

A slick continuous integration interface…

My next stop was Codeship, a very slick-looking alternative.  My favorite thing about Codeship right of the bat was that there is no need for you to include a special config file in your actual repository (as Travis does by looking for a .travis.yml).  Instead, your continuous integration config happens on the continuous integration system, and your source code repository isn’t touched.  Coming from the Jenkins world, this just seems obvious to me.

Codeship doesn’t support quite as many languages as Travis does, but most of the major players are represented (and for my purposes we’re only looking at the JVM anyway).  For Java builds, Codeship gives you complete ability to script whichever command(s) you want run at build-time.

… but a bit pricey, and lacking in manual operation

Thankfully, Codeship was able to support my custom POM files.  However, there is still no native support for multi-project applications.  I had to kick off a build of fitnessjiffy-etl, wait for it to finish and deploy the artifact to my private Maven repo, and then kick off a build of fitnessjiffy-spring.  Definitely a bit clunky for the typical Java use case.  Also, there is no way to manually kick off a build.  Builds are only triggered by a push to the git repo, and so the only way to kick off an extra build on-demand is to push an empty commit.  I’ve had to deal with such workarounds in my professional life when I’m only given limited access to the continuous integration server.  However, if I’m paying for the build server, then I expect a damn “Build” button!

Although paid Codeship plans are more affordable than Travis, they start at $49/month and quickly climb to a hundred dollars and beyond for the ability to run more than one build at a time.  At that price range, it’s cheaper to run your own Jenkins setup on a beefy Digital Ocean droplet.  Not to mention more flexible and powerful for Java projects.

Drone.io continuous integration

Half the price of Codeship, and with a “Build” button…

Drone.io is somewhat comparable to Codeship.  The list of supported languages is roughly the same, and continuous integration config takes place on the continuous integration server rather than within your source code repository.  Moreover, the pricing plans are roughly half as expensive as Codeship’s, and you can launch manual builds!

It’s worth discussing the deployment capabilities of these offerings.  A typical continuous integration task is to deploy your application to a server after compiling and testing it.  Drone.io supports deployment to Heroku, as well as “beta” level deployment options to Google App Engine or dotCloud.  You can also apparently SSH into a remote box and run any custom commands that you script.  I have read some online reviews arguing that Codeship’s deployment options are a bit nicer than Drone’s.  However, it’s all academic in my case.  I run FitnessJiffy on a private DigitalOcean droplet, with my only two environments being “production” and “my laptop”.  So I prefer to handle actual deployments myself rather than deploying every successful build automatically.  However, it’s an important feature, and worth taking into consideration.

… but still no decent multi-project support

All of the previous caveats regarding multi-project dependencies still apply with Drone.io.  You may be able to hack two or more projects together using customized POM’s and a private Maven repo, but there is no true integration between the projects that Drone.io understands.  It’s all manual.  In the end, I decided to refactor my fitnessjiffy-spring application to remove the dependency on fitnessjiffy-etl.  I then chose Drone to provide continuous integration verification for both projects (if you look at their README files, you’ll see the badge logo indicating whether or not tests are passing).  So I guess you could say that Drone “wins”, at least for my open-source needs at the moment… but I would not choose to purchase a paid plan for a professional project.

Shippable continuous integration

An amazing option…

The final choice I tested was Shippable, which bills itself as the “Truly Fastest CI in the Cloud”.  It has the slickest interface out of all the competitors discussed here, even though it follows the Travis model of requiring a YAML file in your source code repository to customize the build in any meaningful way.

Shippable is aggressively generous in their pricing and in what they give away for free.  Every other provider’s free plan covers only publicly-visible source code repositories.  Shippable, however, gives you free unlimited builds for both public and private projects!  There are automated deployment options for Heroku, Amazon Elastic Beanstalk, Google App Engine, and OpenShift.  Their paid plan, supporting up to 5 concurrent builds, is only one dollar a month.  Compared to the other options in this article, that’s insane!

… if it worked

However, I fear that they’re being a bit too generous, to compete in a marketplace that is seriously over-saturated.  Despite their “fastest” monicker, in my experience the service has been ridiculously slow.  There are extreme delays before a triggered build actual executes, and I have yet to see a single build and test suite run all the way to completion.  I suspect that Shippable simply doesn’t have the horsepower to service all of the freeloaders and dollar-a-month people using their system.

Conclusion

As long as you can refactor or hack your way around cross-project dependencies, any option in this article would be sufficient for putting a nifty little “Build Passing” icon on your GitHub project’s README page.  However, it is extremely common for Java applications to have cross-project dependencies.  It is extremely common for Java applications to be deployed to a standalone servlet container or JEE app server, rather than to Heroku or another PaaS.  There are a hundred other things that aren’t thought about in the Ruby/Python/JavaScript world, but which are taken for granted in a Java shop.

Quite simply, this is what Jenkins does.  Open source personal tinkering is one thing, but if I were working on a paid professional project then there’s nothing I’ve seen so far that I would accept as a substitute.  What’s more, the pricing for hosted Jenkins solutions really isn’t out of line with the options discussed above.  A CloudBees plan for 5 to 20 developers is $60 to $100, with Jenkins priced at 42-cents per hour of build-time on top of that.  If you’re already using JIRA for project tracking, then you might like Atlassian’s Bamboo (a commercial CI offering comparable to Jenkins).  Decent hosting options are at $50 and $100 a month, priced by the number of concurrent builds rather than the number of developers.

However, having relied on third-party hosted solutions in the past, I still personally believe that there is no better option than self-hosting.  A $40 to $80 a month Digital Ocean droplet would probably be more than adequate for one-at-a-time builds of fairly complex Java applications.  If you need to get in the range of 16+ GB of memory, for enormous builds or multiple builds run in parallel, then Google Compute Engine or Amazon EC2 starts to make the most financial sense.

Yeah, when you self-host, you are on the hook for solving any problems that come up.  However, I have yet to encounter a Jenkins problem that took more than a few minutes of Google-searching to resolve.  I’ll gladly take that over the helpless feeling of being down for hours while a third-party provider resolves issues beyond my control.

 

Gopher Color

Go for Java Programmers: Formatting Rules and Surprises

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditEmail this to someone

Part of the Go for Java Programmers series

Go (Golang) is more opinionated than Java about best practices in writing code.  This avoids a lot of problems in general, and makes Go code much more uniform and easy to understand by other developers.  However, it’s a significant adjustment for many Java programmers.  In this article, we will look at the formatting of Go source code, and other surprising rules that are enforced by the compiler.

Go Has Standard Formatting

Java and other C-derived languages are fairly flexible when it comes to formatting your source code.  As long as you enclose blocks of code in curly-braces, and terminate statements with semicolons, you can generally do whatever you like.

You can put your curly braces on their own separate lines, in Linux Torvalds-style:

duke-head

for(LineItem lineItem : order.getLineItems())
{
   totalShippingWeight += lineItem.getShippingWeight();
}

… or you can use some variation of classic K&R style

if(order.getAmount() > 50)) {
   shippingCharge = 0;
} else {
   shippingCharge = 5;
}

You can indent with tabs, or with space characters.  You can write your entire application on one line, if you like.  Go crazy!

The problem with having many options is that they lead to many arguments.  Some developers get really worked up over evangelizing their preferred curly-brace style, for example.  When multiple developers on a team code with completely different styles, it makes the code more messy.  It also interferes with your ability to distinguish substantive changes from mere formatting changes when comparing revisions over time in source control.

Most large organizations deal with this by writing a style guide (see Google’s for an example), and using plugins such as Checkstyle to force all developers to use that style.

The creators of Go took this same step at the outset.  The Go compiler ships with a standard utility called gofmt, which basically serves the same function as Java’s Checkstyle.  It re-formats your source code to fit the standard Go conventions.  The gofmt utility can be called directly, or through the main Go executable (i.e. “go fmt“).  It’s also bundled with every IDE or plugin that I know of for Go, and typically re-formats your code on the fly as you type.

Standard formatting rules to note

  • Go uses the “One True Brace” variant of K&R style (“OTBS”). In classic K&R, the opening brace for a function goes on its own separate line.  For control structures (e.g. if, for, etc.), it goes on the same line as the control keyword.  With OTBS, however, an opening brace is always on the same line as any statement preceding it.  Fortunately, this is the style used by the Java standard library source code, and is probably the most common style in the Java community anyway, so you are no doubt already accustomed to seeing it.

gopher-head

func doSomething() {
   if loggingEnabled == true {
      log.Println("Starting doSomething()")
   }
   ...
}
  • It was mentioned earlier in this series in the article on Go’s control structures, but it’s worth re-iterating here.  Java allows you to omit the curly braces when the body of a control structure contains only one line (e.g. if(x > 5) return false;).  Go always requires braces around a block, even it’s just one line.  This is partly due to way in which the Go compiler implicitly adds semicolons to your code, and partly from a belief that this rule simply makes code easier to read.

Not actually rules, but conventions applied by gofmt

  • Use tabs rather than multiple spaces to indent code.
  • When you import multiple packages, gofmt will re-arrange the imports in alphabetical order.
  • We’ll talk about custom types in the next article, but note for now that when you create a type, gofmt will line up the names and types of its fields in clean columns:
type Order struct {
   orderId      uint64
   customerId   uint64
   date         Time
   lineItems    []LineItem
}

Dead Code is Not Allowed

If you use any of the major Java IDE’s, such as IntelliJ, Eclipse, or NetBeans, you are probably accustomed to seeing warnings about unused code.  If you add an import statement but then don’t use the imported class, or declare a variable or method that is never called, then the IDE will politely make note of it even though the code continues to compile.

One of the biggest shocks for Go newcomers is that unused code is not allowed.  Period.  It’s not a warning at the IDE level, it’s an error at the language level.  Your code will NOT compile if it declares something and then doesn’t use it.

Adjusting your work process

At first glance, this seems like a nice idea that encourages good clean code.  However, it does fundamentally change the way that you work.  Sure, good Java programmers clean up those “usused code” warnings before committing to source control anyway.  But we typically do so at the end of a work session, just before committing.  What if those warnings weren’t allowed even during your work session?

Declare things near their use

If you continue using a typical Java work process, it will drive you crazy.  It is common to declare a lot of variables up-front when you start writing a class or method, even though you haven’t written the code to use them yet.  When writing Go, you should be much more mindful about declaring variables as close as possible to their point of first use (which is generally a good coding practice anyway).

Develop in small chunks

When debugging or testing during development, you usually comment-out one or more lines of code temporarily.  In Go, if you comment-out the only line of code that uses a variable or function, then you must also comment-out it’s declaration if you want to compile.

What’s more, commenting-out code can trigger a chain reaction.  Let’s say you comment out the only line of code that uses a JSON parser.  If you want to compile, you now have to comment-out the declaration of that JSON parser.  But you initialized the parser with a file handle, that was the only of that file handle.  So now you have to comment-out the file handle, too.  Opening that file handle was the only use of the “os” package that you imported.  So now you have to comment-out that package import.  So on, and so on.

This restriction pushes you toward a style of work that is loosely similar to test-driven development (TDD).  You’ll want to develop in small chunks, being comfortable with each small chunk of code before moving on the next.  It’s a excellent coding practice, which you can carry back to your Java work as well.  However, it can be a frustrating adjustment at first.

The blank identifier as a loophole

The exception to the “no-dead-code” rule is the blank identifier.  When you assign a value to the underscore character (“_“), Go silently discards that value and does not complain about it being unused.  This is a common technique when you call a function that returns multiple results, and you don’t actually need all of the results.

if _, err := os.Stat(path); os.IsNotExist(err) {
   fmt.Printf("%s does not exist\n", path)
}

In the above canonical example from Effective Go, we’re checking to see whether a file exists.  The os.State() function returns a FileInfo type for a given file path, and an error object that will be populated if no file could be found.  In this case, we don’t actually care about the FileInfo return value.  We’re only interested in whether or not the error return type gets populated.  So we assign the first of the two return types to the underscore blank identifier, to prevent compile errors due to never using it.

Using the blank identifier in package imports

It is sometimes helpful to use the blank identifier with packages that your code imports.  This tells Go that you are importing a package only for the side-effects of initializing that package, and not because you intend to actually use it directly in your own code.

For a Java developer, this concept should be familiar from using JDBC.

duke-head

import java.sql.DriverManager;
import java.sql.Connection;

public class DatabaseExample {

   public static void main(String args[]) {
      Class.forName("org.postgresql.Driver");
      Connection connection = DriverManager.getConnection(
         "jdbc:postgresql://localhost/test",
         "postgres",
         "postgres"
      );
      ...
   }

}

With JDBC, you import the relevant standard library classes as you would anything else (lines 1 and 2).  However, you load the actual JDBC driver implementation through the special Class.forName() construct (line 7).  Whichever implementation class you’re using, you don’t actually reference it anywhere else directly in your code.

We’ll talk about database access more thoroughly in a later article, but the basics of Go’s database/sql package are very similar to JDBC.  You import the standard library’s database/sql package for direct use in your code, and you import a particular driver package only for the side-effect of loading that driver under-the-covers:

gopher-head

package main

import (
   "database/sql"
   _ "github.com/lib/pq"
)

func main() {
   db, err := sql.Open("postgres", "user=postgres password=postgres host=localhost dbname=test sslmode=disable")
   ...
}

Here, the database/sql package is actually used directly in the application’s code.  The github.com/lib/pq package is never referenced directly, it is simply loaded for the side-effect of making a PostgreSQL driver available to database/sql.  Adding the blank identifier to the import on line 5 prevents Go from complaining about the fact that it’s never directly used.

Conclusion

Go is a bit more restrictive in enforcing “best practices” compared to Java.  In many cases, this is not such a major change.  If you use Java in a large team environment, then you are probably already familiar with tools like Checkstyle enforcing a style guide adopted by an architect at your company.  The only difference with Go is that the architects of the language itself wrote the style guide up-front.

However, some unique characteristics of Go, such as the restriction on unused code, are major departures.  Adjusting to those differences will require a new level of discipline… keeping declarations close to where they are used, and working in small tight chunks of logic.  This discipline can help you with your Java coding skills as well.

In the next article we will look at data types in Go, starting with Go’s built-in primitive types and how they compare with their Java counterparts.