Practical intro to Typescript (Part 1)

Classes in TS

Typescript classes are just a form of sugar syntax for prototypes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class User {
private firstName: String;
private lastName: String;
age: Age;
// By Default everything is public, but we can specify it
public address: String;
// We won't be able to change this property once we assign the value
readonly unchangableProperty: String;
// Static property, only accesible on the class itself
static readonly maxAge = 50;

constructor(first: String, last: String) {
this.firstName = first;
this.lastName = last;
this.unchangableProperty = last;
}

getFullName(): String {
return this.firstName + " " + this.lastName;
}
}

const user = new User("Lucas", "Contre");
console.log(user.getFullName());
console.log(User.maxAge);

Interfaces, Inheritance and Classes

1
2
3
4
5
6
7
8
9
// Inheritance
class Admin extends User {}
interface UserIface {
getFullName(): String;
}

class User implements UserIface {
// This class must implement the interface
}

Generics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const addId = <T extends object>(obj: T) => {
// The `extends` is not neccesary but is nice when we konw which type we want to receive
const id = Math.random().toString(16);
return {
...obj, // Unpack all the properties of the object
id,
};
};

// We can now do somehting like this
const user = { name: "Jack" };
const result = addId(user);
// But it would be nicer to do something like
interface UserIface {
name: String;
}
const nicerUser: UserIface = {
name: "Jack Sparrow",
};
const saferResult = addId<UserIface>(user);

Generics with Interfaces

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface PersonInterface<T, V> {
name: string;
data: T;
age: V;
}

const person: PersonInterface<{ meta: String }, Number> = {
name: "John",
age: 33,
data: {
meta: "Hello",
},
};

const person2: PersonInterface<String[], String> = {
name: "Juan",
age: "33",
data: ["s1", "s2"],
};

Enums ? Yes, Enums

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
enum Status {
NotStarted,
InProgress,
Done,
}

console.log(Status.NotStarted); // 0
console.log(Status.InProgress); // 1
console.log(Status.Done); // 2

// Enums are a type
let initialStatus: Status = Status.NotStarted;

initialStatus = "Hi"; // This won't work
initialStatus = Status.Done; // This will

// A common use case would be
interface Task {
id: string;
status: Status;
}

Of course we are missing classic things like loops and some specific types, but I guess you can figure out those by yourself.

Most examples where taken from this video


Author: Lucas Contreras

Practical intro to Typescript (Part 0)

The “Hello world”

If you are reading this post you probably already know what Typescript is. So here’s just a practical guide for Typescript. Feel free to come back as many times as you like while you get use to the language

Variables and Types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Variables
let hello = "world"; //TS infers the type

let hola: String = "mundo"; // Here we explicitly the type
// errorMsg can be either a String or a null
let errMsg: String | null = "This is an error message";
errMsg = null; // This is totally fine
//hola = 123 // This is not possible since I must keep the same type for all variables
hola = "another string"; // This is ok !
const hallo = "asd"; // Here I'm defining a constant, so not only i can't change the type but neither the value

// Type Aliases
type IDs = String[]; // This is just a 'human name' for the string type
// It's really normal to see things like this:
type MaybeIDs = IDs | null; // Things of Type MaybeIDs can be either IDs or null

// Why does any exist ? Hmm
let dew: any = "This could not be a string";
// We also have the unknown type which is pretty much as any but it can not be assigned
let theFutureOfArgentina: unknown = "1";
let s1: String = dew; // This is ok
let s2: String = theFutureOfArgentina; // This is fails
// There still some hope
let s2: String = theFutureOfArgentina as string; // This will not fail .. for now
// We can also do things like
let num: Number = theFutureOfArgentina as unknown as number

Functions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Functions
const getFullName = (first: String, last: String): String => {
return first + " " + last;
};
console.log(getFullName("Lucas", "Contre"));
const getFullNameJS = (first, last) => {
// This function is just Js inside Ts
// This will still work and we will just get a warning but it is not the best way to write TS
return first + " " + last;
};

const noReturn = (): void => {
// When return void when there's no return
console.log(getFullNameJS("Lucas", "Contre"));
};

// We can also write functions that never returns
const oblivio = (): never => {
throw "never";
};

Stick to the types unknown and void. Avoid using any in any case and
you will probably never use never.

Objects in TS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Create Objects like in JS
const userJS = {
name: "Lucas",
age: 25,
};
const user2JS = {
name: "Tom",
};

// Create Objects in TS (defining the type)
const userTS: { name: String, age: Number } = {
name: "Lucas",
age: 25,
};

const user2TS: { name: String, age: Number } = {
name: "Tom",
age: 30, // Now we need to comply to the Type
};

Interfaces

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Lets try to do this a bit more nicer with Interfaces
interface User {
// Interfaces for objects ? It look like, yes.
name: String;
dogsIDs: IDs;
age: Number;
address?: String; // The '?' indicates that this is optinal
getName(): String;
}

const nicerUserTS: User = {
dogsIDs: ["dog1", "dog2"],
name: "Brad",
age: 12,
getName() {
return "My name is " + this.name;
},
};

Author: Lucas Contreras

Notes DDD Quickly (Part 1)

Quick DDD Notes

