Skip to main content

Some Go Irks and Quirks

Now that Jump Start MySQL is published, I’m taking advantage of the spare time I have on my hands while it lasts. I’ve helped organize the Syracuse PHP Users Group, reconnected with some old friends, and gave some love to Kiwi, my forever-project programming language. Moreover, I decided to rewrite Kiwi using Go as it’s one of those languages I found interesting but never had a reason to use in any serious fashion. And now that I’ve got some real experience with it, while I still find myself impressed by some of Go’s features, some things have become really annoying.

I still really like Go’s data typing; it’s static, but it feels dynamic because the compiler is smart enough to deduce a value’s type. If you write your code well then you’ll rarely see a type name outside of a function signature or struct or interface definition. It’s nice to have type safety without the verbosity (yes I’m looking at you, PHP7).

I wish := behaved slightly different, though. Instead of always an allocation, it’d be nice if it could also perform basic assignments. Then we could write code like this:

foo, bar := baz()
foo.x, fizz := quux()
But as it is now, the best we can do is:
foo, bar := baz()
var fizz MyType
foo.x, fizz = quux()
If there’s a go-ism that works around this that you know of, feel free to let me know.

The dangling comma in a list, but only when its closing brace is on a new line, is also irritating. No, it’s not a formatting issue; gofmt won’t enforce one brace placement over the other. Rather, the presence or lack of a comma is a parsing error. We can write:

{foo,
bar,
baz}
And we can write:
{foo,
bar,
baz,
}
But we can’t write:
{foo,
bar,
baz
}
Perhaps it was because I was writing my own parser at the time that this bothered me. It should be trivial to accommodate the desired pattern, especially since structs and interface definitions are brace-delimited and don’t use commas at all.

Go elides some traditional constructs, for example for handles for, foreach, and while loops, so why make and new still exist side-by-side, even when Rob Pike proposed merging them, leaves me scratching my head. &Foo{} is equivalent to new(Foo), so if there’s no need for while then there’s no need for new.

I recognize these gripes are largely syntactic, but the syntax of a language is its API. Programmers are immersed in it every day and it can have an effect on how we think about things.

Surprisingly though, and perhaps this is my biggest complaint, the tooling around Go is still immature. In the 6+ years after its release there is still no killer IDE. Code coverage can only be generated for one package at a time, not and entire project. It’s possible to script coverage for project-wide results but that’s just a hack. Debugging with GDB is brutal and I could not get Delve to work for me.

None of these irks will stop me from using Go in the future if I have the opportunity, but I’d like to suggest Go at work as the go to language (pun intended) for some of the work we do now in C. I can probably make some good technical arguments to sway our old-time C programmers, yet convincing management and the programmers fresh out of college to use Go without viable tooling is going to be a hard sell.

Comments

  1. It actually has a happy side effect:
    http://dave.cheney.net/2014/10/04/that-trailing-comma

    ReplyDelete
    Replies
    1. In that case, yes :) But if you have the brace on the same line as the last item then it becomes a 2-line fix. Gofmt has no preference on the brace placement so there's still the possibility for style variation here.

      Delete

Post a Comment

Popular posts from this blog

Writing a Minimal PSR-0 Autoloader

An excellent overview of autoloading in PHP and the PSR-0 standard was written by Hari K T over at PHPMaster.com , and it's definitely worth the read. But maybe you don't like some of the bloated, heavier autoloader offerings provided by various PHP frameworks, or maybe you just like to roll your own solutions. Is it possible to roll your own minimal loader and still be compliant? First, let's look at what PSR-0 mandates, taken directly from the standards document on GitHub : A fully-qualified namespace and class must have the following structure \<Vendor Name>\(<Namespace>\)*<Class Name> Each namespace must have a top-level namespace ("Vendor Name"). Each namespace can have as many sub-namespaces as it wishes. Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system. Each "_" character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR . The "_" character has no special ...

Safely Identify Dependencies for Chrooting

The most difficult part of setting up a chroot environment is identifying dependencies for the programs you want to copy to the jail. For example, to make cp available, not only do you need to copy its binary from /bin and any shared libraries it depends on, but the dependencies can have their own dependencies too that need to be copied. The internet suggests using ldd to list a binary’s dependencies, but that has its own problems. The man page for ldd warns not to use the script for untrusted programs because it works by setting a special environment variable and then executes the program. What’s a security-conscious systems administrator to do? The ldd man page recommends objdump as a safe alternative. objdump outputs information about an object file, including what shared libraries it links against. It doesn’t identify the dependencies’ dependencies, but it’s still a good start because it doesn’t try to execute the target file. We can overcome the dependencies of depende...

A Unicode fgetc() in PHP

In preparation for a presentation I’m giving at this month’s Syracuse PHP Users Group meeting, I found the need to read in Unicode characters in PHP one at a time. Unicode is still second-class in PHP; PHP6 failed and we have to fallback to extensions like the mbstring extension and/or libraries like Portable UTF-8 . And even with those, I didn’t see a unicode-capable fgetc() so I wrote my own. Years ago, I wrote a post describing how to read Unicode characters in C , so the logic was already familiar. As a refresher, UTF-8 is a multi-byte encoding scheme capable of representing over 2 million characters using 4 bytes or less. The first 128 characters are encoded the same as 7-bit ASCII with 0 as the most-significant bit. The other characters are encoded using multiple bytes, each byte with 1 as the most-significant bit. The bit pattern in the first byte of a multi-byte sequence tells us how many bytes are needed to represent the character. Here’s what the function looks like: f...