Loading...

Follow LinuxLabs | Golang on Feedspot

Continue with Google
Continue with Facebook
or

Valid

I hope you already setup golang according to this guide

Now create a directory for the demo app.

$ mkdir -p ${GOPATH}/src/github.com/ansilh/demo-webapp

Create demo-webapp.go file

$ vi ${GOPATH}/src/github.com/ansilh/demo-webapp/demo-webapp.go
package main

import (
 "fmt"
 "net/http"
 "log"
)

func demoDefault(w http.ResponseWriter, r *http.Request) {
 fmt.Fprintf(w, "404 - Page not found - This is a dummy default backend") // send data to client side
}

func main() {
  http.HandleFunc("/", demoDefault) // set router
  err := http.ListenAndServe(":9090", nil) // set listen port
   if err != nil {
    log.Fatal("ListenAndServe: ", err)
   }
}

Build a static binary

$ cd $GOPATH/src/github.com/ansilh/demo-webapp
$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -ldflags="-w -s" -o $GOPATH/bin/demo-webapp

Execute the program

$ demo-webapp

Open the browser and check if you can see the response using IP:9090
If you see the output “404 – Page not found – This is a dummy default backend” indicates that the program is working

In the upcoming session, we will pack this binary in a Docker image and will push to Docker Hub

The post Create a Web Server using Golang appeared first on LinxLabs.

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

Download Golang tarball

$ curl -O https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz

Extract the contents

$ tar -xvf go1.11.4.linux-amd64.tar.gz

Move the contents to /usr/local directory

$ sudo mv go /usr/local/

Add the environmental variable GOPATH to .profile

$ cat < >>~/.profile
export GOPATH=\$HOME/work
export PATH=\$PATH:/usr/local/go/bin:\$GOPATH/bin
EOF

Create the work directory

$ mkdir $HOME/work

Load the profile

$ source ~/.profile

Verify Golang setup

$ go version
 go version go1.11.4 linux/amd64

Create a directory tree to map to a github repository

$ mkdir -p $GOPATH/src/github.com/ansilh/golang-demo

Create a hello world golang program

$ vi $GOPATH/src/github.com/ansilh/golang-demo/main.go
package main
import "fmt"

func main(){
fmt.Println("Hello World.!")
}

Build and install the program

$ go install github.com/ansilh/golang-demo

Execute the program to see the output

$ golang-demo
Hello World.!

The post Install Golang in Ubuntu 16.04 appeared first on LinxLabs.

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

In Part 2 we executed a shell with modified hostname using UTS namespace

In this article we will explain how we can use PID and Mount namespaces

By isolating mount and process namespaces , we will be able to give the container the impression that its having exclusive access to /proc
Which will make all process related commands to fetch information from isolated /proc

Lets see how we can implement this in go

We can modify ‘startContainer’ function discussed in Part 2 for mounting proc file system in MNT namespace

if err := syscall.Mount("proc", filepath.Join(root, "/proc"), "proc", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), ""); err != nil {
                fmt.Println("Proc mount failed")
        }

As per mount man page the flags mentioned with syscall.Mount are below

http://man7.org/linux/man-pages/man2/mount.2.html
MS_NOEXEC	 8 /* Disallow program execution */

MS_NOSUID	 2 /* Ignore suid and sgid bits */

MS_NODEV	 4 /* Disallow access to device special files */

This will make sure the continer won’t get any special access via /proc

To get mount to work , we need to add namespace syscall.CLONE_NEWNS to Cloneflags in ‘setNameSpaces‘ function
Along with that we will add one more flag syscall.CLONE_NEWPID so that we will get isolated PIDs and process related commands will give isolated details because of mounted /proc.

So lets combine all above codes and build modified program

package main

import (
        "fmt"
        "os"
        "os/exec"
        "syscall"
)