This notes have been taken from the free Domain Driven Design Quickly. I highly recommend reading the book. I have found it to be a concise summary of the original book. In this summary I will be just mentioning/listing the best ideas of the all the concepts mentioned in the book.

Disclaimer: There is no strict narrative to this post, just useful ideas written in a sentence or two to Ctrl+F whenever you hesitate before making a design decision.

Model

The, so called, Model is the abstraction of the Domain.

The Domain comes to light talking to the Domain Experts, which are the business experts.

The abstraction is the model. This is not a diagram but the idea that the diagram is intended to convey.

Sometime the domain contain too much, so we must leave parts out of our model.

We should be able to communicate the Model.

  • Graphical Diagrams
  • Writing
  • Language

Only once we are sure we can communicate the model we can start to design our
code.

Software Design: The big pictures, where the walls of a house are going to
be placed.

Code Design: Detail, where certain painting is going to be hang.

Code design mistakes are easy to correct, the totally opposite happens with Software design mistakes.

Analysis Paralysis: Teams members so afraid of making any design decision that end up making no progress at all.

The Ubiquitous Language

One different person uses different words when writing than when speaking. Sometimes, even in the same sentences.

A core principle of DDD is to use a language based on the model.

That language and the models are strongly interconnected with one another. A change in the language is a change in the model.

Domain experts should easily understands the both the language and the model.

The language can be expressed in text, diagrams, etc. (UML diagrams are not recommended by this book)

Model Driven Design

Very important details are discovered during the design and implementation process. A Model that is truthful to the Domain can turn out to have serious problems with object persistence, or unacceptable performance behaviour. The Model should be constructed with an eye open to the software and design considerations. Developers should be included in the modeling process. This ensures that the model can actually be implemented. “Procedural programming does not suit well Model driven Design”

The building blocks of a Model Driven Design

Model Driven Design

Layered Architecture

A common architectural solution for domain-driven designs contain four conceptual layers:

User Interface (Presentation Layer): Responsible for presenting information to the user and interpreting user commands.

Application Layer: This is a thin layer which coordinates the application activity. It does not contain business logic. It does not hold the state of the business objects, but it can hold the state of an application task progress.

Domain Layer: This layer contains information about the domain. This is the heart of the business software. The state of business objects is held here. Persistence of the business objects and possibly their state is delegated to the infrastructure layer.

Infrastructure Layer: This layer acts as a supporting library for all the other layers. It provides communication between layers, implements persistence for business objects, contains supporting libraries for the user interface layer, etc.

Entities

Entities are necessary objects in the domain model and should be considered from beginning of the modeling.

An Object must be an Entity as long as it has identity. For these objects is not the attributes that matter, but the thread of continuity and identity.

Usually the identity is either an attribute of the object, a combination of attributes or an attribute specially created to preserve and express identity, or even a behaviour. The “ID” could be auto generated by a module, could be the PK of a table in a DB or it could be created by the user.

This means of identification may come from outside or it may be created by and for the system, bit it must correspond to the identity distinctions in the model. The model must define what it means to be the same thing.

Beware of considering all objects entities, there may be performance issues. (Consider the case of a drawing App explained in the book)

Value Objects

There are cases where we need to contain some attributes of a domain element we are not interested in which object it is, but what attributes it has. An object that is used to describe certain aspects of a domain, and which does not have identity, is name value object.

It is highly recommendable that these objects are immutable, even more if they are sharable

Value objects should stay thin, making a copy of a V.O should be easy.

Value Objects, can contain other value objects, and they can even contain references to entities. Although V.O attributes of a domain object, that does not mean that it should contain a long list with all the attributes. Attributes can be grouped in different objects. Attributes chosen to make up a V.O should form a conceptual whole.

Value Objects

Services

Some aspects of the domain are not easily mapped to objects,. Objects are generally considered as having attributes, an internal state which is managed by the object, and exhibit a behaviour.

The nouns of the language are easily mapped to objects, the verbs of the language become the part of the behaviour of those objects. But there are some actions in the domain, some verbs, which do not seem to belong to any object. They represent an important behaviour of the domain, so they cannot be neglected or simply incorporated to some of the Entities or Value Objects. Nonetheless, using an OO language, we have to use an object for this purpose.

When such a behaviour is recognized in the domain, the best practice is to declare it as a Service. Such object does not have an internal state, and it purpose is to provide functionality to the domain. The Service can group related functionality which serves Entities and Value Objects.

Services must be declared explicitly, they must encapsulate a concept. We should not create a Service for each operation needed. But when such an operation stands out as an important concept in the domain.

A Service is not about the object performing the service, but is related to the objects the operations are performed on/for. They usually become the point of connection for many objects.

There are 3 characteristics of a Service:

  1. The operation performed by a Service refers to a domain concept which
    does not naturally belong to an Entity or Value Object

  2. The operation performed refers to other objects in the domain.

  3. The operation is stateless

It is easy to confused services which belongs to the domain and those that belong to the infrastructure. (To read more about it please refer to the last part of the “Service” chapter where some examples are provided)

Modules

The model reaches a point where it is hard to talk about as a whole and understanding the relationships and interaction between different parts becomes difficult. For that reason, it is necessary to organize the model into modules.

