Go vs Python comparison¶
| python | golang | vs | comparison |
It’s not my writings and it’s just a copy of Go vs. Python by Peter Bengtsson (see References below)
- References
- Hello World
- Comments
- Multiline Strings
- Lists
- Maps
- Booleans
- Forloop
- Range
- Switch
- Variadic Functions
- Time Elapsed
- Closure Functions
- Defer
- Panic Recover
- Mutables
- Structs
- Methods
- Goroutines
- Args
- Import Alias
- Sprintf
- Uniqify
- Dotdict
References¶
Hello World¶
Go
package main
import "fmt"
func main() {
fmt.Println("Hello world")
}
Python
print("Hello world")
Print¶
Go
package main
import "fmt"
func main() {
fmt.Println("Some string")
fmt.Print("Some string")
fmt.Printf("Name: %s, Age: %d\n", "Peter", 35)
}
Python
print("Some string")
print("Some string", end="") # no newline character printed
print("Name: {}, Age: {}".format("Peter", 35))
Comments¶
Go
package main
// This is a general comment
/* This is also a comment
but on multiple lines.
*/
/* This is the multi-line comment for the function main().
To get access to this from the command line, run:
godoc comments.go
*/
func main() {
}
Python
"""This is a doc string for the whole module"""
# This is a inline comment
class Class(object):
"""This is the doc string for the class"""
print(__doc__)
print(Class.__doc__)
Multiline Strings¶
Go
package main
import "fmt"
func main() {
fmt.Println(`This is
a multi-line string.
`)
fmt.Println(
"O'word " +
"Another \"word\" " +
"Last word.")
}
Python
print(
"""This is
a multi-line string.
"""
)
print("O'word " 'Another "word" ' "Last word.")
Lists¶
Go
package main
import "fmt"
func main() {
// initialized array
var numbers [5]int // becomes [0, 0, 0, 0, 0]
// change one of them
numbers[2] = 100
// create a new slice from an array
some_numbers := numbers[1:3]
fmt.Println(some_numbers) // [0, 100]
// length of it
fmt.Println(len(numbers))
// initialize a slice
var scores []float64
scores = append(scores, 1.1) // recreate to append
scores[0] = 2.2 // change your mind
fmt.Println(scores) // prints [2.2]
// when you don't know for sure how much you're going
// to put in it, one way is to
var things [100]string
things[0] = "Peter"
things[1] = "Anders"
fmt.Println(len(things)) // 100
}
Python
# initialize list
numbers = [0] * 5
# change one of them
numbers[2] = 100
some_numbers = numbers[1:3]
print(some_numbers) # [0, 100]
# length of it
print(len(numbers)) # 5
# initialize another
scores = []
scores.append(1.1)
scores[0] = 2.2
print(scores) # [2.2]
Maps¶
Go
//You can make a map of maps with:
elements : make(map[string]map[string]int)
elements["H"] = map[string]int{
"protons": 1,
"neutrons": 0,
}
//But note, this is what you have struct for.
package main
import "fmt"
func main() {
elements := make(map[string]int)
elements["H"] = 1
fmt.Println(elements["H"])
// remove by key
elements["O"] = 8
delete(elements, "O")
// only do something with a element if it's in the map
if number, ok := elements["O"]; ok {
fmt.Println(number) // won't be printed
}
if number, ok := elements["H"]; ok {
fmt.Println(number) // 1
}
}
Python
elements = {}
elements["H"] = 1
print(elements["H"]) # 1
# remove by key
elements["O"] = 8
elements.pop("O")
# do something depending on the being there
if "O" in elements:
print(elements["O"])
if "H" in elements:
print(elements["H"])
Booleans¶
Go
x := 1
if x != 0 {
fmt.Println("Yes")
}
var y []string
if len(y) != 0 {
fmt.Println("this won't be printed")
}
Python
x = 1
if x:
print "Yes"
y = []
if y:
print "this won't be printed"
Go
package main
import "fmt"
func main() {
fmt.Println(true && false) // false
fmt.Println(true || false) // true
fmt.Println(!true) // false
x := 1
if x != 0 {
fmt.Println("Yes")
}
var y []string
if len(y) != 0 {
fmt.Println("this won't be printed")
}
}
Python
print(True and False) # False
print(True or False) # True
print(not True) # False
Forloop¶
package main
import "fmt"
func main() {
i := 1
for i <= 10 {
fmt.Println(i)
i += 1
}
// same thing more but more convenient
for i := 1; i <= 10; i++ {
fmt.Println(i)
}
}
Python
i = 1
while i <= 10:
print(i)
i += 1
# ...or...
for i in range(1, 11):
print(i)
Range¶
Go
package main
import "fmt"
func main() {
names := []string{
"Peter",
"Anders",
"Bengt",
}
/* This will print
1. Peter
2. Anders
3. Bengt
*/
for i, name := range names {
fmt.Printf("%d. %s\n", i+1, name)
}
}
Python
names = ["Peter", "Anders", "Bengt"]
for i, name in enumerate(names):
print("{}. {}".format(i + 1, name))
Switch¶
Go
package main
import (
"fmt"
"strconv"
)
func str2int(s string) int {
i, err := strconv.Atoi(s)
if err != nil {
panic("Not a number")
}
return i
}
func main() {
var number_string string
fmt.Scanln(&number_string)
number := str2int(number_string)
switch number {
case 8:
fmt.Println("Oxygen")
case 1:
fmt.Println("Hydrogen")
case 2:
fmt.Println("Helium")
case 11:
fmt.Println("Sodium")
default:
fmt.Printf("I have no idea what %d is\n", number)
}
// Alternative solution
fmt.Scanln(&number_string)
db := map[int]string{
1: "Hydrogen",
2: "Helium",
8: "Oxygen",
11: "Sodium",
}
number = str2int(number_string)
if name, exists := db[number]; exists {
fmt.Println(name)
} else {
fmt.Printf("I have no idea what %d is\n", number)
}
}
Python
def input_():
return int(input())
number = input_()
if number == 8:
print("Oxygen")
elif number == 1:
print("Hydrogen")
elif number == 2:
print("Helium")
elif number == 11:
print("Sodium")
else:
print("I have no idea what %d is" % number)
# Alternative solution
number = input_()
db = {1: "Hydrogen", 2: "Helium", 8: "Oxygen", 11: "Sodium"}
print(db.get(number, "I have no idea what %d is" % number))
Variadic Functions¶
package main
import "fmt"
func average(numbers ...float64) float64 {
total := 0.0
for _, number := range numbers {
total += number
}
return total / float64(len(numbers))
}
func main() {
fmt.Println(average(1, 2, 3, 4)) // 2.5
}
Python
def average(*numbers):
return sum(numbers) / len(numbers)
print(average(1, 2, 3, 4)) # 10/4 = 2.5
Time Elapsed¶
Go
package main
import "fmt"
import "time"
func main() {
t0 := time.Now()
elapsed := time.Since(t0)
fmt.Printf("Took %s", elapsed)
}
Python
import time
t0 = time.time()
time.sleep(3.5) # for example
t1 = time.time()
print("Took {:.2f} seconds".format(t1 - t0))
Closure Functions¶
Go
package main
import "fmt"
func main() {
number := 0
/* It has to be a local variable like this.
You can't do `func increment(amount int) {` */
increment := func(amount int) {
number += amount
}
increment(1)
increment(2)
fmt.Println(number) // 3
}
Python
def run():
def increment(amount):
return number + amount
number = 0
number = increment(1)
number = increment(2)
print(number) # 3
run()
Defer¶
Go
package main
import (
"os"
)
func main() {
f, _ := os.Open("defer.py")
defer f.Close()
// you can now read from this
// `f` thing and it'll be closed later
}
Python
f = open("defer.py")
try:
f.read()
finally:
f.close()
Panic Recover¶
Go
package main
import "fmt"
func main() {
// Running this will print out:
// error was: Shit!
defer func() {
fmt.Println("error was:", recover())
}()
panic("Shit!")
}
Python
try:
raise Exception("Shit")
except Exception as e:
print("error was:", e)
Mutables¶
Go
package main
import (
"fmt"
"strings"
)
func upone_list(thing []string, index int) {
thing[index] = strings.ToUpper(thing[index])
}
func upone_map(thing map[string]string, index string) {
thing[index] = strings.ToUpper(thing[index])
}
func main() {
// mutable
list := []string{"a", "b", "c"}
upone_list(list, 1)
fmt.Println(list) // [a B c]
// mutable
dict := map[string]string{
"a": "anders",
"b": "bengt",
}
upone_map(dict, "b")
fmt.Println(dict) // map[a:anders b:BENGT]
}
Python
def upone(mutable, index):
mutable[index] = mutable[index].upper()
list_ = ["a", "b", "c"]
upone(list_, 1)
print(list_) # ['a', 'B', 'c']
dict_ = {"a": "anders", "b": "bengt"}
upone(dict_, "b")
print(dict_) # {'a': 'anders', 'b': 'BENGT'}
Structs¶
Go
package main
import (
"fmt"
"math"
)
type Point struct {
x float64
y float64
}
func distance(point1 Point, point2 Point) float64 {
return math.Sqrt(point1.x*point2.x + point1.y*point2.y)
}
// Since structs get automatically copied,
// it's better to pass it as pointer.
func distance_better(point1 *Point, point2 *Point) float64 {
return math.Sqrt(point1.x*point2.x + point1.y*point2.y)
}
func main() {
p1 := Point{1, 3}
p2 := Point{2, 4}
fmt.Println(distance(p1, p2)) // 3.7416573867739413
fmt.Println(distance_better(&p1, &p2)) // 3.7416573867739413
}
Python
from math import sqrt
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def distance(point1, point2):
return sqrt(point1.x * point2.x + point1.y * point2.y)
p1 = Point(1, 3)
p2 = Point(2, 4)
print(distance(p1, p2)) # 3.74165738677
Methods¶
Go
package main
import (
"fmt"
"math"
)
type Point struct {
x float64
y float64
}
func (this Point) distance(other Point) float64 {
return math.Sqrt(this.x*other.x + this.y*other.y)
}
// Dince structs get automatically copied,
// it's better to pass it as pointer.
func (this *Point) distance_better(other *Point) float64 {
return math.Sqrt(this.x*other.x + this.y*other.y)
}
func main() {
p1 := Point{1, 3}
p2 := Point{2, 4}
fmt.Println(p1.distance(p2)) // 3.7416573867739413
fmt.Println(p1.distance_better(&p2)) // 3.7416573867739413
}
Python
from math import sqrt
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def distance(self, other):
return sqrt(self.x * other.x + self.y * other.y)
p1 = Point(1, 3)
p2 = Point(2, 4)
print(p1.distance(p2)) # 3.74165738677
print(p2.distance(p1)) # 3.74165738677
Goroutines¶
Go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"sync"
)
func f(url string) {
response, err := http.Get(url)
if err != nil {
panic(err)
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
panic(err)
}
fmt.Println(len(body))
}
// See the example in https://golang.org/pkg/sync/#WaitGroup
func main() {
var wg sync.WaitGroup
urls := []string{
"https://www.peterbe.com",
"https://python.org",
"https://golang.org",
}
for _, url := range urls {
wg.Add(1)
go func(url string) {
defer wg.Done()
f(url)
}(url)
}
// Wait for the goroutines to finish
wg.Wait()
}
Python
import urllib2
import multiprocessing
def f(url):
req = urllib2.urlopen(url)
try:
print(len(req.read()))
finally:
req.close()
urls = ("https://www.peterbe.com", "https://python.org", "https://golang.org")
if __name__ == "__main__":
p = multiprocessing.Pool(3)
p.map(f, urls)
Args¶
Go
package main
import (
"fmt"
"os"
"strings"
)
func transform(args []string) {
for _, arg := range args {
fmt.Println(strings.ToUpper(arg))
}
}
func main() {
args := os.Args[1:]
transform(args)
}
Python
import sys
def transform(*args):
for arg in args:
print(arg.upper())
if __name__ == "__main__":
transform(*sys.argv[1:])
Import Alias¶
Go
import (
pb "github.com/golang/groupcache/groupcachepb"
)
// or
import (
_ "image/png" // You can also import packages that you won't actually use
)
// or
package main
import (
"fmt"
s "strings"
)
func main() {
fmt.Println(s.ToUpper("world"))
}
Python
import string as s
print(s.upper("world"))
Sprintf¶
Go
package main
import "fmt"
func main() {
max := 10
panic(fmt.Sprintf("The max. number is %d", max))
}
Python
max = 10
raise Exception(f"The max. number is {max}")
Uniqify¶
Go
package main
import "fmt"
func uniqify(items []string) []string {
uniq := make([]string, 0)
seen := make(map[string]bool)
// For the highest memory efficiency, do:
// seen := make(map[string]struct{})
// see: https://stackoverflow.com/questions/37320287/maptstruct-and-maptbool-in-golang
for _, i := range items {
if _, exists := seen[i]; !exists {
uniq = append(uniq, i)
seen[i] = true
}
}
return uniq
}
func main() {
items := []string{"B", "B", "E", "Q", "Q", "Q"}
items = uniqify(items)
fmt.Println(items) // prints [B E Q]
}
Python
def uniqify(seq):
seen = {}
unique = []
for item in seq:
if item not in seen:
seen[item] = 1
unique.append(item)
return unique
items = ["B", "B", "E", "Q", "Q", "Q"]
print(uniqify(items)) # prints ['B', 'E', 'Q']
Dotdict¶
Go
package main
import "fmt"
func main() {
names := []string{"peter", "anders", "bengt", "bengtsson"}
initials := make(map[string]int)
for _, name := range names {
initial := string(name[0])
initials[initial]++
}
fmt.Println(initials)
// outputs
// map[p:1 a:1 b:2]
}
Python
initials = {}
for name in ("peter", "anders", "bengt", "bengtsson"):
initial = name[0]
# if initial not in initials:
# initials[initial] = 0
initials.setdefault(initial, 0)
initials[initial] += 1
print(initials)
# outputs
# {'a': 1, 'p': 1, 'b': 2}