//Function to change Arg[0] to "fork" and set namespaces
//Finally call the binary itself  **
func setNameSpaces(shell string) {
        cmd := &amp;exec.Cmd{
                Path: os.Args[0],
                Args: append([]string{"fork"}, shell),
        }
        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        cmd.SysProcAttr = &amp;syscall.SysProcAttr{
                Cloneflags: syscall.CLONE_NEWUSER |
                        syscall.CLONE_NEWPID |
                        syscall.CLONE_NEWNS |
                        syscall.CLONE_NEWUTS,
                UidMappings: []syscall.SysProcIDMap{
                        {
                                ContainerID: 0,
                                HostID:      os.Getuid(),
                                Size:        1,
                        },
                },
                GidMappings: []syscall.SysProcIDMap{
                        {
                                ContainerID: 0,
                                HostID:      os.Getgid(),
                                Size:        1,
                        },
                },
        }
        cmd.Run() // path=./executable , Args[0]=fork , Args[1]=bash
}

//Set new hostname in already initialized namespace and start a shell
func startContainer(shell string) {
        fmt.Println("Starting Container")
        //Set a new hostname for our container
        if err := syscall.Sethostname([]byte("container")); err != nil {
                fmt.Printf("Setting Hostname failed")
        }
        //Mount /proc
        //Mount /proc to new root's  proc directory using MNT namespace
        if err := syscall.Mount("proc", "/proc", "proc", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), ""); err != nil {
                fmt.Println("Proc mount failed")
        }

        if err := syscall.Exec(shell, []string{""}, os.Environ()); err != nil {
                fmt.Println("Exec failed")
        }

}

func main() {
        // Get absolute path to bash
        shell, err := exec.LookPath("bash")
        if err != nil {
                fmt.Printf("Bash not found\n")
                os.Exit(1)
        }
        //This condition will fail first time as the Args[0] will be the name of program
        //But this condition will become true when ,
        //this program itslef calls with Arg[0] = "fork" from startProc() **
        if os.Args[0] == "fork" {
                startContainer(shell)
                os.Exit(0)
        }
        //Starting point
        setNameSpaces(shell)
}
linxlabs@golang:~/.../uts_demo> go build uts_mnt_demo.go
linxlabs@golang:~/.../uts_demo> ./uts_mnt_demo
Starting Container
container:~/.../uts_demo # ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  1 23:47 pts/1    00:00:00
root        23     1  0 23:47 pts/1    00:00:00 ps -ef
container:~/.../uts_demo # cd /proc/
container:/proc # df .
Filesystem     1K-blocks  Used Available Use% Mounted on
proc                   0     0         0    - /proc
container:/proc # echo $$
1
container:/proc # exit
exit

In next article we will change the root file system of the container so that we can completely isolate the process
This will be again be done with mount namespace , but we will use busybox and pivot_root operation to accomplish more isolation and ‘container-ish’ feel

The post Namespaces and Go Part 3 – Proc and Mount appeared first on .

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

In Part 1 of Namespace article series ,we were unable to set hostname from a shell even though the user was root
That program was missing UTS namespace which is responsible for isolating ‘hostname’

In this article we will use UTS namespace , but with a short hack

Go will not allow any changes after setting namespaces and before execution of a program
So here we have to spawn a new process in new namespace and that process can excute commands to set hostname

Picture explains far better than words , so below you can see the flow chart of the program

Now we will explain the the code (working code is at the end of this post)

‘main’ program will check if there is a “fork” in os.Args[0] (We discussed command line arguments in this article )
During first run of the program “fork” will not be set os.Args[0] always set to the executable’s name itself and program flow will change to function ‘setNameSpaces’

In ‘setNameSpaces’ function we will change os.Args[0] to “fork”.
Next we set needed namespace syscall.CLONE_NEWUTS using syscall.SysProcAttr with in the same function and call the process using exec.Run()

This time the flow will change to main again and condition “fork flag set ? ” will succeed ; this will invoke the function ‘startContainer’
‘startContainer’ will set new hostname using syscall.Sethostname and starts a shell using syscall.Exec.

Please note that syscall.Exec will never come back to main if it succeeds and returns -1 if there is any error (man 2 execvp)

Entire code is written below including comments and we will be using the same program to discuss remaining Namespaces .

package main

import (
        "fmt"
        "os"
        "os/exec"
        "syscall"
)