Using modules in design is a way to increase cohesion and decrease coupling. Modules should be made up of elements which functionally or logically belongs together assuring cohesion. Modules should have wall defined interfaces which are accessed by other modules instead of calling three objects of a module, it is better to access one interface, because it reduces coupling. Low coupling reduces complexity, and increases maintainability. It is easier to understand how a system functions when there are few connections between modules.

It is widely accepted that software code should have a high level of cohesion and low level of coupling.

There are several types of cohesion. Two of the most used are communicational cohesion and functional cohesion .

Communicational cohesion is achieved when parts of the module operate on the same data. It makes sense to group the because there is a strong relationship between them.

Functional cohesion is achieved when all parts of the modules work together to perform a well-defined task. This is consider the best type of cohesion.

Chose modules that tells the story of the system and contain a cohesive set of concepts.

Seek low coupling in the sense of concepts that can be understood and reasoned about independently of each other.

Give the modules names that become part of the Ubiquitous Language. Name of modules should reflect insights into the domain.

To be continue (Aggregates) ->


Author: Lucas Contreras

Channels & Routines - Go Intro (IV)

Channels and Routines

Let’s take a look to the following code. It intends to check if a list of links are online.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func main() {
links := []string{
"https://lucascontre.site",
"http://emby.lucascontre.site",
"https://lucaslois.io",
}
for _, link := range links {
checkLink(link)
}
}

func checkLink(link string) {
_, err := http.Get(link) // Blocking code
if err != nil {
fmt.Println(link,"might be down!")
return
}
fmt.Println(link, "is up!")
}

Go Routine

Every time we run a go program we are launching a go routine. We can think of the go routine as a process that executes our code “line by line”.

We can add concurrency to our Link checker just be adding the work go before executing the checkLink() function.

1
2
3
//  for _, link := range links {
go checkLink(link) // Spawns a new Go Routine
//}

This way Go will launch a new thread (go routine) that executes that function and the main go routine will keep on iterating through the loop. Seems pretty straight forward, but this is far from over. There are a lot of interesting rules, side effects and a lot of theory behind the scenes.

What are go routines doing on our machine

Behind the scenes theres something called the Go Scheduler. The scheduler runs one routine until it finishes or makes a blocking call (like the HTTP request).

1
2
3
4
5
6
graph TD
C(Go Routine)-->B
D(Go Routine)-->B
E(Go Routine)-->B
A(CPU Core) --> B(Go Scheduler)
B-->A

By default the scheduler will try to run everything on one core. So when we have only one cpu we are still actually running one go routine at a time. To run multiple go routines at the same time we will need several cores. But concurrency is not parallelism.

1
2
3
4
5
6
7
8
9
10
graph TD
C(Go Routine)-->B
D(Go Routine)-->B
E(Go Routine)-->B
A(CPU Core) --> B(Go Scheduler)
B-->A
R(CPU Core) --> B(Go Scheduler)
B-->R
G(CPU Core) --> B(Go Scheduler)
B-->G

If you’ve just added the go word to our function and tried to run it, you might have seen that when you run it nothing is printed out. What’s happening is that our main routine (the one that launched our other n child go routines) finished before their children.

To fix this issue we will make a good use of channels.

Channels

Channels are the only way we have to communicate different go routines. We can think of a channels as an in mediator through which we can send data through routines. Channels are tight, which means, that messages that goes through a channel must be of the same type.

Channel implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

func main() {
links := []string{
"https://lucascontre.site",
"http://emby.lucascontre.site",
"https://lucaslois.io",
}
c := make(chan string)
for _, link := range links {
go checkLink(link,c)
}
for i := 0; i < len(links); i++ {
fmt.Println(<-c)
}
// fmt.Println(<-c) // Prints the first msg to arrive
// fmt.Println(<-c) // Prints the second msg to arrive
// fmt.Println(<-c) // Prints the third msg to arrive
// fmt.Println(<-c) // Hangs because is waiting for a msg to be receive to the channel
}

func checkLink(link string, c chan string) {
_, err := http.Get(link)
if err != nil {
c <- link + " Link is down :("
return
}
//fmt.Println(link, "is up!")
c <- link + " Link is up :)"
return
}

We might want to send data from the Main routine through the channel to our child routines or vice versa. For this Go has an special syntax

1
2
3
channel <=-5 // Send the value '5' into this channel
myNumber <- channel // Wait for a value to be sent into the channel. When we get one, assign the value to 'myNumber'
gmt.Println(<-channel) // Wait for a value to be sent into the channel. When we get one, log it out immediately.

An important thing to have in mind is that receiving messages through a channel is a blocking thing.

Repetitive Routines

In case we would like to repeat a routine once it’s done we can re-call it inside the for loop. Also making the the functions that wraps that routine to broadcast the same parameter that’s called on that function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func main() {
links := []string{
"https://lucascontre.site",
"http://emby.lucascontre.site",
"https://lucaslois.io",
}
c := make(chan string)
for _, link := range links {
go checkLink(link,c)
}
for {
go checkLink(<-c, c)
}
// A nicer syntax is
//for i := range c { // This is semantically read as "For each time that channel c gets a value i, then.."
//go checkLink( i, c)
//}

}

