Slice in Golang

One of an important feature developer often uses while coding is Array. It is very easy to handle Array but it has limitations like we have to fix size of the array when creating it. Accessing array elements more than its size gives error.

Golang has a feature called Slice, in simple words slice is a variable length array. It has a built in array it expand size on demand.

We can create slice in two ways, first will see using slice literal

numbers := []int {1, 2, 3, 4, 5} 

This statement create slice which has length and capacity as 5. When creating array we have to specify the size of the array, for slice it doesn't required to specify explicitly.

program    

package main

import "fmt"

func main() {
  numbers := []int{1, 2, 3, 4, 5}
fmt.Println(numbers)
numbers[2] = numbers[2] * 10
fmt.Println(numbers)
}

output     

[1 2 3 4 5]
[1 2 6 4 5]

second using make keyword passing type, length and optional capacity as arguments. If we didn't pass the capacity Go runtime cosider length as the capacity of the slice.

numbers = ([]int, 2, 4)
numbers[0] = 1
numbers[1] = 2
numbers[2] = 3

Develper new to golang often confuse the terms slice length and capacity. In simple terms slice lenght means number of elements currently available in the slice, and capacity means maximum number of elements currently slice can hold. 

This create a question like why do we need capacity, because setting up capacity when creating slice reduce often reallocating the slice size. when slice automatically expands the size it reallocate to double its capacity. Built in function len and cap returns slice length and capacity.

Append is a built in function it helps to add elements to the slice. When we append the elements more than slice capacity, it double the slice capacity

program     

package main

import "fmt"

func main() {
numbers := make([]int, 2, 4)
numbers[0] = 1
numbers[1] = 2
fmt.Printf("len - %d, cap - %d, slice - %v\n", len(numbers), cap(numbers), numbers)

numbers = append(numbers, 3, 4)
fmt.Printf("len - %d, cap - %d, slice - %v\n", len(numbers), cap(numbers), numbers)

// adding 5th element more than capacity, double slice capacity
numbers = append(numbers, 5)
fmt.Printf("len - %d, cap - %d, slice - %v\n", len(numbers), cap(numbers), numbers)
}

output     

len - 2, cap - 4, slice - [1 2]
len - 4, cap - 4, slice - [1 2 3 4]
len - 5, cap - 8, slice - [1 2 3 4 5]


Deploy Golang Web Application to Heroku cloud Platform

Here I will provide you the details to deploy simple golang web application on Heroku. 

I hope reader of this post has already installed Golang package and have basic knowledge about golang and basic skill about git not mandatory.


I am using go1.6 version on Linux-Ubuntu machine for this post.


sujin@sujin:~$ lsb_release -d

Description: Ubuntu 14.04.4 LTS

sujin@sujin:~$ go version

go version go1.6 linux/amd64

Setup Go directory structure and set GOPATH env variable. add GOPATH/bin to PATH env variable.


set working directory in GOPATH


sujin@sujin:~$ echo $GOPATH
/home/sujin/godir/work

create a simple web app in golang. For this example i create a folder called HerokuTest, inside a file called HerokuTest.go that contain program below

package main



import (

"fmt"

"net/http"

"os"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "\n\tHello World From Golang on Heroku")
}

func main() {
http.HandleFunc("/", homeHandler)

fmt.Println("Server Listening...")
err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
if err != nil {
panic("ListenAndServe")
}
}

Compile and test the program locally

sujin@sujin:~/godir/work/src/blog/HerokuTest$ go build
sujin@sujin:~/godir/work/src/blog/HerokuTest$ ls
HerokuTest  HerokuTest.go
sujin@sujin:~/godir/work/src/blog/HerokuTest$ PORT=7070 HerokuTest 
Server Listening...

Go to the url http://127.0.0.1:7070/ from web browser it will print Hello World From Golang on Heroku in web page.

We should manage dependency package using Godep

install godep

go get github.com/kr/godep

save all golang dependencies

sujin@sujin:~/godir/work/src/blog/HerokuTest$ godep savesujin@sujin:~/godir/work/src/blog/HerokuTest$ ls Godeps HerokuTest HerokuTest.go

We should create Procfile to tell Heroku which command to execute on web

sujin@sujin:~/godir/work/src/blog/HerokuTest$ echo 'web: HerokTest' > Procfile

