Swift vs Go

Swift vs Go

Creating Variables

Jumping from the Swift programming language to the Go programming language is easy, as I discovered. But how does creating variables compare?

Variable Declaration (without assignment)

In Swift, first we declare whether the variable will change or not, so we choose let or var. Second, we choose a variable name, followed by some semicolons and the type of the variable. Example: var myNumber : Int? . Note that we have to add a ‘?’ to make this an optional, because Swift only allows variable declaration by itself if the variable is optional.

In Go, the variable is expected to change, so we start with ‘var’, then choose a variable name, and finally declare the variable type. Example: var myNumber int.

Variable Assignment

In both Swift and Go, the syntax is the same: variable = assignment. For example, myNumber = 3.

Variable Declaration and Assignment (short version)

In Swift, we begin by declaring whether the variable can change, using ‘let’ or ‘var’, then do the same as variable assignment. Example: let myNumber = 3.

In Go, we start with the variable name, and then use ‘:=’ followed by the assignment. Example: myNumber := 3.

Variable Declaration and Assignment (long version)

Sometimes, you may want to specify a variable type, instead of implying it. For example, if you know the compiler will interpret an unspecified variable as a float, but you want it to be a double.

In Swift, we take the short version, let myNumber = 3 , and add a scodeicolon followed by the variable type after the variable name. Example: let myNumber : Int = 3 .

In Go, we take the variable declaration and add = assignment. Example: var myNumber int = 3 .

Method Signatures

There are a few syntax differences between Swift and Go with regards to method names/signatures, but beyond this they are very similar.

Function without parameters or return values

In both swift and Go, the basic function is the same; first declare ‘func’, then choose a function name followed by (), and finish with the content in brackets. Example:

func functionName() {
//content here
}

In Go, it is also possible to set the function like you would set a variable. We specify the name, use ‘:=’, then declare func followed by (). Example:

functionName := func() { //content here }

Function with 1 parameter

In Swift, to add a parameter, in () we add a type declaration followed by the variable name; in Go, we add the same things, but in opposite order. Example in Swift:

func functionName(Int varName) {
//content here
}

Example in Go:

func functionName(varName int) {
//content here
}

Function with multiple parameters

In both languages, we can add parameters by adding a comma after our first parameter, then using the same syntax for a second parameter.

Example in Swift:

func functionName(Int varName, bool secondVarName) {
//content here
}

Example in Go:

func functionName(varName int, secondVarName bool) {
//content here
}

In Go, if all the parameters are the same type, we only need to specify the type on the last parameter–the other parameters will be inferred to have the same type! Example:

func functionName(firstInt, secondInt int) {
//content here
}

Function with 1 return value

In both languages, any returned parameters/variables are declared after (). In Swift, we use -> to point to the return type; in Go, we can simply declare the return type. Example in Swift:

func functionName() -> Int {
return 3
}

Example in Go:

func functionName() int {
return 3
}

In Go, you can also set the return type to have a variable name. What use is this? We can set and alter this variable, and when the function returns, we don’t have to say ‘return this value’, the function will automatically return the variable. Example:

func functionName() (x int) {
x = 3
return
}

Here, the function will return 3, because we created x and told the function that this particular variable will be returned when the function is returned.

Function with multiple return values

To return multiple values, make sure your first return value is surrounded by (). After your first return value, declare an additional value the same way you declared the first. Example in Swift:

func functionName() -> (Int, Int) {
//content here
}

Example in Go:

func functionName() (int, int) {
//content here
}

Alternate example in Go:

func functionName() (x int, y int) {
//content here
}

Similar to parameters, if all your return types in go are the same and you name your variables, you only need to declare the type for the final value; all others will be inferred. Example:

func functionName() (x, y int) {
//content here
}

Functions with multiple parameters and return values

Here are a couple examples to showcase multiple parameters and return values in a method signature:

Example in Swift:

func functionName(Int x, Int y) -> (Int, Int) {
return (x + y, x * y)
}

Example in Go:

func functionName(x, y int) (a, b int) {
a = x + y
b = x * y
return
}

Arrays & Slices

When it comes to Arrays and Dictionaries, there is one main difference between Swift and Go: Dealing with memory. While in Swift you can count on the compiler to handle memory for you, in Go you must specify and manage memory yourself.

Empty Arrays

In Swift, we start with ‘let/var’, depending on if the array will change, followed by a name. To specify type, we use : [type], like a standard variable. To make it an empty array, we then say = []. For example: var basicArray : [Int] = []. Note that this array has an dynamic size that conforms to what you need.

In Go, we must go about this by defining memory. We again start with ‘var’ and the name of the array, then declare the size in [], followed by the type (without brackets). Example: var basicArray [5]int. Here, we have created an empty array that can hold five numbers.

Set an Empty Array

In Swift, we can either add items/arrays individually to our empty array, or manually write out the array and set it to the variable. Example of the former: basicArray.append(3) or basicArray.append(contentsOf: [1,2,3,4,5]). Example of the latter: basicArray = [1,2,3,4,5]. Note that appending adds the item(s) to the end of the array.

In Go, the unset array is not necessarily ’empty’, but has default or nil values; we must set each item in the array individually. Example: basicArray[0] = 1.

Set an Array on Creation

In Swift, instead of setting our array = [], we set it equal to a set of values we desire. For example: var basicArray : Int = [1, 2, 3, 4, 5].

In Go, we simply add a list of desired elements, in {}, at the end of our declaration. Example: var basicArray [5]int{1, 2, 3, 4, 5}.

Increase Size of Array

In Swift, because memory is handled for you, you can increase the size of an array by setting it to a larger array, or simply appending another element. For example:

var basicArray : Int = [1, 2, 3, 4, 5]
basicArray.append(6)

In Go, however, we cannot innately increase the size of the array; we must find a work around, such as creating a new array with more memory, and transferring over the values. For example:

var basicArray [5]int{1, 2, 3, 4, 5}
var newArray [6]int{basicArray[0], basicArray[1], basicArray[2], basicArray[3], basicArray[4], 6}.

Note that if this were a large array, it would be wiser to use a loop to transfer over the values.

Slices

Wouldn’t it be nice if there was something in Go that acted like an array in Swift? Something that could dynamically resize the array for you? Well good news–there is! And they are called slices. The initialization is the same as for arrays, but without specifying the size: var basicArray []int{1, 2, 3, 4, 5} . To add to the slice, we can simply use an append function, which takes an array and additional input and returns a new array: basicArray = append(basicArray, 6,7,8).

This seems kind of familiar, does it not? That’s because array in Swift is comparable to a slice in Go.

Dictionaries/Maps

In Swift, Dictionaries let you assign a variable to a key value; in Go, maps are used in the same manner. While the names are different, functionally the two are the same. Here we will discuss the syntax differences between the two.

Create Empty Dictionary/Map

In Swift, a dictionary is created similar to an array, such as var myArray : [Int] = [], except we declare two types (separated by a semicolon) instead of one. The first type is the key type, and the second type is the variable type. For example: var myDiction: [String : Int] = [:]. Note that we also add a semicolon to the empty brackets on the right side.

In Go, we can use the function make() to create empty arrays and dictionaries. The function requires an argument of the array or map you want to make; the syntax for a map is map[keyType]variableType . Put all this together, and we get something such as: myDiction := make(map[string]int) .

Create Dictionary/Map with Values

In Swift, instead of setting a dictionary equal to an empty list, we set it equal to an array of key/value pairs. For example: var myDiction: [String : Int] = ["alpha":1, "beta":2, "gamma":3]. Keep in mind that “alpha”, “beta”, and “gamma” are the keys here.

In Go, we no longer need to use the ‘make’ function, since the function is only for creating an empty array. Instead, we use the map function and add an array of values at the end. For example: myDiction := map[string]int{"alpha": 1, "beta": 2, "gamma": 3}. Here, “alpha”, “beta”, and “gamma” are still the keys.

Add a Value/Change a Value

The syntax for adding or changing a value in Swift and Go is… exactly the same. The dictionary/map name, followed by the key in “[]”, equals the desired value. Example: myDiction["delta"] = 4 . This is valid if delta has been used as a key, in which case the value is changed, or if delta has not been used as a key, in which case the key/value pair is added to the dictionary.

Parsable Structs

Structs are a basic element of object-oriented languages, and usually simple to implement. But when dealing with Swift and Go, one thing we frequently run into is parsing with json–that means creating a struct that can parse json data. How can we do this?

Basic Structs

In both Swift and Go, we start a struct with ‘struct’ followed by the struct name (reverse order in Go). In the following lines, between the brackets, we have a list of variables, declared differently in each language. In Swift, we declare the variables without setting them; for example, ‘let var: string!’. For structs in Swift, it is important to clarify if the variable can be nil, so the declaration should end with ‘!’ or ‘?’. In Go, we simply give the variable name followed by variable type — no extra characters.

Swift example:
struct structName {
var firstVariable: String!
}

Go example:
structName struct {
firstVariable String
}

Make Structs JSON Structs

To make Swift struct codable, after the struct name, we add ‘:’ followed by the type ‘Codable’. Done. In Go, for each variable we need to add a line defining the json key, in the form `json:”key”` , making sure to use the ` character.

Swift example:
struct structName: Codable {
var firstVariable: String!
}

Go example:
structName struct {
firstVariable String `json:"variableKey"`
}

But where do we set the variable key in Swift? Actually, the variable name is the variable key in Swift.

Use Struct to Parse JSON into a Variable

Now that we have an appropriate struct, how can we use it to turn json into something useful? In Go, we do ‘json.NewDecoder’ and pass the json data as a parameter; this creates a decoder that will decode the desired json. We then call ‘Decode’ and pass a variable that conforms to our struct (and put ‘&’ at the start of the variable). Don’t forget to import “encoding/json” to use the json library.

Example in Go:
receptorVariable := structName{}
json.NewDecoder(jsonData).Decode(&receptorVariable)

In Swift, it’s a bit more complicated, because we must use a do/catch block. Inside the ‘do’ section, create a new variable, and set it equal to ‘try JSONDecoder().decode’ and pass the struct followed by ‘.self’, and for the second parameter pass the json data.

Swift example:
do {
let receptorVariable = try JSONDecoder().decode(structName.self, from: jsonData)
} catch {
print("JSON parsing failed") //something to catch the failed JSON parsing
}

Testing

Unit testing is crucial for any project; but the two types of testing found in Swift and Go are fundamentally different. In Swift, the testing is assertion-based, while the testing in Go is output-based. However, these two things are very easy to switch between.

Testing in Swift

In a separate target (usually a target with ‘test’ in the name), we create a class that is a subclass of ‘XCTestCase’, and import XCTest at the top. To write the actual test, we declare ‘func’ followed by a function name that begins with ‘test’. In the function, we can run the desired code, and then add an XCTAssert function. There are several variations on this function, such as asserting true or false; the bottom line is, you can use it to inform XCode what conditions are needed to pass. Example:

import XCTests
class sampleTests: XCTestCase {


func testAddition() {
var x = 3
x += 4
XCTAssertTrue(x == 7)
}


}

Testing in Go

In Go, you don’t have to deal with targets, just create a new file that has the word ‘test’ in its name; for example, ‘sample_test.go’. At the top, include ‘package main’ and import ‘testing’. In this file, write a function that starts with ‘Test’ and takes (t *testing.T) as a parameter. Then run the desired code in this function. To determine if the test passes, first run a statement that checks the conditions needed to pass, then run a t.Fatal() function. The t.Fatal tells the program that the test has failed; the programmer must create conditions that determine if this line if programming is run. Example:

package main
import (
"testing"
)

func TestAddition(t *testing.T) {
x := 3
x += 4
if x != 7 {
t.Fatal("Incorrect Sum").
}
}

The Difference

So what is the fundamental difference between these two testing procedures? In Swift, we write SucceedsOrFails(condition), while in Go, we write Condition(succeedsOrFails). Note that the above testing functions (XCTAssertTrue and t.Fatal) are just a few of the many testing functions.

Running Tests

In Swift, presumably you are using XCode, in which case you can simply press the diamond next to your test function to run the test, or at the top of the class to run every test in the class. You can also go to the test section in the left window menu (the icon is a diamond with a dash in the middle) and run any and all test in the project.

In Go, simply use the command line to reach the desired folder, then run ‘go test’ to run every test file, or run ‘go test addition_test.go’ to run tests in a specific file, in this case called ‘addition_test.go’.

Setup Tests

In both Swift and Go, you can add a function that will run before every test in a class/file; this is useful if you would otherwise run the same block of code at the start of every test. In Swift, this is accomplished with ‘override func setUp() { }’, while in Go, we use ‘func init() { }’. These are just a couple of examples of helper functions that can be used to make the testing process easier.

Basic Flow Control

Time for some basic flow control. In this post, we will look at if statements, switch blocks, and for loops in Swift and Go.

If Statements

In both Swift and Go, if statements have the same format: if something { execute } else { do something else }, where the else statement is optional. Example:

if 3 > 2 {
//do something
} else {
//this should not execute
}

Switch Blocks

In both Swift and go, the switch statement starts with ‘switch’ followed by the switch variable and brackets. In the brackets, we list out the cases. In both languages, if something executes in a case, we do not write break; however, if nothing executes in Swift, we must write ‘break’ (in Go we can leave the case blank). Additionally, while a ‘default’ case is mandatory in Swift, it is optional in Go.

Swift Example:

let x = 4
switch x {
case 1:
break
case 4:
print("success")
default:
break
}

Go Example:

x := 4
switch x {
case 1:
case 4:
fmt.Println("success")
}

For Loops

Go uses the traditional f0r loop format of (define variable, loop termination condition, loop iteration). However, Swift cannot use this format; instead, the we use ‘for’ followed by the variable declaration, followed by a list of numbers separated by …, ..<, or ..> , which indicate a range of values through which we iterate.

Go example:

for x := 0; x < 4; x-- {
//Do something
}

Swift example:

for x in 0..<4 {
//do something
}

For Loops with List

In both Swift and Go, a for loop can iterate through a list of objects. In Swift we accomplish this by creating the list, such as an array, and saying ‘for variableName in (our array). In Go, a for loop that iterates through a list is set up to iterate through a dictionary. Thus, if we have a dictionary, we can say ‘for keyName, valueName := range ourDictionary’ and iterate as such. If, however, we have an array or splice that we wish to iterate through, we must replace ‘keyName’ with ‘_’.

Swift example

for myWord in ["start", "middle", "end"] {
print(myWord)
}

Go example with dictionary

for myKey, myWord := range map[int]string{1: "start", 2: "middle", 3: "end"} {
fmt.print{"%d, %s", myKey, myWord}
}

Go example with array

for _, myWord := range []string{"start", "middle", "end"} {
fmt.print{"%s", myWord}
}