func checkLink(link string, c chan string) {
_, err := http.Get(link)
if err != nil {
fmt.Println(link," is down")
c <- link
return
}
fmt.Println(link, " is up!")
c <- link
}

Function Literal

A Function literal in go is the exact same thing as what it would be a Anonymous function in Javascript or Lambda in Python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func main() {
links := []string{
"https://lucascontre.site",
"http://emby.lucascontre.site",
"https://lucaslois.io",
}
c := make(chan string)
for _, link := range links {
go checkLink(link,c)
}
for {
go func() { // This is the "Anonymous" function
time.Sleep(5 * time.Second)
checkLink(<-c, c)
}() // "()"--> calls the function.
}
}

To prevent the variable i to be replaced. Literal Functions have a work around. As a rule of thumb.: Never try to access the same variable from a different child routine

1
2
3
4
5
6
for i := range c{
go func(link string) {
time.Sleep(5 * time.Second)
checkLink(l, c)
}(i)
}

Author: Lucas Contreras

Maps & Interfaces - Go Intro (III)

Maps

Maps in Go similar to Hashes in Ruby, Objects in JavaScript and Dictionaries in Python is a Key-Value datatype. Even though they are similar to sturcts, they differ in some things.

Both Keys and Values are statically types. Keys and Values can be of different types between them but all Keys on a Map should be of the same Type, same for Values.

Declare an empty Maps.

1
2
3
4
5
colors := map[string]string{
"red": "#ff0000",
"white": "#fffffff",
"black": "#000000",
}

Note that all of the values should have a comma at the end of the value.

1
2
3
4
// Another option #1
var color map[string]string
// Another option #2
color := make(map[string]string)

Add items to a map and the call it

1
2
3
4
// Set a alue for a key
colors["white"] = "#ffffff"
// Retrieve a value given a key
colors["white"]

Delete a value inside a map

1
delete(colors, "white")

Iterating over Maps

1
2
3
4
5
func main(){
for key,value := range colors {
fmt.Println("This is my ", key," and this is my value ", value )
}
}

Difference between Maps and Structs

Maps Structs
All Keys must be the same type Struct’s “Keys” (Fields) does not have a type
All Values must be of the same type Values can be of different types
Use to represent a collection of related properties Use to represent a “thing” with a lot of different properties
Don’t need to know all the keys at compile time You need to know all the different fields at compile time
Keys are indexed, we can iterate over them “Keys” (Fields) are not indexed, we can’t iterate a Struct
Referent Type Value Type

Interfaces 101

Interfaces theory

Interfaces are named collections of method signatures. If we have two or more Structs that have the have the same method, we can use an interface so we don’t need to specify the type of our Structs every time we need to work with them. We just use the interface in that case.

A code snippets from goyexample.com/interfaces leaves this very clear.

I added some notes as comments in the code

Here we declare our interface and other Structs that will make use of our interfaces.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Boilerplate code..

// This is our interface, there are many shapes that will have area and perimeter (rectangle, circle, triangle, ...)
type geometry interface {
area() float64
perim() float64
}

type rect struct {
width, height float64
}

type circle struct {
radius float64
}

Not that in the example above we distinguish two classes of types, an interface type “geometry” which can not be instantiated by itself and two concrete types “rect” and “circle” than can be instantiated. Other concrete types are the one predefines in go like “maps”, “structs”, “int” , etc.

Here’s an important part, and this might be a bit counter-intuitive if you come from POO languages. The way we have of implementing an interface is by implementing ALL the methods in the interface.

So our program now has a new type called geometry. So from now on, every single type in our program with a (receiver) function called *”area()”* that returns a float64 and a (receiver) function called *”perim()”* that returns a float64 are now an honorary member of type geometry.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// IMPORTANT !
// We implement an interface by just implementing ALLL the methods in the interface. Here we implement geometry on rect
func (r rect) area() float64 {
return r.width * r.height
}
func (r rect) perim() float64 {
return 2*r.width + 2*r.height
}

func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}

Making use of our interface.

1
2
3
4
5
6
7
8
9
10
11
12
13

func measure(g geometry) {
fmt.Println(g)
fmt.Println(g.area())
fmt.Println(g.perim())
}

func main() {
r := rect{width: 3, height: 4}
c := circle{radius: 5}
measure(r)
measure(c)
}

As we can see, without interfaces we would have to make a measure() function for each type (rect and circle).

More “complex” Interfaces

Here’s an example of an interface that specifies multiples return and parameter types

1
2
3
type vehicle interface {
driveCoordinate(int, int) (int,int,string,error)
}

Interface inside interfaces

Example: https://golang.org/pkg/io/#ReadCloser

1
2
3
4
5
6
7
8
9
10
11
12
type Reader interface {
Read(p []byte) (n int, err error)
}

type Closer interface {
Close() error
}

type ReadCloser interface {
Reader
Closer
}

In order to satisfy the ReadCloser interface you will need to also satisfy both Reader and Closer interfaces.

Some notes on interfaces

  • Interfaces are not generic types
  • Interfaces are implicit
    • We don’t “inherit” or link any interface with other types, Go handles that for us
  • Interfaces are a contract to help us manage types and only types
  • Step #1 of understanding interfaces i understanding how to read them.

Examples of common interfaces

The io.Reader Interface