Now its time to configure git for the project.

git init
git add .
git git commit -m "Heroku Test Project Initial Commit"
git remote add origin https://github.com/sujinsr/HerokuTest.git
git push origin master


Register in heroku website to get free account https://signup.heroku.com/?c=70130000001x9jFAAQ


install heroku tool belt

sujin@sujin:~/godir/work/src/blog$ heroku login
Enter your Heroku credentials.
Email: sujinsr@gmail.com
Password (typing will be hidden): 
Logged in as sujinsr@gmail.com


Pull the HerokuTest project from git

go get github.com/sujinsr/HerokuTest/...


Move to project directory and create heroku instance for your application




sujin@sujin:~/godir/work/src/github.com/sujinsr/HerokuTest$ heroku create heroku-test-app-blog -b https://github.com/kr/heroku-buildpack-go.git
Creating heroku-test-app-blog... done, stack is cedar-14
Setting buildpack to https://github.com/kr/heroku-buildpack-go.git... done
https://heroku-test-app-blog.herokuapp.com/ | https://git.heroku.com/heroku-test-app-blog.git

Now push your application to git heroku master

sujin@sujin:~/godir/work/src/github.com/sujinsr/HerokuTest$ git push heroku master
Counting objects: 14, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (14/14), 1.48 KiB | 0 bytes/s, done.
Total 14 (delta 2), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Fetching set buildpack https://github.com/kr/heroku-buildpack-go.git... done
remote: -----> Go app detected
remote: -----> Checking Godeps/Godeps.json file.
remote: -----> Installing go1.6... done
remote: -----> Running: godep go install -tags heroku ./...
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote: 
remote: -----> Compressing...
remote:        Done: 2.2M
remote: -----> Launching...
remote:        Released v3
remote:        https://heroku-test-app-blog.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy.... done.
To https://git.heroku.com/heroku-test-app-blog.git
 * [new branch]      master -> master

Check whether application running

sujin@sujin:~/godir/work/src/github.com/sujinsr/HerokuTest$ heroku ps
=== web (Free): HerokuTest (1)
web.1: up 2016/02/28 14:09:45 +0530 (~ 37s ago)

Check the aplication by running heroku open

sujin@sujin:~/godir/work/src/github.com/sujinsr/HerokuTest$ heroku open
Opening heroku-test-app-blog... done
Created new window in existing browser session.


Check the logs 

sujin@sujin:~/godir/work/src/github.com/sujinsr/HerokuTest$ heroku logs --tail
2016-02-28T08:38:42.408669+00:00 heroku[api]: Enable Logplex by sujinsr@gmail.com
2016-02-28T08:38:42.408669+00:00 heroku[api]: Release v2 created by sujinsr@gmail.com
2016-02-28T08:39:43.323594+00:00 heroku[api]: Scale to web=1 by sujinsr@gmail.com
2016-02-28T08:39:43.566013+00:00 heroku[slug-compiler]: Slug compilation started
2016-02-28T08:39:43.566018+00:00 heroku[slug-compiler]: Slug compilation finished
2016-02-28T08:39:43.414709+00:00 heroku[api]: Deploy 51ae268 by sujinsr@gmail.com
2016-02-28T08:39:43.414779+00:00 heroku[api]: Release v3 created by sujinsr@gmail.com
2016-02-28T08:39:44.250976+00:00 heroku[web.1]: Starting process with command `HerokuTest`
2016-02-28T08:39:45.250323+00:00 app[web.1]: Server Listening...
2016-02-28T08:39:45.844980+00:00 heroku[web.1]: State changed from starting to up

Connect Redis from Golang


In this article i am not going to say how Redis and golang works, I hope you have basic knowledge of both. Instead I will tell you how to connect to redis server and execute command from golang. 

In case you don't have the knowledge on Redis & Golang please check their official websites (GOLANG & REDIS) for documentation and more information.

I believe you have already installed golang and redis server in your laptop/PC. If not please check their official website for installation procedure.

Redis server written in C programming language but it has client available for most of the programming language. There is more libraries available for golang as well. I am going to use Redigo because it has many feature and easy to use. You can check their github website [ Redigo github ] for source code and documents

