Golang human readable byte sizes

March 31, 2020

Here is a function that prints out byte sizes, like the return from len() function, into human readable units.

Function and example

package main

import (
	"fmt"
	"strconv"
)

const (
	TB = 1000000000000
	GB = 1000000000
	MB = 1000000
	KB = 1000
)

func lenReadable(length int, decimals int) (out string) {
	var unit string
	var i int
	var remainder int

	// Get whole number, and the remainder for decimals
	if length > TB {
		unit = "TB"
		i = length / TB
		remainder = length - (i * TB)
	} else if length > GB {
		unit = "GB"
		i = length / GB
		remainder = length - (i * GB)
	} else if length > MB {
		unit = "MB"
		i = length / MB
		remainder = length - (i * MB)
	} else if length > KB {
		unit = "KB"
		i = length / KB
		remainder = length - (i * KB)
	} else {
		return strconv.Itoa(length) + " B"
	}

	if decimals == 0 {
		return strconv.Itoa(i) + " " + unit
	}

	// This is to calculate missing leading zeroes
	width := 0
	if remainder > GB {
		width = 12
	} else if remainder > MB {
		width = 9
	} else if remainder > KB {
		width = 6
	} else {
		width = 3
	}

	// Insert missing leading zeroes
	remainderString := strconv.Itoa(remainder)
	for iter := len(remainderString); iter < width; iter++ {
		remainderString = "0" + remainderString
	}
	if decimals > len(remainderString) {
		decimals = len(remainderString)
	}

	return fmt.Sprintf("%d.%s %s", i, remainderString[:decimals], unit)
}

func main() {
	test := []int{425005, 8741208, 114448910, 557891, 557,
		114710, 8933578, 5849684981, 12033687, 742289, 678007439}

	for _, v := range test {
		fmt.Println(v, "\t = ", lenReadable(v, 2))
	}
}

Output

425005          =  425.00 KB
8741208         =  8.74 MB
114448910       =  114.44 MB
557891          =  557.89 KB
557             =  557 B
114710          =  114.71 KB
8933578         =  8.93 MB
5849684981      =  5.84 GB
12033687        =  12.03 MB
742289          =  742.28 KB
678007439       =  678.00 MB

Read more →

Golang serving resume able file downloads with net/http

March 30, 2020

Here is a fully commented example golang function on how to serve and transmit files to clients with the go net/http package. It supports the "Accept-Ranges" header, which allows for downloads to be paused or interrupted and resumed later on. This is very useful for clients who don't have stable connections to download larger files. However this function does not support Multipart downloads, if you wish to have that functionality check this function in the net/http source code for implementation.

This function is written with the following sources RFC 7233 section 3.1MDN Range Requests and Content Range.

Read more →

Golang Beego how to use sessions

January 18, 2017

The official documentation on using sessions in Beego is besides being outdated quite unclear. I'll show you how to use sessions inside your Beego application.

Read more →