The Reader Interface can be found all over Go’s documentation, so I guess it is worth mentioning. This interface let us handle a wide diversity of input source with different types associated. The io.Reader interface represents an entity from which you can read a stream of bytes.

1
2
3
type Reader interface {
Read(buf []byte) (n int, err error)
}

Read reads up to len(buf) bytes into buf and returns the number of bytes read – it returns an io.EOF error when the stream ends.

Example of an HTTP request using the Read() function from the Reader interface:

1
2
3
4
5
6
7
8
9
10
// ...
func main() {
resp, err := http.Get("https://btc.lucascontre.site")
if err != nil {
fmt.Println(err)
}
bs := make([]byte, 9999)
resp.Body.Read(bs)
fmt.Println(string(bs))
}

We can see it reads from the body into our byte slice ([]byte)

The io.Writer Interface

1
2
3
type Writer interface {
Write(p []byte) (n int, err error)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early.

The io.Copy function

The io.Copy function is, as well as io.Writer and io.Reader, part of the io packer

Copy definition:

1
func Copy(dst Writer, src Reader) (written int64, err error)

Copy copies from src to dst until either EOF is reached on src or an error occurs. It returns the number of bytes copied and the first error encountered while copying, if any.

With the io.Copy function, our http request would look like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import (
"fmt"
"io"
"os"
)

func main() {
resp, err := http.Get("https://btc.lucascontre.site")
if err != nil {
fmt.Println(err)
}
io.Copy(os.Stdout, resp.Body)
// We know that os.Stdout implement the Writer interface, because it has a Write() function
// We also know that resp.Body has a Read function because it implements the Read() function
}

Author: Lucas Contreras

Receivers & Pointers - Go Intro (II)

Receiver functions in Go

By now we probably know how to declare a function in go from the intro section. Now we’ll learn how to declare a receiver functions (spoiler alert: It’s a method)

We would learn that we can add behavior to a struct with this Receiver functions (Spoiler alert: Methods)

1
2
3
4
5
6
7
func (p person) print() {
fmt.Printf("%+v", p)
}

func (p person) updateName(newFirstName string) {
p.firstName = newFirstName
}

We see that this functions receives a variable p of type person which is a struct of type person. And we can call these functions with the struct the following way

1
2
3
4
5
6
7
lucas =: person{
name: "Lucas Contreras",
age: 100,
}

lucas.print() // {name:Lucas Contreras age:100}
lucas.updateName("Pedro Alfonso") // Name will not change due to pointers.

Pointers in Go

I’ll assume that you already know about pointers and show you how pointers works on Go really quickly. Spoiler: They work pretty much like in C.

Go is a *”pass by value”* language, so every time we pass a value to a function we are passing a copy of that value to the function to operate with, no the real value.

Here are two examples dealing with pointers

Without pointers:

1
2
3
4
5
6
7
8
9
10
11
12
package main
import "fmt"

func main() {
my_greet := "Hola como estás"
add_name_to_greet(my_greet, "John Doe")
fmt.Println(my_greet) // This will print "Hola como estás" without the name
}

func add_name_to_greet(greet string, name string) {
greet = greet + name
}

With pointers:

1
2
3
4
5
6
7
8
9
10
11
package main
import "fmt"

func main() {
my_greet := "Hola como estas "
add_name_to_greet(&my_greet, "John Doe") // We pass the memory address where our greet is located (pointer)
fmt.Println(my_greet) // This will print "Hola como estás John Doe"}

func add_name_to_greet(greet *string, name string) { // We take this pointer as parameter
*greet += name //We take the Value of the pointer and change it
}

Another alternative whit pointers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import "fmt"

func main() {
my_greet := "Hola como estas " // Acé es donde C haría el Malloc !
var pointerGreet *string
pointerGreet = &my_greet

add_name_to_greet(pointerGreet, "John Doe") // We pass the memory address where our greet is located (pointer)
fmt.Println(my_greet)
}

func add_name_to_greet(greet *string, name string) { // We take this pointer as parameter
*greet += name //We take the Value of the pointer and change it
}

This last happens only for Value Types in go, which are int, float, string, bool and structs. But that’s not the same for Reference Types. So let’s see how we deal with pointers in this case.

Pointers with Reference Types (Slices)

In the case of slices this works just fine since a Slice is a pointer to the head of an array. So copying that pointer will create a pointer that points to the same array.

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"

func main() {
mySlice := []string{"Hola","como","estas?"}
updateSlice(mySlice)
fmt.Println(mySlice)
}

func updateSlice( slice []string) {
//slice = append(slice, "John Doe")
slice[0] = "Hello"
}

This also applies for Maps, Channels, Pointers itself and functions.

Value Types Reference Types
int slices
floats maps
strings channels
bool pointers
structs functions

The & and the *

1
2
3
4
5
*variableName // Makes refence to the value that the pointer... points.

*type // This is also a type. A type of "type pointer"

& variableName // Makes reference to memory address.

So just to recap:

  • To turn address into value : *address

  • To turn value into address: &value

  • To declare some variable as *”pointer to something of type type (eg. person)”* : var contre *person

Exercise:

Why this wont work

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import "fmt"

func main() {
var my_greet *string
*my_greet = "Hola como estas"

add_name_to_greet(my_greet, "John Doe") // We pass the memory address where our greet is located (pointer)
fmt.Println(my_greet)
}

func add_name_to_greet(greet *string, name string) { // We take this pointer as parameter
*greet += name //We take the Value of the pointer and change it
}

Spoiler: I initialize the pointer that point to nil (nowhere) and tried to assigned a value to

Receivers: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/5-Receivers.md
Pointers: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/6-Pointers.md


Author: Lucas Contreras

For & Structs - Go Intro (I)

For loops

The most basic for loop with a single condition

1
2
3
4
5
i := 1
for i <= 3 {
fmt.Println(i)
i = i + 1
}

A classic initial/condition/after for loop.

1
2
3
for j := 7; j <= 9; j++ {
fmt.Println(j)
}

A for without a condition will loop repeatedly until you break out of the loop or return from the enclosing function, basically a while loop

1
2
3
4
for {
fmt.Println("loop")
break
}

You can also continue to the next iteration of the loop

1
2
3
4
5
6
for n := 0; n <= 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
}

For loops in slices. (Basically a for each with indexes :)

1
2
3
for index,value := range sliceName {
fmt.Println("Index: ". index, "Value: ", value)
}

Not classes, structs.

Go is clearly not an object oriented programing language but taking a POO approach to understand Go worked for me.

Struct

A data structure in Go that we can think like a collection of properties that somehow are related together. We can think a struct like a plain object.

Defining a struct in Go that represents a person

1
2
3
4
5
type person struct { 
firstName string
lastName string
age int
}

As you can see we defined a new type person. Then we would be able to create diferent variables of type person like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
// Option 1
lucas := person{"Lucas", "Contreras",105}
// Option 2
lucas := person{
firstName: "Lucas",
age: 105, lastName: "Contreras",
}
// Option 3
var lucas person // This assigns "Zero values" to the properties depending on this type
lucas.firstName = "Lucas"
lucas.lastName = "Contreras"
lucas.age = 105
}