//Function to change Arg[0] to "fork" and set namespaces
//Finally call the binary itself  **
func setNameSpaces(shell string) {
        cmd := &amp;exec.Cmd{
                Path: os.Args[0],
                Args: append([]string{"fork"}, shell),
        }
        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        cmd.SysProcAttr = &amp;syscall.SysProcAttr{
                Cloneflags: syscall.CLONE_NEWUSER |
                        syscall.CLONE_NEWUTS,
                UidMappings: []syscall.SysProcIDMap{
                        {
                                ContainerID: 0,
                                HostID:      os.Getuid(),
                                Size:        1,
                        },
                },
                GidMappings: []syscall.SysProcIDMap{
                        {
                                ContainerID: 0,
                                HostID:      os.Getgid(),
                                Size:        1,
                        },
                },
        }
        cmd.Run() // path=./executable , Args[0]=fork , Args[1]=bash
}

//Set new hostname in already initialized namespace and start a shell
func startContainer(shell string) {
        fmt.Println("Starting Container")
        //Set a new hostname for our container
        if err := syscall.Sethostname([]byte("container")); err != nil {
                fmt.Printf("Setting Hostname failed")
        }
        if err := syscall.Exec(shell, []string{""}, os.Environ()); err != nil {
                fmt.Println("Exec failed")
        }

}

func main() {
        // Get absolute path to bash
        shell, err := exec.LookPath("bash")
        if err != nil {
                fmt.Printf("Bash not found\n")
                os.Exit(1)
        }
        //This condition will fail first time as the Args[0] will be the name of program
        //But this condition will become true when ,
        //this program itslef calls with Arg[0] = "fork" from startProc() **
        if os.Args[0] == "fork" {
                startContainer(shell)
                os.Exit(0)
        }
        //Starting point
        setNameSpaces(shell)
}

Save the code as uts_demo.go and build it

linxlabs@golang:~/.../uts_demo> go build uts_demo.go
linxlabs@golang:~/.../uts_demo> ./uts_demo
Starting Container
container:~/.../uts_demo #
container:~/.../uts_demo # hostname
container
container:~/.../uts_demo # id
uid=0(root) gid=0(root) groups=0(root)
container:~/.../uts_demo # exit
exit
linxlabs@golang:~/.../uts_demo>

The post Namespaces and Go Part 2 – UTS Namespace appeared first on .

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

In this article we will see how to access command line arguments from a go program

