DEV Community

Cover image for Algorithm For Generating a Short Link 🧮
Јане Џумеркоски
Јане Џумеркоски

Posted on

Algorithm For Generating a Short Link 🧮

In the previous part, we manage to set up the server using Golang Echo. In this part, we are going to work on the algorithm that creates short URL from long URL.

For the implementation, we are going to use two main schemes - a hash function and a binary-to-text encoding algorithm.

First, we will need to create two files - shortener.go and shortener_test.go, inside a folder named shortener

├── go.mod
├── go.sum
├── main.go
└── shortener
   ├── shortener.go
   └── shortener_test.go
Enter fullscreen mode Exit fullscreen mode

Then, we open shortener.go file and add the SHA-256 code below. We will use the Golang built-in implementation of this hash function. SHA-256 is a patented cryptographic hash function that outputs a value that is 256 bits long.

package shortener

import (
    "crypto/sha256"
)

func sha256Of(input string) []byte {
    algorithm := sha256.New()
    algorithm.Write([]byte(input))
    return algorithm.Sum(nil)
}
Enter fullscreen mode Exit fullscreen mode

Next thing is to add encoding. In this tutorial, we will go with BASE58 one. I can see you re-reading the name of the encoding and thinking "58? 🤔 Did the author make a typo?". Well no, this encoding is a modification of the classic BASE64. it makes it easier for humans to read the result by eliminating 0 (zero), O (capital o), I (capital i), l (lower L), + (plus), and / (slash) characters to avoid confusion. Well, let’s add then the BASE58 encoding.

First things first - let’s load the BASE58 dependency library.

go get github.com/itchyny/base58-go/cmd/base58
Enter fullscreen mode Exit fullscreen mode

Now, we'll extend the code with another function.

func base58Encoded(bytes []byte) string {
    encoding := base58.BitcoinEncoding
    encoded, err := encoding.Encode(bytes)
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }
    return string(encoded)
}
Enter fullscreen mode Exit fullscreen mode

Since we have our two main building blocks (hashing and encoding) already in place, the final algorithm is easy.

  • Hashing initialLink + userId with SHA-256. We use userId for preventing similar shortened URLs to different users in case they want to shorten the same URL.
  • Derive a big integer number from the hash bytes generated during the hashing.
  • Apply BASE58 on the derived big integer value and pick the first 8 characters.
func GenerateShortURL(initialLink string, userId string) string {
    urlHashBytes := sha256Of(initialLink + userId)
    generatedNumber := new(big.Int).SetBytes(urlHashBytes).Uint64()
    finalString := base58Encoded([]byte(fmt.Sprintf("%d", generatedNumber)))
    return finalString[:8]
}
Enter fullscreen mode Exit fullscreen mode

Our algorithm is done. Let’s do some unit testing to be sure that it works as expected. We already created our test file shortener_test.go, so now we only need to add testify toolkit

go get github.com/stretchr/testify/assert
Enter fullscreen mode Exit fullscreen mode

and some pieces of code.

package shortener

import (
    "github.com/stretchr/testify/assert"
    "testing"
)

func TestShortLinkGenerator(t *testing.T) {
    initialLink := "https://go.dev/doc/tutorial/getting-started"
    userId := "UwQPr3aIf9dM5x7r"
    shortLink := GenerateShortURL(initialLink, userId)

    assert.Equal(t, shortLink, "dysg5Fas")
}
Enter fullscreen mode Exit fullscreen mode

With this, we are done with the implementation of the algorithm for generating a short URL. 🥳 We can execute all tests using the command go test ./... or only those inside the shortener folder with go test ./shortener assuming we are at the root of the project (on the same level with main.go)


Originally published at projectex.dev

Top comments (0)