Different ways of printing a struct

1
2
3
import fmt
fmt.Println(lucas) // Prints the struct within {}
fmt.Printf("%+v", lucas) // This will print the properties { firstName:Lucas lastName:Contreras age:105 }

Nesting sturcts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type contactInfo struct { 
number int
email string
}

type person struct {
name string
age int
contact contactInfo
// we can omit the "contact" but the property will also bename contactInfo (same as the type)
}

contre := person{
name : "Lucas Contreras",
age: 100,
contact contactInfo{
email: "[email protected]",
number: 123123123123,
} // returns a reference

contre2 := new(Person) // returns a pointer
}

Note that all of the properties of a struct takes a comma at the end of the line regardless if it is the last properties (unlike JSONs)

For: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/3-For.md
Structs: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/4-Structs.md


Author: Lucas Contreras

Practical intro to Go language

The “Hello world”

1
2
3
4
5
6
package main
import "fmt"

func main(){
fmt.Println("Hello world")
}

Package = Workspace = Project

Several files in go can belong to a same package. All of them must have the package main on top of the file.

Two types of packages

  • Executable -> Generates a file that we can actually run
  • Reusable -> A good place to put reusable logic such as “helpers” or libraries or dependencies.

The word main is used for executable packages.

1
$> go build --> makes our exec file

Imports

Use to get code from other packages, imports go right below the package name.

“fmt” or Format is one of the most known packages and lets us print to stdout among other things. For more info refer to golan.org/pkg/fmt

Go file organization

  1. package name
  2. imports
  3. functions

Functions

We’ve already seen how a function looks on the “Hello world” example. In the function below we have between brackets the parameters and next to them the type that the function will return. Additionally, we are casting the sum of the integers we receive by parameter to string in order to return the correct type.

1
2
3
func functionName(a, b, c int) string {
return string(a + b + c)
}
  • The main() function is called automatically
  • Functions must have return types specified.

Function names that starts with lower case are functions that can’t be used outside the file/package and functions that start with upper case can be exported and used outside the file/package

Invariant arguments

Go functions can take invariant arguments. Let’s see an example

1
2
3
4
5
6
7
func my_functions (i int, s string, fn func (u int), t ...string) {
fmt.Println(i)
fn(8)
for a, b := range t {
fmt.Println("%d - %s", a , b)
}
}

As we can see we can receive n strings in the argument t.

Variable declarations

There are several ways of declaring a variable

1
2
var card string = "I'm  a wonderful string"
[declaration] [name] [type] = [value]

A shorter way where the compiler interprets the type

1
card := "I'm a  wonderful string"

Slices

Go has arrays but those are hardly used. Unlike arrays, slices are typed only by the elements they contain (not the number of elements). These are dynamically allocated while arrays have a fixed length.

Declare an empty array with make, fill it and print it by accessing it.

1
2
3
4
5
6
s := make([]string, 3),
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("set:", s)
fmt.Println("get:", s[2])

The built-in append, which returns a slice containing one or more new values. Note that we need to accept a return value from append as we may get a new slice value.

1
2
3
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println("apd:", s)

Declare and define a slice in the same line

1
mySlice := []string{"A","B","C"}

Slices can also be copy’d. Here we create an empty slice c of the same length as s and copy into c from s.