You can download the Redigo redis client library for golang using the go get command like below
          go get github.com/garyburd/redigo/redis
You should configure GOPATH environment variable to succeed this command.

Here I provide the simple program to connect redis server from golang and query redis SET & GET command.

Example Program:

package main

import (
    "fmt"
    "github.com/garyburd/redigo/redis"
    "log"
)

func main() {
    /* Connect With Redis Server */
    r, err := redis.Dial("tcp", ":7777")
    if err != nil {
        fmt.Println("Error ", err)
    }
    fmt.Println("Connection Success With Redis Server")

    /* Query Redis Commands */
    _, err = r.Do("SET", "Name1", "Michel")
    if err != nil {
        log.Fatal("Error to SET", err)
    }
    fmt.Println("SET Success")

    value, err := redis.String(r.Do("Get", "Name1"))
    if err != nil {
        log.Fatal("Error to GET", err)
    }
    fmt.Println("GET Success: Name1 =", value)

    /* Close Redis Server Connection*/
    r.Close()

}

Output:

Connection Success With Redis Server
SET Success

GET Success: Name1 = Michel


Source Code Explanation:

In this example code i used two redigo api calls Dial which help to connect redis server and Do execute redis command.

r, err := redis.Dial("tcp", ":7777")

This statement connect help to connect your redis server running in port number 7777 using tcp connection. It return error and redis handler which help for other redigo APIs.

    _, err = r.Do("SET", "Name1", "Michel")

DO api will execute redis SET command with key as "Name1" and value as "Michel". Here "r" is handle returned from previous Dial API. This statement is similar to executing redis command "SET Name1 Michel" from redis CLI client.

    value, err := redis.String(r.Do("Get", "Name1"))

This statement get the redis key with name as "Name1" and convert to string format. This is similar to executing "GET NAME1" .

    r.Close()

This statement used to close redis connection.

Buffered io reader and writer in Golang


Writing to file using buffered writer

package main

import (
"bufio"
"log"
"os"
)

func main() {
/* Create and Open file for writing */
filefd, err := os.Create("blog.txt")
if err != nil {
log.Fatal(err)
}
defer filefd.Close()

/* create buffered write handler for opened file */
bufWriteHandle := bufio.NewWriter(filefd)

/* Write bytes to buffer */
byteData := []byte{'a', 'b', 'c', 'd', 'e', '\n'}
nn, err := bufWriteHandle.Write(byteData)
if err != nil {
log.Fatal(err)
}
log.Println("Number of bytes Written to buffer", nn)

/* Write String to buffer */
nn, err = bufWriteHandle.WriteString("String written using bufferd io\n")
log.Println("Number of bytes Written to buffer", nn)

/* flush from buffer to disk */
bufWriteHandle.Flush()
}


Reading from file using buffered reader

package main

import (
"log"
"os"
"bufio"
"fmt"
)

func main() {
/* Open existing file for reading */
filefd, err := os.Open("blog.txt")
if err != nil {
log.Fatal(err)
}
defer filefd.Close()

/* Create buffered read handler for opened file */
bufReadHandle := bufio.NewReader(filefd)

/* allocate slice of bytes to read */
readBytes := make([]byte, 64)

/* Read bytes and move pointer */
nn, err := bufReadHandle.Read(readBytes)
if err != nil {
log.Fatal(err)
}
fmt.Println("Number of bytes read", nn)
fmt.Println("Read Bytes:", string(readBytes))
}

Simple HTTP Web Server in Golang

PROGRAM:

package main

import (
"fmt"
"net/http"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Inside homeHandler...")
/* Write text to web page */
fmt.Fprintf(w, "Hi, This is from Home Handler")
}

func page1Handler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Inside page1Handler...")
fmt.Fprintf(w, "Hello, This is from Page 1 Handler")
}

func page2Handler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Inside page2Handler...")
fmt.Fprintf(w, "Hello, This is from Page 2 Handler")
}

func main() {
/* Add handler */
http.HandleFunc("/", homeHandler)
http.HandleFunc("/page1", page1Handler);
http.HandleFunc("/page2", page2Handler);

/* Listen on a port */
fmt.Println("Listening...")
err := http.ListenAndServe(":9090", nil)
if err != nil {
fmt.Println("ERROR: ListenAndServe:", err)
}
}