First Impressions: Go (GoLang) 30 April, 2013


Go is a language that mixes old and new concepts. They use automatic memory management, but also bring back pointers and unsigned primitives. Other differences include forcing defensive style. It is a statically typed language, which helps find errors at compile time rather than waiting for a runtime error/test to catch the problem. Something else that I really like is the basic web site readiness. Go comes built with web technologies built in.

I think it's a decent language, but for me to spend more time using GO, it needs:
1 - a unique name (try to google 'go' + something)
2 - to be built out more (ex: compiler optimizations, improved web site readiness)
3 - better data integration (it feels like the only good support is for AppEngine's Datastore)

The use of GO seems to be restricted to a few startups, or to tools of better known or longer lived companies. Here's a list of some features I wanted to highlight:


Tools

The tools are still ramping up. Getting automatic building and completion on OSX seems like it was more of a pain than it should have been. The windows setup was pretty simple. It gives you an idea of what is available, but isn't quite as smooth as your standard Eclipse or VS auto-complete.


Speed

Another thing that needs some love is the compiler optimizations. I ran a couple of benchmarks. I know these are specific cases, but  for a compiled binary, it should have out preformed Java. Instead Java was at least twice as fast. The two tests I ran were SHA2 generation, and Fibonacci generation.

Built In Web Framework

There is no need for an additional or external web container. No Tomcat. No Rails. It runs it's own server and it's built in.
package main
import (
  "net/http"
)
func main() {
  http.HandleFunc("/", someHandlerFunction)
  http.ListenAndServe(":8080", nil)
}

HTML Templating

Built into the language is the ability to markup HTML with GO data:
.go file:
x, y := template.ParseFiles("some.html")
x.Execute(httpResponse, dataModel)
.html file:
<a href="someLink">{{.LinkTitle}}</a>

Multiple Return Values

func getPair() (int,int) {
  return 1,2
}

Signed & Unsigned Types

a int8 = 127b uint8 = 255

Forced Style

{}s required for one line if/for blocks. Not doing this creates a compile time error. Also, else statements must be on the same line as it's braces.
Right:
if i==0 {
  //Something
} else {
  //Something else

Wrong (no braces):
if i==0
  i = -1

Wrong (closing if/starting else braces are on different lines):
if i==0 {
}
else {
}

Unused Code

Unused code (variables/imports/etc.) will create compile time errors instead of warnings.

Initializing Statements for if Blocks

if i:=math.Max(a,b); i==5 {
  //Do something, possibly using i
} else {
  //Use i here too 
}  

Easy Small Object Construction & Assignment

Java:
class Pair {
  int a;
  int b;
  public Pair(int a, int b) {
    this.a = a;
    this.b = b;
  }
}
new Pair(1, 2);
V.S.
GO:
type Pair struct {  a int  b int}Pair{1,2}


Pointers (No Pointer Arithmetic)

func mod(i *int) {
    *i++
}
func main() {
    i:=4
    mod(&i)
    fmt.Println(i)
}

Variable Struct Construction Args

type fourPropertyStruct struct {
    a,b,c,d int
}
func main() {
    fmt.Println(fourPropertyStruct{b:4,d:7})
}


Simpler Syntax for Arrays

someArray[firstElement:lastElement-1] will return the appropriate subset of someArray[]. Missing indexes imply beginning or end ([:3] or [3:] for example)


One Form of For

Instead of a multi step for and a simple iterator based for, one form is used:
var list = []int{1, 2, 4, 8, 16}
func main() {
    for i, v := range list {
        fmt.Printf("index: %d, value: %d\n", i, v)
    }
}
To keep a single For form, _ is used when you don't need either the index or value
for _, value := range pow {
    fmt.Printf("%d\n", value)
}

Object Creation

new creates New Objects
make creates New Arrays & Maps
a:=new(SomeStruct)
b:=make([]int, 5)
Maps are declared: map[keyType]valType
maps can return a key, boolean pair describing what the value is/if the key existed

Simultaneous Assignment

x,y = y,x+y
Temp variables are no longer needed!


No Break Statement Needed in Switch Statements

switch ret {
  case 1: //Do something
  case 2: //Do something else
  default:
}

No Classes. Just Structs with Methods Appended

interface types can have method signatures defined in them. a type implements an interface when it has those methods, not by tagging it as that interface
type Greeter interface {
    Greet() string
}

Errors Implemented by Having an Error()(string) Method

You don't tag a struct or object with an interface. If an object has the methods defined in an interface, it is automatically-polymorphically-compatible.

Easy Threading

go someMethod, will launch that method on a separate thread. When you combine this with channels (a report back mechanism), concurrency becomes simple compared to many other languages:
func getInfoFromThread(x chan string) {
    x <- "hi"

}
func main() {
    x := make(chan string)
    go getInfoFromThread(x)
    z := <-x br="">    fmt.Println(z)
}

No comments:

Post a Comment