1
2
3
c := make([]string, len(s))
copy(c, s)
fmt.Println("cpy:", c)

Slices also support a “slice” operator with the syntax slice[low:high].

1
2
l := s[2:5]
fmt.Println("sl1:", l)

Intro: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/1-Intro.md
Slices: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/2-Slices.md


Author: Lucas Contreras

GPG + SSH ? (Part 0 bis)

This will be a small walk through on how to generate an authentication subkey on GPG and integrated with ssh. First of all bare in mind that will need a GPG key first in order to generate this subkey, if have not generated on yet refer to part 0 of these series.

Authentication Key

In order to generate an authentication key, as I mentioned before, you will need to have a key generated. Let’s check that with

1
2
3
4
5
6
7
$ gpg -K                                                       
/home/<USER>/.gnupg/pubring.kbx
-------------------------------
sec rsa4096 2019-12-19 [SC]
F0ASSDF32440E42342FDF25GHB8F9CF4EC8EFE1B
uid [ultimate] Your Name (Comment) <[email protected]>
ssb rsa4096 2019-12-19 [E]

Then we will edit our key using the key ID shown above with the command gpg --expert --edit-key F0ASSDF32440E42342FDF25GHB8F9CF4EC8EFE1B. We’ll be prompt with a GPG tty where we will be able to add a new key with “Authentication” capabilities. By default, as we have seen in part 0, GnuPG creates new keys with Sign and Encryption capabilities so we need to make sure to remove those since we already have keys for that purpose.
Now answer what you are prompted and you’ll be good to go. I’ll leave a set of steps taken from Yubico’s website I’ve found very useful.

  1. Insert the YubiKey into the USB port if it is not already plugged in.
  2. Enter the GPG command: gpg --expert --edit-key 1234ABC (where 1234ABC is the key ID of your key)
  3. Enter the command: addkey
  4. Enter the passphrase for the key. Note that this is the passphrase, and not the PIN or admin PIN.
  5. You are prompted to specify the type of key. Enter 8 for RSA.
  6. Initial default will be Sign and Encrypt. To select authentication key toggle S to disable sign, E to disable encrypt, A to enable authentication.
  7. Once you can confirm that authentication is the current allowed actions select Q to Finish the selection.
  8. Specify the key size.
  9. Specify the expiration of the authentication key (this should be the same expiration as the key).
  10. When prompted to save your changes, enter y (yes).

Once you’re done, run gpg -K. The output should look something like this.

1
2
3
4
5
6
7
8
$> gpg -K                                                       
/home/<USER>/.gnupg/pubring.kbx
-------------------------------
sec rsa4096 2019-12-19 [SC]
F0ASSDF32440E42342FDF25GHB8F9CF4EC8EFE1B
uid [ultimate] Your Name (Comment) <[email protected]>
ssb rsa4096 2019-12-19 [E]
ssb rsa4096 2019-12-27 [A]

Note that now we have a new subkey with “ [A] “ capabilities.

Integrating SSH

First of all let me clarify that using GPG does not make your SSH connections more secure, it just change a bit the way you manage your ssh keys and sometimes is a bit more convenient.
To make use of the new authentication subkey we’ve just created, we need to tell the gpg-agent we want him to handles the ssh requests from SSH. For that we need to enable ssh support by running the following command.

1
$> echo "enable-ssh-support" >> ~/.gnupn/gpg-agent.conf

Additionally you might want to specify which subkey you want to use. We do this by adding the keygrip of our key to ~/.gnupg/sshcontrol

1
2
3
4
5
6
7
8
9
10
11
12
13
$> gpg -K --with-keygrip
/home/<USER>/.gnupg/pubring.kbx
-------------------------------
sec rsa4096 2019-12-19 [SC]
F032E440E7B8F960B9A4D68BA32DDCF4EC8EFE1B
Keygrip = 872C0BA0BB0EAB6600EE9A14146819B41DFF8B73
uid [ultimate] Lucas Contre (Contre) <[email protected]>
ssb rsa4096 2019-12-19 [E]
Keygrip = 96FD0AD76EB01C5475122670A0F85961C7952A1E
ssb rsa4096 2019-12-19 [A]
Keygrip = 037A6603BBDA3461BF672F8071037AK66ACACE34

$ echo 037A6603BBDA3461BF672F8071037AK66ACACE34 >> ~/.gnupg/sshcontrol

Last but not least you need to tell the ssh-agent how to access these keys. This is done by changing the SSH_AUTH_SOCK env variable.
To be sure this variable is well set, add these two lines to your .bashrc, .zshrc or whatever shell run commands file you use.

1
2
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent

Now you’re done! In order to share your public ssh keys just run ssh-add -L to list all of your public ssh keys and place them on any server your like.

Bibliography and technology used in this project


Author: Lucas Contreras
Email: [email protected]
GPG: gpg.lucascontre.site

Dealing with your private key (Part 1)

Now that you’ve managed to create your own GPG key it’s time to understand a bit more about how GnuPG works.

The first question we need to ask is where are our keys stored. The answer depends on which version of GnuPG you are running. From version 2.1 onwards the method of storing your keys has change. On previous versions our keys were stored in two separate keyring under the ~/.gnupg directory. Prior version to 2.1 used to keep the public key pairs in two files: pubring.gpg and secring.gpg, you can imagine which stores which.

