go |cpp

Discovering Go from C++ [Part 1] variables, conditions, loops, print.

pmalhaire

pmalhaire

Posted on April 8, 2018

Discovering Go from C++ [Part 1] variables, conditions, loops, print.

Go
C++

Variable initialization and declaration

Go and C++ are following the same track here. Variables initialization and declaration are very similar.

var test int
test = 1

var test int = 1

test := 1
Enter fullscreen mode Exit fullscreen mode

Some more constrain could here be less error prone but more painful to write.
A classical error is variable shadowing this way:

import (
    "fmt"
)

func main() {
    variable := 1
    if true {
        variable := 3
        fmt.Println(variable)
    }
    fmt.Println(variable)
}
Enter fullscreen mode Exit fullscreen mode

test code

C++ style is less error prone (for shadowing) auto a = x is more visible than := compared to =. The -Wshadow g++ warning is a possibility. From my experience shadowing occurs really less when writing C++ than Go.

#include <iostream>

using namespace std;

int main()
{
    auto variable = 1;

    {
        auto variable = 3;
        cout << variable << endl;
    }
    cout << variable << endl;
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

test code

Go way looks nice but the taste is strange.

Not used variable

func main() {
    test := 1
}
Enter fullscreen mode Exit fullscreen mode

test code

 prog.go:5:2 test declared and not used
Enter fullscreen mode Exit fullscreen mode

I am sometimes lazy with this and I am not the only one. For code maintainability it's just awesome.

It can be annoying for debug. If you remove some expression Go starts complaining of unused variable, then of unused import, etc.


import "fmt"

func main(){
   test := "test"
/*
   fmt.Println(test)
*/
}

Enter fullscreen mode Exit fullscreen mode
 prog.go:X:5: fmt imported and not used
Enter fullscreen mode Exit fullscreen mode

The most easy way to avoid this is to wrap expression with if (false) {…} but it's messy.

Clang and GCC warn about the unused variables since ages. I would love to have GCC/Clang style (warn and -Werror for release).

I love that as it make my code cleaner. Some improvement would help especially for writing debug code.

Multiple return values

I discovered that in Lua and find it really interesting.

Here is an example :

package main
import "fmt"


func set() (x, y, z int) {
    return 1, 2, 3
}

func main() {
    x, y, z := set()
    fmt.Println(x, y, z)
}
Enter fullscreen mode Exit fullscreen mode

test code

1 2 3
Enter fullscreen mode Exit fullscreen mode

Note : When a function returns multiple variables not all are used it’s important to avoid not using the result that takes long to compute.
I wish I could add a compilation warning sent when I am ignoring the variable taking cpu time to be computed.

A C++ way to do this:

#include <iostream>
#include <tuple>

using namespace std;

auto set() {
    return make_tuple(1,2,3);
}

int main()
{
    auto [a, b, c] = set();


    std::cout << a << " " << b << " " << c << std::endl;

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

test code

I definitely like this. It's compacting code mostly for good.

Conditions If, else if

Go forces only one syntax:

if A {
} else {
}
Enter fullscreen mode Exit fullscreen mode

Nested else if in C++ style is not allowed :

if A {
    If B {
    } else if C {
    }

}
Enter fullscreen mode Exit fullscreen mode

At first go is destroying my brain coming from C++.

It felt like that :

  • try raw code
  • read doc
  • code
  • get annoyed
  • read doc
  • code
  • getting the point
  • be ok with go.

Forcing one syntax is a way to avoid bugs coming from mixing multiple syntax.

A kind of dictature but why not (in this, and only this, particular case).

It's easier to read code always written the same way even if I don't like loosing my freedom.

For loop

First thing I found simple is for, we tried to replace this but, we don’t have to reinvent the wheel.
For is extended as well which is good but C granny won’t get confused.

for i := 1; i<=4; i++ {
        fmt.Println(i)
}

numbers := []int{1,2,3,4}
for _,v := range numbers {
    fmt.Println(v)
}
Enter fullscreen mode Exit fullscreen mode

Nothing really new here. C++ has a lot of patterns to do this including iterators which are not implemented (yet) in Go.

Switch

Switch in go and easy to read not far C++.

Go

switch t {
case 1:
    fmt.Println("case 1")
default:
    fmt.Println("default")
}
Enter fullscreen mode Exit fullscreen mode

test code

C++

switch (var) {
        case 1:
            cout << "case 1" << endl;
            break;
        default:
            cout << "default" << endl;
}

Enter fullscreen mode Exit fullscreen mode

test code

String printing

Multiple ways of doing very close things, I got used quite fast but found it annoying.

import "fmt"

func main() {
    str := "hello"
    slice := []string{"one", "two", "three"}

    fmt.Print(str)
    fmt.Print("\n")
    fmt.Print(slice)
    fmt.Print("\n")

    fmt.Println(str)
    fmt.Println(slice)

    fmt.Printf("%v\n", str)
    fmt.Printf("%v\n", slice)
}

Enter fullscreen mode Exit fullscreen mode
hello
[one two three]
hello
[one two three]
hello
[one two three]
Enter fullscreen mode Exit fullscreen mode

It can really get messy and the Println("string") function is a hook which can be replaced by Print("string\n"). Note Println behave the same on all platforms, it does not change the separator to \r\n in Windows. It's just syntactic sugar why not.

Where go it simpler than Cpp is to print slice content.

Cpp would do :

#include <iostream>

using namespace std;

int main()
{
    auto list = {1, 2, 3};


    for ( const auto &v: list) {
        cout << v << " ";
    }
    cout << endl;


    return 0;
}
Enter fullscreen mode Exit fullscreen mode

test code

After using Print and Println functions for more time it makes life easier. Go is often used in various containers having a simple and compact way to print objects and values is nice.

What is println ?

I just end up mistyping fmt.Println to println :

import "fmt"

func main() {

    fmt.Println("Hello")
        // ok 
    println("hello")
        // ok 

    slice := []string{"toto", "tutu"}
    fmt.Println(slice)
        // ok
    println(slice)
        // ko
}
Enter fullscreen mode Exit fullscreen mode
hello
hello
[toto tutu]
[2/2]0x1040a0d0
Enter fullscreen mode Exit fullscreen mode

Interesting thing but what the hell is that, I guess it’s language internals ?
In fact it's just an helper for printf debugging without additionnal import, it may disappear in the future.

This is just a something strange with no real impact (just never commit println).

More details here.

Bytes vs Rune

Rune is unicode character.

import "fmt"
import "reflect"

func main() {

str := "s"
str_utf8 := "漢"
rune_utf8 := []rune("漢")

//printing the object the first item and the first item type for each case
fmt.Println(str, string(str[0]), reflect.TypeOf(str[0]))
fmt.Println(str_utf8 , string(str_utf8[0]), reflect.TypeOf(str_utf8[0]))
fmt.Println(rune_utf8 , string(rune_utf8[0]), reflect.TypeOf(rune_utf8[0]))
}
Enter fullscreen mode Exit fullscreen mode
s s uint8
漢 æ uint8
[28450] 漢 int32
Enter fullscreen mode Exit fullscreen mode

test code

It's a nice thing to have rune, but why not make it the default. Most of the time strings are to be shown. Unicode then makes sense. I feel like it's a good start stopped in the middle.

Conclusion

Go is growing a lot today and it's syntax is very easy to handle. For the basics it has some nice things.

Next part will be about objects and concurrency/parallelism in Go coming from C++ there Go and C++ differences have more impact.

And thanks to Dmytro who had a look at my post.

💖 💪 🙅 🚩
pmalhaire
pmalhaire

Posted on April 8, 2018

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related