We will use the variable ‘Args’ from the package ‘os ‘ (https://golang.org/pkg/os/#pkg-variables)

Lets execute below code and examine the output

package main

import (
"fmt"
"os"
)

func main() {
fmt.Printf("%T\n", os.Args)
fmt.Println(os.Args)
}

linxlabs@golang:~/.../Golang-Tutor> go build args.go
linxlabs@golang:~/.../Golang-Tutor> ./args ls -lrt abc 1234
[]string
[./args_sample ls -lrt abc 1234]
linxlabs@golang:~/.../Golang-Tutor>

os.Args is a string slice and it holds all the command line arguments including executed command

You may extract each arguments using index like os.Args[0] , os.Args[1] etc..

To iterate through the arguments we can use ‘for’ loop along with ‘range’ ; which will return two values ; index and value of index

Lets modify above code with for loop

package main

import (
"fmt"
"os"
)

func main() {
for i, val := range os.Args {
fmt.Printf("Index [%d] = %s\n", i, val)
}
}
linxlabs@golang:~/.../Golang-Tutor> go build args.go
linxlabs@golang:~/.../Golang-Tutor> ./args ls -lrt abc 1234
Index [0] = ./args
Index [1] = ls
Index [2] = -lrt
Index [3] = abc
Index [4] = 1234

I hope this article is simple and easy
We will discuss more exciting topics in coming articles

The post How to access command line arguments in Golang appeared first on .

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

In this article we will setup a Golang development environment using IntelliJ Community edition IDE

We need to download below software

Put all downloaded installers to a directory on your desktop; lets call it as ‘Golang-Intellij‘

Follow below steps in the order as explained

Installation

Install JDK with default settings
Install PortableGit to C:/Git
Install Golang to C:/Go
Install Intellij IDEA with default settings

Git prompt customization

Goto C:/Git/etc/profile.d/
Edit git-prompt.sh
Comment out the lines ending with # newline ; with this we are making the bash prompt bit more compact
In PortableGit-2.15.0-64-bit version , you can do this by commenting out lines 13 , 15 and 35 (Use notepad++ to get line numbers visible while editing)
Save the file

Customize plugin

Go to C:/Git/bin and start bash.exe
You will get a Bash prompt – execute below commands from bash ; anything starts with ‘#’ indicates comment

cd /c/Users/<your win username>/Desktop/Golang-Intellij
unzip Go-0.171.1931.zip
cd Go/lib
mkdir intellij-build
mv intellij-go-0.171.1931.jar intellij-build/
cd intellij-build
/c/Program\ Files/Java/jdk1.8.0_151/bin/jar.exe xvf intellij-go-0.171.1931.jar
cd META-INF
vi plugin.xml # Change the 'until-build="171.*" to 'until-build="172.*" and save the file
# if you are not comfortable with vi , you may edit this file in notepad++ (File location is /c/Users/<your win username>/Desktop/Golang-Intellij/Go/intellij-build/META-INF )
rm intellij-go-0.171.1931.jar
/c/Program\ Files/Java/jdk1.8.0_151/bin/jar.exe cvf ../intellij-go-0.171.1931.jar . # 'dot' at the end of the command is important
cd ..
rm -fr intellij-build
cd ../../

Go to Golang-Intellij directory in desktop and compress Go directory as a zip file (Righ click ->Send to->Compressed zip folder)
Now the plugin (Go.zip) is ready to import to IntelloJ IDEA

IntelliJ IDEA settings

Open IntelliJ IDEA and open a blank project
Go to File->Settings->Plugins->Install Plugin From disk
Here you have to select the zip file we made above (Go.zip) and apply and press OK; don’t restart IDEA at this stage

Import Coding Style

File->Import Settings->Select ‘Ladies Night 2.jar’ File from Golang-Intellij directory on desktop and it will ask for a confirmation ; say OK

Misc settings

File->Settings->Tools->Terminal->Shell Path->C:\Git\bin\bash.exe – press OK
File->Settings->Editor->Code Style->Go-> Set Tab Size , indent and Continuation indent to 4 – press OK
File->Settings->Color Scheme->Color Scheme font and Console Font can be changed to ‘Source code pro’ – press OK
File->Settings->Editor->File Types->Ignore files and folders – add ‘;*.iml;.git;.idea;’ – press OK

Integrate Github account

File->Settings->Version Control->Github->Click Create API Token – You will be asked to enter your Github account credentials – press OK
File->Settings->Version Control->Git->Path to Git executable->C:\Git\bin\git.exe – press OK

Now enjoy your new Golang IDE

The post Golang IDE using Intellij IDEA – Step by Step appeared first on .

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

Linux provides the following namespaces and we will see how we can demonstrate these with Go

       Namespace   Constant          Isolates
       Cgroup      CLONE_NEWCGROUP   Cgroup root directory
       IPC         CLONE_NEWIPC      System V IPC, POSIX message queues
       Network     CLONE_NEWNET      Network devices, stacks, ports, etc.
       Mount       CLONE_NEWNS       Mount points
       PID         CLONE_NEWPID      Process IDs
       User        CLONE_NEWUSER     User and group IDs
       UTS         CLONE_NEWUTS      Hostname and NIS domain name

This post is part one which explains the how we can implement User namespace
Namespaces were introduced in Linux to isolate a process .This is the fundamental idea which evolved to Linux containers (Docker,LXC etc..)

Lets start with a program user_namesapce_demo.go to execute a binary – here we will start a shell

package main

import (
        "os"
        "os/exec"
)

func main() {
       cmd := exec.Command("/bin/sh")
       cmd.Stdin = os.Stdin
       cmd.Stdout = os.Stdout
       cmd.Stderr = os.Stderr
       cmd.Run()
}

Compile and execute it

linxlabs@golang:~/.../Golang-Tutor> go build user_namesapce_demo.go
linxlabs@golang:~/.../Golang-Tutor> ./user_namesapce_demo
sh-4.3$ id
uid=1000(linxlabs) gid=100(users) groups=100(users)
sh-4.3$

We can see the user id is same as the parent shell as expected.
How can we change this behavior so that the newly spawned process will get a new user ID instead of its parent user ID
To accomplish that ,we will use USER Namespace
Lets rewrite the program to include user namespace

package main

import (
       "os"
       "os/exec"
       "syscall" // For SysProcAttr to pass clone flag CLONE_NEWUSER
)

func main() {
     cmd := exec.Command("/bin/sh")
     cmd.Stdin = os.Stdin
     cmd.Stdout = os.Stdout
     cmd.Stderr = os.Stderr
     cmd.SysProcAttr = &syscall.SysProcAttr{
         Cloneflags: syscall.CLONE_NEWUSER,
         }
     cmd.Run()
}

Compile and execute it to see the user id

linxlabs@golang:~/.../Golang-Tutor> go build user_namesapce_demo.go
linxlabs@golang:~/.../Golang-Tutor> ./user_namesapce_demo
sh-4.3$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
sh-4.3$

Now you can see “nobody” instead of “linxlabs”

We didn’t define any mappings in our program ,so Go will assign overflow ID 65534
So lets see what is UID/GID mappings

We will get a user id from parent process which will be called as “HostID”
In our “containerized” process we need a custom user ID which will be called as “ContainerID”

You may read more detailed implementation in this LKML article.
Below copied snipp is from the same article.

Normally, one of the first steps after creating a new user namespace is to define the mappings used for the user and group IDs of the processes that will be created in that namespace.
This is done by writing mapping information to the /proc/PID/uid_map and /proc/PID/gid_map files corresponding to one of the processes in the user namespace. (Initially, these two files are empty.)
This information consists of one or more lines, each of which contains three values separated by white space:

ID-inside-ns ID-outside-ns length
Together, the ID-inside-ns and length values define a range of IDs inside the namespace that are to be mapped to an ID range of the same length outside the namespace.
The ID-outside-ns value specifies the starting point of the outside range.
How ID-outside-ns is interpreted depends on the whether the process opening the file /proc/PID/uid_map (or /proc/PID/gid_map) is in the same user namespace as the process PID:

As per the documentation of SysProcAttr, we can add UID/GID mappings with below two structure members

UidMappings []SysProcIDMap // User ID mappings for user namespaces.
GidMappings []SysProcIDMap // Group ID mappings for user namespaces.

SysProcIDMap structure have three members which matches with the kernel documentation (ID-inside-ns ,ID-outside-ns and length)

type SysProcIDMap struct {
   ContainerID int // Container ID.
   HostID int // Host ID.
   Size int // Size.
}

So lets add few lines of codes to map both UID and GID

package main

import (
      "os"
      "os/exec"
      "syscall"
)

func main() {
     cmd := exec.Command("/bin/sh")
     cmd.Stdin = os.Stdin
     cmd.Stdout = os.Stdout
     cmd.Stderr = os.Stderr
     cmd.SysProcAttr = &syscall.SysProcAttr{
         Cloneflags: syscall.CLONE_NEWUSER,
          UidMappings: []syscall.SysProcIDMap{
           {
              ContainerID: 0,
              HostID: os.Getuid(),
              Size: 1,
           },
        },
         GidMappings: []syscall.SysProcIDMap{
           {
              ContainerID: 0,
              HostID: os.Getgid(),
              Size: 1,
          },
       },
    }
cmd.Run()
}

Lets compile and execute the program

linxlabs@golang:~/.../Golang-Tutor> go build user_namesapce_demo.go
linxlabs@golang:~/.../Golang-Tutor> ./user_namesapce_demo
sh-4.3#
sh-4.3# id
uid=0(root) gid=0(root) groups=0(root)
sh-4.3#

Now the shell shows root instead of nobody as we did the UID/GID mappings to “0” which is root

But that’s not all . Even Though the shell shows root , we will not be able to execute any privileged commands
For example , changing hostname whill be denied with an error shown below

sh-4.3# hostname test
hostname: you must be root to change the host name
sh-4.3#

This is because we only used one namespace and there is more name spaces to initialize which will allow the program to execute privileged commands in their own isolated place
The hostname command modifies a kernel paramter which is part of UTS namespace and we will see that implementation and demo in next article . Stay tunen

If you like this article , please subscribe and follow us on social media

The post Namespaces and Go Part 1 – USER Namespace appeared first on .

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 
LinuxLabs | Golang by Openlinuxlabs - 1y ago

The goals of the Go project were to eliminate the slowness and clumsiness of software development at Google to make the process more productive and scalable.

Brain behind Golang are the pioneers in computing

  • Kenn Thompson (B,C,Unix ,UTF8)
  • Rob Pike (Unix, UTF8)
  • Robert Griesemer (Hotspot, JVM)

(From left to right; Robert Griesemer, Rob Pike, Kenn Thompson)

These folks started sketching the goals for a new language on the whiteboard on September 21, 2007.
Within a few days, the goals had settled into a plan to do something and a fair idea of what it would be.

Design continued part-time in parallel with unrelated work.

By January 2008, Ken had started work on a compiler with which to explore ideas; it generated C code as its output.

By mid-year, the language had become a full-time project and had settled enough to attempt a production compiler.

In May 2008, Ian Taylor independently started on a GCC front end for Go using the draft specification.
Russ Cox joined in late 2008 and helped move the language and libraries from prototype to reality.

The thought was to have a language with efficient compilation, efficient execution, and ease of programming
because no language existed with all these three characteristics before go was developed

Referring to himself along with the other original authors of Go Kenn Thompson states :

“When the three of us [Thompson, Rob Pike, and Robert Griesemer] got started, it was pure research.
The three of us got together and decided that we hated C++. [laughter] … [Returning to Go,]
we started off with the idea that all three of us had to be talked into every feature in the language,
so there was no extraneous garbage put into the language for any reason”

Go became a public open source project on November 10, 2009.
Many people from the community have contributed ideas, discussions, and code.

Developers prefer ease Over Safety and moved to dynamically typed languages like Python, JavaScript, and Java.But that caused impact in efficiency and complexity

Go is an attempt to combine the ease of programming of an interpreted,
dynamically typed language with the efficiency and safety of a statically typed, compiled language.

In every respect, the language was designed by thinking about what programmers do and how to make programming, at least the kind of programming we do, more effective, which means more fun.

Still, if you didn’t get the answer to, why should I learn go ;

  • Look at the names who architected this language and their past.
  • Its backed by Google.
  • Cross-platform support (Linux, FreeBSD, Mac, Windows).
  • Famous OS container service Docker developed in go.
  • Container orchestration service Kubernetes developed in go.
  • Compiled binary (not like python or Perl or javascript which needs a separate runtime).
  • Execution speed, thin, garbage-collection, dynamic and so on.
  • Own runtime.
  • Object Oriented (without inheritance).
  • Simple syntax.
  • Concurrency using Goroutines.

So I would say Go is 21st century’s C language and there is no reason for you not to learn this language.

The post Why Should I learn Go ? appeared first on .

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

In this post I’ll explain how you can clone a project from git hub to your go work space
If you don’t have a project on GitHub to play with ; then please read this post to create one

So lets start

Go to GitHub project page to copy git URL

Try to clone the repository using ‘go get’ with the URL we copied

linxlabs@golang:~> go get https://github.com/OpenLinXlabs/Golang-Tutor.git
package https:/github.com/OpenLinXlabs/Golang-Tutor.git: "https://" not allowed in import path
linxlabs@golang:>;

It failed with message indicating that we cannot use “https:..” while mentioning URL

Now lets try without “https://”

linxlabs@golang:~> go get github.com/OpenLinXlabs/Golang-Tutor.git
package github.com/OpenLinXlabs/Golang-Tutor.git: invalid version control suffix in github.com/ path
linxlabs@golang:~>

Failed again saying invalid version control suffix – which means we cannot use .git suffix in URL

Now lets try again without .git suffix

linxlabs@golang:~> go get github.com/OpenLinXlabs/Golang-Tutor
go: missing Git command. See https://golang.org/s/gogetcmd
package github.com/OpenLinXlabs/Golang-Tutor: exec: "git": executable file not found in $PATH
linxlabs@golang:~>

Failed again with messaging saying , we need “git” binary

Install git package

Go to root and install ‘git’ package using one of the procedure below based on your distro.

For Fedora Based distros like RedHat or CentOS

# dnf install git-all

For Debian based distros like Ubuntu

# apt-get install git-all

Now lets try to execute go get again

linxlabs@golang~>; go get github.com/OpenLinXlabs/Golang-Tutor
# github.com/OpenLinXlabs/Golang-Tutor
github.com/OpenLinXlabs/Golang-Tutor/hello.go:5:14: invalid character literal (more than one character)
github.com/OpenLinXlabs/Golang-Tutor/hello.go:5:14: cannot use '\u0000' (type rune) as type string in argument to fmt.Printf
linxlabs@golang:~>

Failed once again with messages indicating syntax errors in our source .go file

Correct the syntax errors as mentioned by editing the file from GitHub

Now execute go get again

linxlabs@golang:~&amp;gt; go get github.com/OpenLinXlabs/Golang-Tutor</pre>
linxlabs@golang:~> ls -lR $GOPATH/src
/home/linxlabs/go_workspace/src:
total 1836
drwxr-xr-x 3 linxlabs users 4096 Oct 14 01:55 github.com

/home/linxlabs/go_workspace/src/github.com:
total 4
drwxr-xr-x 3 linxlabs users 4096 Oct 14 01:55 OpenLinXlabs

/home/linxlabs/go_workspace/src/github.com/OpenLinXlabs:
total 4
drwxr-xr-x 3 linxlabs users 4096 Oct 14 01:56 Golang-Tutor

/home/linxlabs/go_workspace/src/github.com/OpenLinXlabs/Golang-Tutor:
total 44
-rw-r--r-- 1 linxlabs users 72 Oct 14 01:56 hello.go
-rw-r--r-- 1 linxlabs users 35141 Oct 14 01:56 LICENSE
-rw-r--r-- 1 linxlabs users 52 Oct 14 01:56 README.md
linxlabs@golang:~>

voila.! it worked.

Now you can see the project directories and files

In my next post I’ll explain basics of git and how to push changes from command line to your github repository

The post How to clone a GitHub project to go work space appeared first on .

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

In this post I’ll explain how you can setup golang on any 64bit Linux distribution (Fedora/Ubuntu/SuSE/CentOS/..you name it)

Make sure you are doing these steps from a non-root user ; I’m using a non-root user ‘linxlabs’ throughout this post

Download

Download ‘golang’ binary archive from https://golang.org/dl/
OR
Copy the URL of Linux binary from https://golang.org/dl/ to download it via ‘wget’ from command line

linxlabs@golang:~> wget https://storage.googleapis.com/golang/go1.9.1.linux-amd64.tar.gz
--2017-10-09 23:52:00-- https://storage.googleapis.com/golang/go1.9.1.linux-amd64.tar.gz
Resolving storage.googleapis.com (storage.googleapis.com)... 74.125.68.128, 2404:6800:4003:c02::80
Connecting to storage.googleapis.com (storage.googleapis.com)|74.125.68.128|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 104197862 (99M) [application/x-gzip]
Saving to: ‘go1.9.1.linux-amd64.tar.gz’

100%[=======================================================================>] 104,197,862 9.90MB/s in 13s

2017-10-09 23:52:14 (7.48 MB/s) - ‘go1.9.1.linux-amd64.tar.gz’ saved [104197862/104197862]

linxlabs@golang:~>

Installation

Extract the contents using tar command.
You will see a directory called ‘go’ in your home directory

linxlabs@golang:~> tar -xvf go1.9.1.linux-amd64.tar.gz
linxlabs@golang:~> ls -lrt
total 101764
drwxr-xr-x 2 linxlabs users 4096 May 10 04:56 bin
drwxr-xr-x 11 linxlabs users 4096 Oct 5 00:24 go
-rw-r--r-- 1 linxlabs users 104197862 Oct 5 01:59 go1.9.1.linux-amd64.tar.gz
linxlabs@golang:~>

Environment Setup

To include go binaries in you path variable edit .bash_profile
(by the way this may vary based on user’s shell; I’m using default shell BASH – execute “echo ${SHELL}” to verify to know your shell )

linxlabs@golang:~> vi .bash_profile
PATH=${PATH}:~/go/bin

To make the PATH variable set , either you may logout and login OR execute “source .bash_profile”

linxlabs@golang:~> logout

Verify Go setup

Execute “go version” to verify your installation

linxlabs@golang:~> go version
go version go1.9.1 linux/amd64
linxlabs@golang:~>
linxlabs@golang:~> go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/linxlabs/go"
GORACE=""
GOROOT="/home/linxlabs/go"
GOTOOLDIR="/home/linxlabs/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
linxlabs@golang:~>

Here you can see a set of default variables.
The ‘GOPATH’ environment variable specifies the location of your ‘workspace’.
The ‘GOROOT’ environment variable specifies the location of the ‘go installed directory’
You may set this if you installed “go” in a different path

I would recommend to set this path to different filesystem where you have redundancy on file system (Storage LUN , MD-RAID , LVM mirror )
This is to make sure you will not lose your hard work in case of a disk failure

So edit .bash_profile again and add your path . I’ll be setting it to a test directory called /home/linxlabs/go_workspace

linxlabs@golang:~> echo "export GOPATH=/home/linxlabs/go_workspace" >>.bash_profile
linxlabs@golang:~> source .bash_profile

Verify your work space again with “go env” command

linxlabs@golang:~> go env |grep GOPATH
GOPATH="/home/linxlabs/go_workspace"
linxlabs@golang:~>

Now create few mandatory directories in your workspace

linxlabs@golang:~> cd ${GOPATH}
linxlabs@golang:~/go_workspace> mkdir src bin pkg

Write your first golang program

So let’s write our first golang program

linxlabs@golang:~> cd ${GOPATH}/src
linxlabs@golang:~> vi hello.go
package main
import "fmt"
func main(){
fmt.Printf("hello, world\n")
}

Golang formating 

Above code looks ok , but its a bad coding style as there is no proper spacing or indentation
But go have an option to set the proper readable style formatting with ‘go fmt’

linxlabs@golang:~/go_workspace/src> go fmt
hello.go

Now do a cat on hello.go , you will see beautiful coding style

linxlabs@golang:~/go_workspace/src> cat hello.go
package main

import "fmt"

func main() {
       fmt.Printf("hello, world\n")
}

How to run your code

linxlabs@golang:~/go_workspace/src> go run hello.go
hello, world

If you got a hello, world ; then congratulations , you made your first step to the world of ‘golang’

But , where is your binary which can be executed without running it from source code every time! ?

When you execute go run , go will create temporary files to build the code and it will be deleted after execution

Build binary

So to build the binary , execute below

linxlabs@golang:~/go_workspace/src> go build hello.go
linxlabs@golang:~/go_workspace/src> ls -lrt
total 1832
-rw-r--r-- 1 linxlabs users 74 Oct 10 00:34 hello.go
-rwxr-xr-x 1 linxlabs users 1868323 Oct 10 00:42 hello
linxlabs@golang:~/go_workspace/src>

Now you can see a binary file called ‘hello’ which can be executed

linxlabs@golang:~/go_workspace/src> ./hello
hello, world

Install binary to a path

we will see ,how we can ‘install’ it to the bin directory – (mimic of make install)

linxlabs@golang:~/go_workspace/src> go install
go install: no install location for directory /home/linxlabs/go_workspace/src outside GOPATH
For more details see: 'go help gopath'

We got an error saying that our present directory is outside of GOPATH ; which is true . Now what we can do to over come this ?

Here we will export one more variable GOBIN to install binaries

linxlabs@golang:~/go_workspace/src> export GOBIN=/home/linxlabs/go_workspace/bin
linxlabs@golang:~/go_workspace/src> go install hello.go
linxlabs@golang:~/go_workspace/src> ls ../bin/
hello

You have to make sure the GOBIN is persistent by appending it to .bash_profile

linxlabs@golang:~/go_workspace/src> echo "export GOBIN=/home/linxlabs/go_workspace/bin" >>~/.bash_profile

In next post I’ll show you how to integrate your github account with go and how to commit to your repository with go

The post How to install and setup golang appeared first on .

Read Full Article

Read for later

Articles marked as Favorite are saved for later viewing.
close
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

Separate tags by commas
To access this feature, please upgrade your account.
Start your free month
Free Preview