Now, the file secring.gpg is not used to store the secret keys anymore. Instead they are stored on the key store of the gpg-agent (a folder named private-keys-v1.d below the GnuPG home directory ~/.gnupg) with an unique identifier for the key called “Keygrip“ as the name of the file (i.e ~/.gnupg/private-keys-v1.d/{KEYGRIP}.key).Additionally, the pubring.gpg file has been replaced with pubring.kbx which remains under the GnuPG directory. This “database“ stores all of our friend’s keys, metadata and certificates. We might wanna backup this file.

Know that we know where our (I bet passphrase encrypted) private key is stored, we naturally ask the next question. Is it safe down there? Well.. it’s passphrase protected, right? Depends on the degree of securit/privacy obsession you can handle. Let’s take a look at this comment on https://security.stackexchange.com/.

On the days when my paranoia is like a ripe tomato, begging me to pick it, I split the private key (naturally it is already passphrase-protected) in half, then make a 3rd string by XOR-ing them together. Then I use simple password encryption (gpg –symmetric) on each string, and put each on a remote server on a different continent. Ideally, each remote server is with a different ISP or cloud provider.
But as the medicine was working – at least until I realized how ambitious the NSA has been – what I’ve actually done in the past is merely encrypted the (whole) private key (again using gpg –symmetric) and put it on my smartphone.
Now, having read the other answers, I’m finding the idea of three QR codes, embedded into three family photos, blindingly attractive. Time for stronger medicine?

Source: https://security.stackexchange.com/questions/51771/where-do-you-store-your-personal-private-gpg-key

Whether you want keep your private key on your local (probably proprietary) machine or do what our dear friend Darren did, it’s on you. I will show how to import, backup and retrieve/restore that private key as I think is the most secure and practical way.

First, we need to somehow backup our keys in case we lose them. I suggest exporting the private key and print it on a piece of paper. You would not need the backup unless you somehow lose your private key. To do so the following command might help you.

1
2
3
4
5
6
7
8
9
10
11
$ gpg --armor --export-secret-key [email protected]
-----BEGIN PGP PRIVATE KEY BLOCK-----

lQdGBF6kqnEBEAD3TDT/BfbKQE4aqOSmSAsLCsQ8HCt3HATXPBgDWhSUzy3xyQsl
x4oHGCnOpG5bBaUF3LRZh5GFsQovjfMVy11JeFcNkJO3eJRvwGgS98CiKW72HI+/
{ . . . }
3K/UBeKAtimIZagOWBpwX9OJehVcFwws4ToCshnyio2rhU79HWutJFtls/oE8HJc
Rc4Y9PMRfu7nuiCcNdc9Lp1BiaTymnQDLECi3bNtstZEnUGkzgvGwTX7DAZ5BDlY
KMBBP60EgSDpp1eG+4z8M/0O9NV2TQ==
=AXh6
-----END PGP PRIVATE KEY BLOCK-----

Print that on paper and you’ll be good to go. Now that you’ve backed up your keys, let’s see how can we export them and use them on different devices. There are several ways we can achieve this.

Having multiple copies of our private key

A simple and fast solution, if we don’t mind having our keys in multiple devices, is simply export them with into a file:

1
gpg --armor --export-secret-key [email protected] > private.key

and then just import the gpg on the other machine with:

1
gpg --import private.key

This is far from the safest option but it lets us decrypt no matter on what device we are working on.

Store it on an USB stick

Another option is to simply store it on an USB stick. This way you can have your private key with you always and there’s no need to store it on any machine we don’t trust. I haven’t tried this solution myself any further than a PoC to be sure it works.

Basically, what you want to do first is copy the file on ~/.gnupg/private-keys-v1.d on an USB stick.

1
mv ~/.gnupg/private-keys-v1.d/{KEYGRIP}.key /PATH/TO/USB

Be aware that moving these files from your machine will require to have the USB stick plugged when you need to decrypt something.

You will probably find more than one {KEYGRIP}.key file, each of them corresponding to a subkey. We can know which one belongs to which by simply listing your key this way: gpg -k --with-keygrip

Now that you’ve copied the files into the USB stick you will need to create a symbolic link.

1
ln -s ~/.gnupg/private-keys-v1.d/{KEYGRIP}.key /path/to/usb/{KEYGRIP}.key

We will need to do this for every single subkey we want to export. Once you are done check you can access these key (with the USB stick plugged) running gpg -K . Bare in mind that you should always mount your device on the same path, otherwise the sym-links won’t work.

Note: You will need to import your public key as well if you want gpg to recognize your keys. They need to be part of the pubring.kbx database. Source.

Yubikey or SmartCard

Finally, in my opinion the most secure/practical trade off for storing your private key is a Yubikey. For those who doesn’t know a YubiKey is a hardware authentication device manufactured by Yubico that supports one-time passwords, public-key cryptography and authentication, and the Universal 2nd Factor and FIDO2 protocols.

A detailed step by step on how to export your secret key to a Yubi will be the starting point of part 2 of this GnuPG series.

Bibliography and technology used in this project


Author: Lucas Contreras

Leave a comment: Join the Reddit discussion