Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/oalders/go-for-perl-hackers
Go Cheat Sheet for Perl Hackers
https://github.com/oalders/go-for-perl-hackers
go golang perl perl5
Last synced: 19 days ago
JSON representation
Go Cheat Sheet for Perl Hackers
- Host: GitHub
- URL: https://github.com/oalders/go-for-perl-hackers
- Owner: oalders
- Created: 2017-08-02T15:20:28.000Z (over 7 years ago)
- Default Branch: main
- Last Pushed: 2024-12-09T17:37:58.000Z (about 2 months ago)
- Last Synced: 2025-01-04T01:00:16.852Z (27 days ago)
- Topics: go, golang, perl, perl5
- Language: Perl
- Homepage:
- Size: 148 KB
- Stars: 92
- Watchers: 11
- Forks: 16
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
* [go-for-perl-hackers](#go-for-perl-hackers)
* [Your editor](#your-editor)
* [Go vs Perl](#go-vs-perl)
* [Installing binaries:](#installing-binaries)
* [Perl](#perl)
* [Go](#go)
* [Constructs](#constructs)
* [Comments](#comments)
* [Perl](#perl-1)
* [Go](#go-1)
* [Print](#print)
* [Printing strings](#printing-strings)
* [Perl](#perl-2)
* [Go](#go-2)
* [Formatted print statements.](#formatted-print-statements)
* [Perl](#perl-3)
* [Go](#go-3)
* [Printing from within a test](#printing-from-within-a-test)
* [Perl](#perl-4)
* [Go](#go-4)
* [Variables](#variables)
* [Environment Variables](#environment-variables)
* [Perl](#perl-5)
* [Go](#go-5)
* [Variable Assignment](#variable-assignment)
* [Perl](#perl-6)
* [Go](#go-6)
* [Multiple Variables](#multiple-variables)
* [Declare without explicit values](#declare-without-explicit-values)
* [Perl](#perl-7)
* [Go](#go-7)
* [Declare with explicit values](#declare-with-explicit-values)
* [Perl](#perl-8)
* [Go](#go-8)
* [Double vs Single Quotes](#double-vs-single-quotes)
* [Perl](#perl-9)
* [Go](#go-9)
* [Multiline strings](#multiline-strings)
* [Perl](#perl-10)
* [Go](#go-10)
* [Boolean checks (true/false)](#boolean-checks-truefalse)
* [Perl](#perl-11)
* [Go](#go-11)
* [Checking for (un)definedness](#checking-for-undefinedness)
* [Perl](#perl-12)
* [Go](#go-12)
* [Incrementing and Decrementing Integer](#incrementing-and-decrementing-integer)
* [Perl](#perl-13)
* [Go](#go-13)
* [Division with Integers](#division-with-integers)
* [Perl](#perl-14)
* [Go](#go-14)
* [String Concatenation](#string-concatenation)
* [Perl](#perl-15)
* [Go](#go-15)
* [String Concatenation (Existing String)](#string-concatenation-existing-string)
* [Perl:](#perl-16)
* [Go:](#go-16)
* [string to byte array Conversion](#string-to-byte-array-conversion)
* [Go](#go-17)
* [byte array to string Conversion](#byte-array-to-string-conversion)
* [Go](#go-18)
* [Constants](#constants)
* [Perl](#perl-17)
* [Go](#go-19)
* [Lists](#lists)
* [Create an Array](#create-an-array)
* [Perl](#perl-18)
* [Go](#go-20)
* [Size of an array:](#size-of-an-array)
* [Perl](#perl-19)
* [Go](#go-21)
* [Hashes / Structs](#hashes--structs)
* [Perl](#perl-20)
* [Go](#go-22)
* [Iterating Over a List](#iterating-over-a-list)
* [Perl](#perl-21)
* [Go](#go-23)
* [Splitting a string](#splitting-a-string)
* [Perl](#perl-22)
* [Go](#go-24)
* [Iterating Over a Hash/Map](#iterating-over-a-hashmap)
* [Perl using keys](#perl-using-keys)
* [Go using only primary return value](#go-using-only-primary-return-value)
* [Perl using each](#perl-using-each)
* [Go using both primary and secondary return values](#go-using-both-primary-and-secondary-return-values)
* [Perl: using values](#perl-using-values)
* [Go: ignoring primary return value, using only secondary return value](#go-ignoring-primary-return-value-using-only-secondary-return-value)
* [Checking if a Hash/Map Key Exists](#checking-if-a-hashmap-key-exists)
* [Perl](#perl-23)
* [Go](#go-25)
* [Using a Hash/Map to Track Seen Things](#using-a-hashmap-to-track-seen-things)
* [Perl](#perl-24)
* [Go](#go-26)
* [Deleting a Hash/Map Key](#deleting-a-hashmap-key)
* [Perl](#perl-25)
* [Go](#go-27)
* [Getting a List of Hash/Map Keys](#getting-a-list-of-hashmap-keys)
* [Perl](#perl-26)
* [Go](#go-28)
* [Slices:](#slices)
* [Perl](#perl-27)
* [Go](#go-29)
* [Appending Slices:](#appending-slices)
* [Perl](#perl-28)
* [Go](#go-30)
* [Dumping Data Structures](#dumping-data-structures)
* [To your terminal](#to-your-terminal)
* [Perl](#perl-29)
* [Go](#go-31)
* [To disk (write)](#to-disk-write)
* [Perl](#perl-30)
* [Go](#go-32)
* [To disk (append)](#to-disk-append)
* [Perl](#perl-31)
* [Go](#go-33)
* [File Operations](#file-operations)
* [Creating a directory](#creating-a-directory)
* [Perl](#perl-32)
* [Go](#go-34)
* [Read an Entire File](#read-an-entire-file)
* [Perl](#perl-33)
* [Go](#go-35)
* [Read First Line of a File](#read-first-line-of-a-file)
* [Perl](#perl-34)
* [Go](#go-36)
* [Flow Control](#flow-control)
* [if](#if)
* [Perl](#perl-35)
* [Go](#go-37)
* [else](#else)
* [Perl](#perl-36)
* [Go](#go-38)
* [elsif / else if](#elsif--else-if)
* [Perl](#perl-37)
* [Go](#go-39)
* [Loops](#loops)
* [For loops](#for-loops)
* [Perl](#perl-38)
* [Go](#go-40)
* [While loops](#while-loops)
* [Perl](#perl-39)
* [Go](#go-41)
* [Infinite loops](#infinite-loops)
* [Perl](#perl-40)
* [Go](#go-42)
* [Short-circuiting a loop iteration](#short-circuiting-a-loop-iteration)
* [Terminating a loop](#terminating-a-loop)
* [Regular Expressions](#regular-expressions)
* [Perl](#perl-41)
* [Go](#go-43)
* [Today's Date as YYYY-MM-DD](#todays-date-as-yyyy-mm-dd)
* [Perl](#perl-42)
* [Go](#go-44)
* [Functions](#functions)
* [Functions without signatures](#functions-without-signatures)
* [Perl](#perl-43)
* [Go](#go-45)
* [Running Tests](#running-tests)
* [Perl](#perl-44)
* [Go](#go-46)
* [Debugging](#debugging)
* [Printing Stack Traces](#printing-stack-traces)
* [Perl](#perl-45)
* [Go](#go-47)
* [Sleep](#sleep)
* [Perl](#perl-46)
* [Go](#go-48)
* [Parsing URIs](#parsing-uris)
* [Perl](#perl-47)
* [Go](#go-49)
* [Changing URI Query Params](#changing-uri-query-params)
* [Go](#go-50)
* [Command Line Scripts](#command-line-scripts)
* [Print first argument to a script](#print-first-argument-to-a-script)
* [Perl](#perl-48)
* [Go](#go-51)
* [Exiting a script](#exiting-a-script)
* [Perl](#perl-49)
* [Go](#go-52)# go-for-perl-hackers
The primary aim of this cheat sheet is to help Perl programmers get up and running with Go.
## Your editor
I recommend setting up [gopls](https://pkg.go.dev/golang.org/x/tools/gopls).
## Go vs Perl
### Installing binaries:
#### Perl
```perl
cpm install -g App::perlimports
```This will install a `perlimports` binary in your `$PATH`.
#### Go
```go
go install golang.org/x/tools/cmd/goimports@latest
```This will install `goimports` into `$GOPATH/bin`
### Constructs
In this section we'll document some commonly used Perl constructs and try to find their equivalents in Go.
### Comments
#### Perl
```perl
# single line=pod
Multi line
=cut
```#### Go
```go
// single line (C++-style)/*
Multi-line (C-Style)
*/
```#### Printing strings
##### Perl
```perl
print 'hello, world';
```##### Go
```go
package mainimport "fmt"
func main() {
fmt.Print("hello, world")
}
```See "Double vs Single Quotes" for more information on why single quotes are not
used to quote strings in Go.#### Formatted print statements.
##### Perl
```perl
printf('We are open %i days per %s', 7, 'week');
```##### Go
```go
package mainimport (
"fmt"
)func main() {
fmt.Printf("We are open %d days per %s", 7, "week")
}
```See [golang.org/pkg/fmt/](https://golang.org/pkg/fmt/)
#### Printing from within a test
##### Perl
```perl
diag 'foo happens';
```##### Go
```go
t.Log("foo happens")
t.Logf("We are open %d days per %s", 7, "week")
```### Variables
#### Environment Variables
##### Perl
```perl
$ENV{FOO} = 'bar';
local $ENV{FOO} = 'bar'; # Same as above, but with local scopeprint "GOPATH: $ENV{GOPATH}\n";
```##### Go
```go
os.Setenv("FOO", "bar")fmt.Println("GOPATH: ", os.Getenv("GOPATH"))
```#### Variable Assignment
##### Perl
```perl
my $foo = 'bar';
my $pi = 3.14;
my $no_assignment;
```##### Go
```go
// the following assignments are equivalent
var foo = "bar"
foo := "bar"var pi float32 = 3.14 // explicit cast as float32
pi := float32(3.14) // explicit cast as float32
pi := 3.14 // implicit cast as float64
pi := "3.14" // implicit cast as stringvar noAssignment string // equivalent to: noAssignment := ""
```:
> When you need an integer value you should use int unless you have a specific
> reason to use a sized or unsigned integer type.#### Multiple Variables
##### Declare without explicit values
###### Perl
```perl
my ($foo, $bar);
```###### Go
```go
var foo, bar int
var nothing []string // create an empty slice
```##### Declare with explicit values
###### Perl
```perl
my ($i, $j) = (1, 2);
```###### Go
```go
var i, j int = 1, 2
```#### Double vs Single Quotes
##### Perl
```perl
my $foo = 'bar'; # no variable interpolation
my $bar = "$foo baz"; # allow for variable interpolation
```##### Go
```go
foo := "本" // implicitly cast as a string
foo := '本' // implicitly cast as a rune
```Rune is an alias for `int32` and represents a Unicode code point.
For example: `fmt.Println('a')` prints 97, which is hexadecimal 61. The Unicode
for `a` is `U+0061`.To print the Hex value of `'a'` you can also do `fmt.Println("%x", 'a')`
Go expects only a single letter inside single quotes, so this will yield a
compile time error:```go
fmt.Printf("%s", 'hello')
```> more than one character in rune literal
See
[golang.org/ref/spec#Rune_literals](https://golang.org/ref/spec#Rune_literals)
and#### Multiline strings
##### Perl
```perl
my $long_string = <<'EOF';
my multiline
string
EOF
```Use double quotes `<<"EOF";` if you need to interpolate variables.
##### Go
```go
longString := `
my multiline
string
`
```#### Boolean checks (true/false)
##### Perl
```perl
my $success = 1; # true
$success = 'foo'; # true
$success = 0; # false
$success; # (undef) falseif ($success) {
print "This succeeded";
}if ( !$success ) {
print "This failed";
}```
##### Go
```go
var success boolsuccess = true
success = falseif success == true {
fmt.Println("This succeeded")
}if success {
fmt.Println("This succeeded")
}if success == false {
fmt.Println("This failed")
}if !success {
fmt.Println("This failed")
}
```#### Checking for (un)definedness
##### Perl
```perl
my $foo;
if ( ! defined $foo ) {
...;
}
```##### Go
```go
package mainimport "fmt"
func main() {
var myString stringif myString == "" {
fmt.Println("Empty")
}var mySlice []int
if mySlice == nil {
fmt.Println("nil")
}
if len(mySlice) == 0 {
fmt.Println("empty")
}
}
```[Go Playground](https://go.dev/play/p/R2rQ4F8lyCu)
#### Incrementing and Decrementing Integer
##### Perl
See [https://perldoc.perl.org/perlop.html#Auto-increment-and-Auto-decrement](https://perldoc.perl.org/perlop.html#Auto-increment-and-Auto-decrement)
```perl
$i = 0; $j = 0;
print $i++; # prints 0
print ++$j; # prints 1$i = 0; $j = 0;
print $i--; # prints 0
print --$j; # prints -1
```##### Go
```go
counter := 1
counter++
counter--
```#### Division with Integers
##### Perl
```perl
my $amount = 18 / 20_000;
```##### Go
```go
package mainimport "fmt"
func main() {
amount := float32(18) / float32(20000)
fmt.Println(amount)
}
```Note: without the `float32` conversion, `amount` will be 0.
[https://go.dev/play/p/ZIotxD2kQen](https://go.dev/play/p/ZIotxD2kQen)
#### String Concatenation
##### Perl
```perl
my $foo = 'go';
my $bar = 'pher';my $gopher = "$foo$bar";
$gopher = $foo . $bar;
$gopher = join q{}, $foo, $bar;
$gopher = sprintf '%s%s', $foo, $bar;
```##### Go
```go
package mainimport (
"fmt"
"strings"
)func main() {
var gopher stringgopher = foo + bar
gopher = fmt.Sprintf("%s%s", foo, bar)
}
``````go
package mainimport (
"fmt"
"strings"
)func main() {
foo := "go"
bar := "pher"gopher = strings.Join([]string{"go", "pher"}, "")
fmt.Println(gopher)
}
``````go
package mainimport (
"bytes"
"fmt"
)func main() {
var buffer bytes.Buffer
foo := "go"
bar := "pher"buffer.WriteString(foo)
buffer.WriteString(bar)
fmt.Println(buffer.String())
}
```#### String Concatenation (Existing String)
##### Perl:
```perl
my $foo = 'go';
$foo .= 'pher';
```##### Go:
```go
package mainfunc main() {
foo := "go"
foo += "pher"
}
```[https://go.dev/play/p/UJqGTHWCbQB](https://go.dev/play/p/UJqGTHWCbQB)
#### string to byte array Conversion
##### Go
```go
b := []byte("Each day provides its own gifts")
```#### byte array to string Conversion
##### Go
```go
package mainimport "fmt"
func main() {
// create the byte array
b := []byte("Each day provides its own gifts")// convert back to a string by passing the array
contentAsString := string(b)
fmt.Println(contentAsString)// convert back to a string by passing a slice referencing the storage of b
contentAsString = string(b[:])
fmt.Println(contentAsString)
}
```
[https://go.dev/play/p/DKsQJmS5yuf](https://go.dev/play/p/DKsQJmS5yuf)#### Constants
##### Perl
```perl
use Const::Fast;
const my $hello => 'Hello, world';
```##### Go
```go
// Create an *untyped* string constant
const hello = "Hello, world"// Create a typed string constant
const hello string = "Hello, World"
```Create multiple constants with one `const` declaration:
```go
const (
hello = "Hello, world"
goodbye = "Goodbye!"
)
```Constants cannot be declared using the := syntax.
### Lists
#### Create an Array
##### Perl
```perl
my @foo = (1..3);
my $first = $foo[0];
```##### Go
```go
foo := [3]int{1, 2, 3}
first := foo[0]
```Note that creating an empty array in Go means that it will be populated by the type's default values:
```go
var bar [5]int // creates an array of [0,0,0,0,0]
```#### Size of an array:
##### Perl
```perl
my $size = @array;
```##### Go
```Go
size := len(array)
```#### Hashes / Structs
##### Perl
```perl
use Data::Printer; # exports p()my %foo = (
X => 1,
Y => 2,
);$foo{X} = 4;
print $foo{X}; # prints 4p %foo;
# prints:
# {
# X => 4,
# Y => 2,
# }delete $foo{X};
```##### Go
[https://play.golang.org/p/wyeohYSw-cf](https://play.golang.org/p/wyeohYSw-cf)
```go
package mainimport "fmt"
type Vertex struct {
X int
Y int
}func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X) // prints 4
fmt.Printf("%+v\n", v) // prints {X:4 Y:2}// additional examples
v1 := Vertex{1, 2} // has type Vertex
v2 := Vertex{X: 1} // Y:0 is implicit
v3 := Vertex{} // X:0 and Y:0v.X = 0
fmt.Printf("1: %d, 2: %d, 3: %d", v1.X, v2.X, v3.X)
}
```#### Iterating Over a List
##### Perl
```perl
my @foo = ('foo', 'bar', 'baz');for my $value ( @foo ) {
print "$value\n";
}
``````perl
my @foo = ('foo', 'bar', 'baz');for (@foo) {
print "$_\n";
}
``````perl
// Print array index for each element
my @foo = ('foo', 'bar', 'baz');for my $i (0..$#foo) {
print "$i: $foo[$i]\n";
}```
##### Go
```go
package mainimport (
"fmt"
)func main() {
foo := [3]int{1, 2, 3}for i, v := range foo {
fmt.Printf("index: %v value: %v\n", i, v)
}
}
```#### Splitting a string
##### Perl
```perl
my @list = split ',', 'a,b,c'
```##### Go
[https://play.golang.org/p/RXUdiKhZsjG](https://play.golang.org/p/RXUdiKhZsjG)
```go
package mainimport (
"fmt"
"strings"
)func main() {
mySlice := strings.Split("a,b,c", ",")
fmt.Printf("%v", mySlice)
}
```#### Iterating Over a Hash/Map
##### Perl using keys
```perl
my %hash = ( key_1 => 'foo', key_2 => 'bar', );
for my $key ( keys %hash ) {
printf( "key: %s value: %s\n", $key, $hash{$key} );
}```
##### Go using only primary return value
```go
package mainimport (
"fmt"
)func main() {
myMap := map[string]string{"key1": "foo", "key2": "bar"}for k := range myMap {
fmt.Printf("key: %s value: %s\n", k, myMap[k])
}
}
```* [Go Playground](https://go.dev/play/p/qHcGFM1YRbF)
##### Perl using each
```perl
my %hash = ( key_1 => 'foo', key_2 => 'bar', );
for my $key, $value ( each %hash ) {
printf( "key: %s value: %s\n", $key, $value );
}```
##### Go using both primary and secondary return values
```go
package mainimport (
"fmt"
)func main() {
myMap := map[string]string{"key1": "foo", "key2": "bar"}for k, v := range myMap {
fmt.Printf("key: %s value: %s\n", k, v)
}
}
```* [Go Playground](https://go.dev/play/p/01_1pFznIHQ)
##### Perl: using values
```perl
my %hash = ( key_1 => 'foo', key_2 => 'bar', );
for my $value ( values %hash ) {
printf( "value: %s\n", $value );
}
```##### Go: ignoring primary return value, using only secondary return value
```go
package mainimport (
"fmt"
)func main() {
myMap := map[string]string{"key1": "foo", "key2": "bar"}for _, v := range myMap {
fmt.Printf("value: %s\n", v)
}
}
```* [Go Playground](https://go.dev/play/p/UWqh6M4dGB6)
#### Checking if a Hash/Map Key Exists
##### Perl
```perl
my %pages = ( home => 'https://metacpan.org' );
if ( exists $foo{home} ) {
...
}```
##### Go
[https://stackoverflow.com/a/2050629/406224](https://stackoverflow.com/a/2050629/406224)
```go
package mainimport "fmt"
func main() {
pages := make(map[string]string)
pages["home"] = "https://metacpan.org"
if _, ok := pages["home"]; ok {
fmt.Println("ok")
}
}
```#### Using a Hash/Map to Track Seen Things
##### Perl
```perl
my %seen;
$seen{sunrise} = 1;
if ( exists $seen{sunrise} ) {
...
}
```##### Go
[https://go.dev/play/p/d1RTCE1pmaH](https://go.dev/play/p/d1RTCE1pmaH)
```go
package mainimport "fmt"
func main() {
seen := make(map[string]struct{})
seen["sunrise"] = struct{}{}
if _, ok := seen["sunrise"]; ok {
fmt.Println("I have seen the sunrise")
}
}
```The motivation here is that if the value has no inherent meaning, it could be
confusing to assign it something which could convey a meaning, like `true` or
`false`. There may be a small performance gain in terms of memory when using
`struct{}`, but it may not be any faster.
[https://gist.github.com/davecheney/3be245c92b61e5045f75](https://gist.github.com/davecheney/3be245c92b61e5045f75)#### Deleting a Hash/Map Key
##### Perl
```perl
my %pages = ( home => 'https://metacpan.org' );
delete $pages{home};
```##### Go
```go
package mainimport "fmt"
func main() {
pages := make(map[string]string)
pages["home"] = "https://metacpan.org"
delete(pages, "home")
}
```#### Getting a List of Hash/Map Keys
##### Perl
```perl
my %pages = ( home => 'https://metacpan.org' );
my @keys = keys %pages;
```##### Go
[https://go.dev/play/p/Z8OlHN7Q3GY](https://go.dev/play/p/Z8OlHN7Q3GY)
```go
package mainimport (
"fmt"
)func main() {
pages := make(map[string]string)
pages["home"] = "https://metacpan.org"var keys []string
for k := range pages {
keys = append(keys, k)
}
fmt.Printf("%+v", keys)
}
```#### Slices:
##### Perl
```perl
my @array = (0..5);
my @slice = @list[2..4];
```##### Go
```go
array := [6]int{0, 1, 2, 3, 4, 5}
var slice []int = array[2:4]var myslice []int // create an empty slice of integers
var nothing []string // create an empty slice of strings
```Note that arrays in Go have a fixed size, whereas slices are dynamically sized.
Also:
> A slice does not store any data, it just describes a section of an underlying array.
>
> Changing the elements of a slice modifies the corresponding elements of its underlying array.
>
> Other slices that share the same underlying array will see those changes.See [https://tour.golang.org/moretypes/8](https://tour.golang.org/moretypes/8)
Note also that slices in Go can use defaults for lower and upper bounds. That
means that for the array of 10 integers `var a [10]int`, the following slices
are equivalent:```go
var a [10]inta[0:10] // explicit lower to upper bound
a[:10] // use default lower bound (0)
a[0:] // use default upper bound (0)
a[:] // use default upper and lower bounds (0 and 10)
```Note that the lower bound is the starting point in the index (ie 0) and the
_length_ of the slice is the upper bound, which is why the entire slice
consists of `a[0:10` and _not_ `a[0:9]`.See [https://tour.golang.org/moretypes/10](https://tour.golang.org/moretypes/10)
#### Appending Slices:
##### Perl
```perl
my @array = (0..5);
my @slice = @list[2..4];
push @slice, 11, 12;
```Note that in Perl, a slice of an array is also an array, so there's no need to
make a distinction between the two.##### Go
```go
array := [6]int{0, 1, 2, 3, 4, 5}
var slice []int = array[2:4]
slice = append(slice, 11, 12)
```In Go, if you want to add two slices together, you'll need to treat the second
slice as a variadic parameter (`...`).```go
package mainimport "fmt"
func main() {
first := []int{1, 2}
second := []int{3, 4}
total := append(first, second...)
fmt.Printf("%+v", total)
}
```See [https://go.dev/play/p/ylbpv1KDjzE](https://go.dev/play/p/ylbpv1KDjzE)
### Dumping Data Structures
#### To your terminal
##### Perl
```perl
use strict;
use warnings;
use feature qw( say );use Data::Printer; # exports p() and np()
my %foo = ( a => 'b' );
p( %foo );# or
say np( %foo );
```##### Go
```go
package mainimport "fmt"
func main() {
var config struct {
user string
pass string
}config.user = "florence"
config.pass = "machine"fmt.Printf("%+v", config)
return
}
```Or:
```go
package mainimport "github.com/sanity-io/litter"
func main() {
var config struct {
user string
pass string
}config.user = "florence"
config.pass = "machine"litter.Dump(config)
return
}
```Or:
```go
package mainimport (
"encoding/json"
"fmt"
"log"
)func main() {
data := []string{"one", "two", "three"}
fmt.Println(prettyJSON(data))
}func prettyJSON(target any) string {
data, err := json.MarshalIndent(target, "", " ")
if err != nil {
log.Fatalf("Cannot create pretty json from %v: %v", target, err)
}
return string(data)
}
```[https://play.golang.org/p/FbSfHRNoVfP](https://play.golang.org/p/FbSfHRNoVfP)
#### To disk (write)
##### Perl
```perl
use Data::Printer; # exports np()
use Path::Tiny qw(path);my @list = ( 1..3 );
path('/tmp/foo.txt')->spew( np( @list ) );
```##### Go
```go
package mainimport (
"log"
"os""github.com/sanity-io/litter"
)func main() {
list := [3]int{1, 2, 3}
err := os.WriteFile("/tmp/foo.txt", []byte(litter.Sdump(list)), 0666)
if err != nil {
log.Fatal(err)
}
}
```[Go Playground](https://go.dev/play/p/qjgoHlvYWfY)
#### To disk (append)
##### Perl
```perl
use Data::Printer; # exports np()
use Path::Tiny qw(path);my @list = ( 1..3 );
path('/tmp/foo.txt')->append( np( @list ) );
```##### Go
```go
package mainimport (
"log"
"os""github.com/davecgh/go-spew/spew"
)func main() {
list := [3]int{1, 2, 3}file, err := os.OpenFile(
"/tmp/foo.txt",
os.O_APPEND|os.O_CREATE|os.O_WRONLY,
0666,
)if err != nil {
log.Fatal(err)
}spew.Fdump(file, list)
file.Close()
}
```### File Operations
#### Creating a directory
##### Perl
```perl
use Path::Tiny qw( path );
use Try::Tiny qw( catch try );my $dir = '.my-perl-cache';
try {
path($dir)->mkpath( { chmod => 0644 });
}
catch {
die sprintf "Could not create dir %s because of %s", $dir, $_;
};
```##### Go
```go
package mainimport (
"log"
"os"
)func main() {
cacheDir := ".my-go-cache"
if err := os.MkdirAll(cacheDir, 0644); err != nil {
log.Printf("Cannot create dir %s because %v", cacheDir, err)
}
}
```#### Read an Entire File
##### Perl
```perl
use Path::Tiny qw( path );my $content = path('path', 'to', 'file')->slurp_utf8;
```##### Go
Note that in this case `dat` is `[]byte`
```go
package mainimport (
"fmt"
"log"
"os"
)func main() {
err := os.WriteFile("test.txt", []byte("Hello, Gophers!"), 0666)
if err != nil {
log.Fatal(err)
}dat, err := os.ReadFile("test.txt")
if err != nil {
log.Fatal(err)
} else {
fmt.Println(string(dat))
}
}
```[https://go.dev/play/p/3dCR2NJuZOF](https://go.dev/play/p/3dCR2NJuZOF)
#### Read First Line of a File
##### Perl
In the Perl example, we'll chomp the line to make explicit that newlines need to be handled.
```perl
use Path::Tiny qw( path );my $first_line;
my $fh = path('/path/to/file')->openr_utf8;while (my $line = <$fh>) {
$first_line = $line;
chomp $first_line;
last;
}print $first_line, "\n";
```##### Go
`scanner.Scan()` helpfully trims newlines for us.
```go
import (
"fmt"
"log"
)func main() {
file, err := os.Open("/path/to/file")
if err != nil {
log.Fatal(err)
}
defer file.Close()scanner := bufio.NewScanner(file)
var firstLine string
for scanner.Scan() {
firstLine = scanner.Text()
break
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}fmt.Println(firstLine)
}
```### Flow Control
#### if
##### Perl
```perl
if ( $foo > 1 ) {
print 'bar';
}
```##### Go
```go
if foo > 1 {
fmt.Println("bar")
}// parens are optional
if foo > 1 {
fmt.Println("bar")
}
```#### else
##### Perl
```perl
if ( $foo > 1 ) {
print 'bar';
}
else {
print 'baz';
}
```##### Go
```go
if foo > 1 {
fmt.Println("bar")
} else {
fmt.Println("baz")
}
```#### elsif / else if
##### Perl
```perl
if ( $foo > 1 ) {
print 'bar';
}
elsif ( $foo < 10 ) {
print 'baz';
}
```##### Go
```go
if foo > 1 {
fmt.Println("bar")
} else if foo < 10 {
fmt.Println("baz")
}
```### Loops
#### For loops
##### Perl
```perl
my $sum;
for ( my $i = 0 ; $i < 10 ; $i++ ) {
$sum += $i;
}
```##### Go
```go
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
```#### While loops
##### Perl
```perl
my $sum = 0;
my $i = 0;
while ( $i < 10 ) {
$sum += $i++;
}
```##### Go
```go
// The init and post statement in a Go for loop are optional.
sum := 0
i := 0
for i < 10 {
sum += i
i++
}
```#### Infinite loops
##### Perl
```perl
while (1) {
}
```##### Go
```go
for {
}
```#### Short-circuiting a loop iteration
Perl
```perl
while (1) {
...
next if $foo eq 'bar';
...
}
```Go
```go
for {
if foo == "bar" {
continue
}
// Won't get here if continue is called
}
```Note that `continue` will immediately begin the next iteration of the innermost `for` loop.
#### Terminating a loop
Perl
```perl
while (1) {
...
last if $foo eq 'bar';
...
}
```Go
```go
for {
if foo == "bar" {
break
}
// Won't get here if break is called
}
```Note that `break` will exit the enclosing loop at the point where it is called.
### Regular Expressions
Match a string prefix.
#### Perl
```perl
my $str = '5.5.1';
if ( $str =~ m{\A5\.5} ) {
print "ok\n";
}
```#### Go
[https://go.dev/play/p/rpACvjzRt-K](https://go.dev/play/p/rpACvjzRt-K)
```go
package mainimport (
"fmt"
"regexp"
)func main() {
re := regexp.MustCompile(`\A5\.5`)
str := "5.5.1"
if re.MatchString(str) {
fmt.Println("ok")
}
}
```[https://go.dev/play/p/-NXI8SjMjJQ](https://go.dev/play/p/-NXI8SjMjJQ)
```go
package mainimport (
"fmt"
"strings"
)func main() {
str := "5.5.1"
if strings.HasPrefix(str, "5.5") {
fmt.Println("ok")
}
}
```### Today's Date as YYYY-MM-DD
#### Perl
```perl
use DateTime ();
print DateTime->now->ymd;
```#### Go
[https://play.golang.org/p/k0ijssDDOU6](https://play.golang.org/p/k0ijssDDOU6)
```go
package mainimport (
"fmt"
"time"
)func main() {
fmt.Println(time.Now().Format("2006-01-02"))
}
```### Functions
#### Functions without signatures
##### Perl
```perl
sub foo {
print 'ok';
}
foo();
```##### Go
```go
package mainimport "fmt"
func main() {
foo()
}
func foo() {
fmt.Println("foo")
}
```### Running Tests
#### Perl
```shell
$ perl Makefile.PL
$ make
$ make test
```or
```shell
$ prove -l t/path/to/test.t
```Use the `-v` flag for verbose output:
```shell
$ prove -lv t/path/to/test.t
```#### Go
```shell
$ go test
```Use the `-v` flag for verbose output:
```shell
$ go test -v
```If you're using `vim-go`, use `:GoTest` either from your `foo.go` or
`foo_test.go`. (Note, you can also use `:GoAlternate` to toggle between the
two files.)To test a subset of functions:
```shell
$ go test -run regexp
```If you're using `vim-go`, move your cursor to the name of the function you'd
like to test. Running `:GoTest` here will run the function you're currently
in.To bypass Go's test caching:
```shell
$ go test -count=1
```### Debugging
#### Printing Stack Traces
##### Perl
```perl
use Carp qw( longmess );
print longmess();
```##### Go
```go
package mainimport (
"runtime/debug"
)func main() {
debug.PrintStack()
}
```### Sleep
#### Perl
```perl
sleep 60;
```#### Go
```go
package mainimport (
"time"
)func main() {
time.Sleep(60 * time.Second)
}
```### Parsing URIs
#### Perl
```perl
use Mojo::URL ();
my $url = Mojo::URL->new('https://www.google.com/search?q=schitt%27s+creek');
print $url->query->param('q'); # schitt's creek
```#### Go
```go
import (
"fmt"
"log"
"net/url"
)func main() {
url, err := url.Parse("https://www.google.com/search?q=schitt%27s+creek")
if err != nil {
log.Fatal(err)
}
q := url.Query()
fmt.Println(q.Get("q")) // schitt's creek
}
```### Changing URI Query Params
#### Go
```go
package mainimport (
"fmt"
"net/url"
)func main() {
url, _ := url.Parse("https://example.com")q := url.Query()
q.Set("activity", "dance")
q.Set("type", "flash")
url.RawQuery = q.Encode()fmt.Println(url)
}
```### Command Line Scripts
#### Print first argument to a script
##### Perl
```perl
print $ARGV[0], "\n" if $ARGV[0];
```##### Go
```go
package mainimport (
"fmt"
"os"
)func main() {
if len(os.Args) > 1 {
fmt.Printf("%v\n", os.Args[1])
}
}
```#### Exiting a script
##### Perl
```perl
exit(0);
```##### Go
```go
import("os")os.Exit(0)
```