The original milapneupane.com.np/2019/07/06/…

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. – GoLang

In many languages, there are many ways to solve a given problem. Programmers can spend a lot of time thinking about the best way to solve problems. Golang, on the other hand, insists on streamlined features — there’s only one right way to solve a problem.

This saves developers time and makes large code bases easy to maintain. There are no “expressive” features like maps and filters in Golang.

“If you have features that add expressiveness, it usually adds to the cost” — Rob Pike

Golang’s new logo, recently released: HTTPS://blog.golang.org/go-brand

An introduction to

Golang consists of packages. The package main tells the Golang compiler that the program is compiled as an executable, not a shared library. It is the entry point to the application. The main package is defined as:

package main
Copy the code

Let’s write a simple Hello World example by creating a file in the Go Lang workspace via main.go

The workspace

The workspace in Go is defined by the environment variable GOPATH.

Any code you write will be written in your workspace. Go will search for all packages in the GOPATH directory, or the directory GOROOT defaults to when installing Go. GOROOT is the path to install Go.

Set GOPATH to the desired directory. Now, let’s set ~/workspace to GOPATH.

# export env
export GOPATH=~/workspace
# go inside the workspace directory
cd ~/workspace
Copy the code

Use the following code to create the file in the workspace folder we just created in main.go.

HELLO WORLD!

 package main

 import (
     "fmt"
 )

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

In the example above, FMT is a function in Go that the built-in package implements to format I/O.

We import packages in Go using the import keyword. Func Main is the main entry point for code execution. Println is a function inside the package, FMT that prints “Hello world” for us.

Let’s take a look at running this file. We can run the Go command in two ways. As we know, Go is a compiled language, so we first need to compile it before we execute it.

> go build main.go
Copy the code

This will create a binary executable file, main, which we can now run

> ./main 
# Hello World!
Copy the code

Note: To try to run the code mentioned in this article, you can useplay.golang.org

variable

Variables in Go are explicitly declared. Go is a statically typed language. This means checking the variable type at variable declaration time. Variables can be declared as:

var a int
Copy the code

In this case, the value will be set to 0. Declare and initialize variables with different values using the following syntax:

var a = 1
Copy the code

Here the variable is automatically specified as int. We can use the shorthand definition for variable declarations:

message := "hello world"
Copy the code

We can also declare multiple variables on the same line:

Var b, c int = 2,3Copy the code

The data type

Like any other programming language, Golang supports a variety of different data structures. Let’s explore:

NUMBER, STRING, AND BOOLEAN

Some INT types are INT, int8, INT16, INT32, INT64, uint, uint8, uint16, uint32, uint64, uintptr……

The string type stores a sequence of bytes. It is represented and declared with the keyword string.

Use the keyword bool to store Boolean types.

Golang also supports complex numeric types, which can be complex64 and complex128.

var a bool = true
var b int = 1
var c string = "hello world"
var d floatComplex128 = cmplx.sqrt (-5 + 12i)Copy the code

ARRAYS, SLICES, AND MAPS

An array is a sequence of elements of the same data type. Arrays have a fixed length defined in the declaration and therefore cannot be expanded. The array declaration is:

var a [5] int
Copy the code

Arrays can also be multidimensional. We can create them using the following format:

var multiD [2] [3] int
Copy the code

Arrays limit this when their values change at run time. Arrays also do not provide the ability to get subarrays. For this, Golang has a data type called slices.

Slices store a series of elements that can be extended at any time. A slice declaration is similar to an array declaration – no capacity is defined:

var b [] int
Copy the code

This will create a slice with zero capacity and zero length. Slicing can also define capacity and length. We can use the following syntax:

Numbers: = make ([] int, 5,10)Copy the code

Here, the initial length of the slice is 5 and the capacity is 10.

Slicing is an abstraction of an array. Slicing uses an array as its underlying structure. Slicing consists of three components: capacity, length, and a pointer to the underlying array, as shown below:

You can increase the size of slices by using append or copy. The append function adds value to the end of an array and increases capacity as needed.

numbers = append(numbers, 1, 2, 3, 4)
Copy the code

Another way to increase slice capacity is to use the copy function. Simply create another slice with a larger capacity and copy the original slice to the newly created slice:

// create a new slice
number2 := make([]int, 15)
// copy the original slice to new slice
copy(number2, number)
Copy the code

We can create subslices of slices. This can be done with the following command:

 package main

 import (
     "fmt"
 )

 func main() {
     // initialize a slice with 4 len and values
     number2 := []int{1, 2, 3, 4}
     fmt.Println(number2) // -> [1 2 3 4]
     // create sub slices
     slice1 := number2[2:]
     fmt.Println(slice1) // -> [3 4]
     slice2 := number2[:3]
     fmt.Println(slice2) // -> [1 2 3]
     slice3 := number2[1:4]
     fmt.Println(slice3) // -> [2 3 4]
 }
Copy the code

Map is the data type in Go that maps keys to values. We can define the mapping using the following command:

var m map[string]int
Copy the code

This m is the new map variable, whose key is string and value is integers. We can easily add keys and values to the map:

package main

 import (
     "fmt"
 )

 func main() {
     m := make(map[string]int)
     // adding key/value
     m["clearity"] = 2
     m["simplicity"] = 3
     // printing the values
     fmt.Println(m["clearity"])   // -> 2
     fmt.Println(m["simplicity"] // -> 3}Copy the code

Type conversion

You can use type conversions to convert a data type of one type to another. Let’s look at a simple cast:

 package main

 import (
     "fmt"
 )

 func increment(i *int) {
     *i++
 }

 func main() {a := 1.1 b := int(a) FMT.Println(b) //-> 1}Copy the code

Not all types of data types can be converted to other types. Make sure the data type is compatible with the transformation.

Conditional statements

IF ELSE

For conditional statements, we can use if-else statements, as shown in the following example. Make sure the curly braces are on the same line as the condition.

 package main

 import (
     "fmt"
 )

 func increment(i *int) {
     *i++
 }

 func main() {
     if num := 9; num < 0 {
         fmt.Println(num, "is negative")}else if num < 10 {
         fmt.Println(num, "has 1 digit")}else {
         fmt.Println(num, "has multiple digits")}}Copy the code

SWITCH CASE

Switch Cases help organize multiple conditional statements. The following example shows a simple switch case statement:

 package main

 import (
     "fmt"
 )

 func increment(i *int) {
     *i++
 }

 func main() {
     i := 2
     switch i {
     case 1:
         fmt.Println("one")
     case 2:
         fmt.Println("two")
     default:
         fmt.Println("none")}}Copy the code

Looping

Golang has a circular keyword. A single for loop command helps to implement different types of loops:

 package main

 import (
     "fmt"
 )

 func increment(i *int) {
     *i++
 }

 func main() {
     i := 0
     sum := 0
     for i < 10 {
         sum += 1
         i++
     }
     fmt.Println(sum)
 }
Copy the code

The example above is similar to the while loop in C. For the for loop, we can use the same for statement:

 package main

 import (
     "fmt"
 )

 func increment(i *int) {
     *i++
 }

 func main() {
     sum := 0
     for i := 0; i < 10; i++ {
         sum += i
     }
     fmt.Println(sum)
 }
Copy the code

Infinite loop in Go:

for{}Copy the code

Pointer to the

Golang provides Pointers. A pointer is where the address of the value is stored. A pointer is defined by *. Define Pointers based on data types. Ex. :

var ap * int
Copy the code

This AP is a pointer to an integer type. The & operation can be used to get the address of a variable.

A := 12 ap =&aCopy the code

The * operator can be used to access the value to which the pointer points:

Fmt. Println (* AP) // => 12Copy the code

Pointers are usually preferred when structs are passed as arguments or methods are declared for defined types.

  • When passing values, the actual copied value means more memory
  • After passing the pointer, the value changed by the function is reflected in the method/function caller.

Ex. :

package main

 import (
     "fmt"
 )

 func increment(i *int) {
     *i++
 }

 func main() {
     i := 10
     increment(&i)
     fmt.Println(i)
 }

 //=> 11
Copy the code

Note: When you run the sample code in this article, don’t forget to include it in the main package and import FMT or other packages as needed, as shown in the first main.go example above.

function

The main function defined in the main package is the entry point for the execution of the Golang program. More functions can be defined and used. Let’s look at a simple example:

 package main

 import (
     "fmt"
 )

 func add(a int, b int) int {
     c := a + b
     return c
 }

 func main() {
     fmt.Println(add(2, 1))
 }
 //=> 3
Copy the code

As we saw in the example above, the Golang function is defined using the func keyword followed by the function name. The parameters required by a function need to be defined according to its data type, and finally the data type returned.

The return value of a function can also be predefined in a function:

package main

 import (
     "fmt"
 )

 func add(a int, b int) (c int) {
     c = a + b
     return
 }

 func main(a) {
     fmt.Println(add(2.1))}/ / = > 3
Copy the code

Here c is defined as the return variable. Therefore, the defined variable C is returned automatically without having to be defined in the closing return statement.

You can also return multiple return values from a function, separating the return values from commas.

package main

 import (
     "fmt"
 )

 func add(a int, b int) (int.string) {
     c := a + b
     return c, "successfully added"
 }

 func main(a) {
     sum, message := add(2.1)
     fmt.Println(message)
     fmt.Println(sum)
 }

 //=> successfully added
 / / = > 3
Copy the code

Methods, structures, and interfaces

Golang is not a fully object-oriented language, but has structures, interfaces, and methods to support object-oriented development.

The structure of the body

A structure is a collection of types for different fields. Structs are used to group data together. For example, if we wanted to group data of type Person, we would define a Person’s attributes, which might include name, age, and gender. You can define the structure using the following syntax:

typePerson struct {person struct {person struct}Copy the code

With a person type structure defined, let’s now create a person:

//way 1: specifying attribute and value
p = person{name: "Bob", age: 42, gender: "Male"}
//way 2: specifying only value
person{"Bob", 42, "Male"}
Copy the code

We can use point (.) Easy access to this data

p.name
//=> Bob
p.age
//=> 42
p.gender
//=> Male
Copy the code

You can also use its Pointers to access the structure’s properties directly:

pp = &person{name: "Bob", age: 42, gender: "Male"}
pp.name
//=> Bob
Copy the code

methods

Methods are special types of functions with receivers. A receiver can be either a value or a pointer. Let’s create a method called Describe, which is part of the Person structure in our example above:

package main

 import "fmt"

 // struct defination
 type person struct {
     name   string
     age    int
     gender string
 }

 // method defination
 func (p *person) describe() {
     fmt.Printf("%v is %v years old.", p.name, p.age)
 }

 func (p *person) setAge(age int) {
     p.age = age
 }

 func (p person) setName(name string) {
     p.name = name
 }

 func main() {
     pp := &person{name: "Bob", age: 42, gender: "Male"}
     pp.describe()
     // => Bob is 42 years old
     pp.setAge(45)
     fmt.Println(pp.age)
     //=> 45
     pp.setName("Hari")
     fmt.Println(pp.name)
     //=> Bob
 }
Copy the code

As we saw in the above example, the method pp.describe can now be called using the dot operator. Note that the receiver is the pointer. With a pointer, we pass a reference to that value, so if we make any changes to the method, it will be reflected in the sink PP. It also saves memory by not creating new copies of objects.

Notice that in the example above, the value of age has changed, but the value of name has not, because the method setName is of the sink type and setAge is of the pointer type.

interface

The Golang interface is a collection of methods. Interfaces help to group attributes of a type together. Take the animal interface as an example:

 type animal interface {
     description() string
 }
Copy the code

Animal here is the interface type. Now let’s create two different types of Animal to implement the Animal interface:

package main

 import (
     "fmt"
 )

 type animal interface {
     description() string
 }

 type cat struct {
     Type  string
     Sound string
 }

 type snake struct {
     Type      string
     Poisonous bool
 }

 func (s snake) description() string {
     return fmt.Sprintf("Poisonous: %v", s.Poisonous)
 }

 func (c cat) description() string {
     return fmt.Sprintf("Sound: %v", c.Sound)
 }

 func main() {
     var a animal
     a = snake{Poisonous: true}
     fmt.Println(a.description())
     a = cat{Sound: "Meow!!!"}
     fmt.Println(a.description())
 }

 //=> Poisonous: true
 //=> Sound: Meow!!!
Copy the code

In the main function, we create a variable of type A animal. We assign snake and cat types to animal and print a.description using Println. Since we implement the methods described in the two types (cat and snake) in different ways, we get descriptions of different animals.

package

We write all the code in Golang in one package. This main package is the entry point for program execution. There are many built-in packages in Go. The one we’ve been using the most is the FMT package.

“Go packages in the main mechanism for programming in the large that Go provides and they make possible to divvy up a Large project into smaller pieces.”

– Robert Griesemer

Install a package

go get 
// example
go get github.com/satori/go.uuid
Copy the code

Our installed packages are stored in GOPATH, our working directory. You can access the package CD $GOPATH/ PKG through the PKG folder in our working directory.

Create a custom package

Let’s start by creating a folder custom_package:

> mkdir custom_package
> cd custom_package
Copy the code

To create a custom package, we need to first create a folder with the package name we want. Suppose we are building a package person. To do this, we create a folder named person in the custom_package folder:

> mkdir person
> cd person
Copy the code

Now let’s create a file person.go in this folder.

package person

 func Description(name string) string {
     return "The person name is: " + name
 }

 func secretName(name string) string {
     return "Do not share"
 }
Copy the code

We now now need to install the package so that it can be imported and used. So let’s install it:

> go install
Copy the code

Now let’s go back to the custom_package folder and create a main.go file

 package main

 import (
     "custom_package/person"
     "fmt"
 )

 func main() {
     p := person.Description("Milap")
     fmt.Println(p)
 }

 // => The person name is: Milap
Copy the code

Now we can import the Person package we created and use the function Description. Note that the secretName function we created in the package will not be accessible. In Go, method names that begin with a lowercase letter will be private.

Package document

Golang has built-in support for package documentation. Run the following command to generate the document:

godoc person Description
Copy the code

This will document the Description function for our package developers. To view the document, run the Web server using the following command:

Godoc-http = ": 8080"Copy the code

Now open the URLhttp / / localhost8080 / PKG/and view the document we just create packages.

Some of the built-in packages in GO

FMT

This package implements formatted I/O functionality. We have used this package to print to STdout.

JSON

Another useful package in Golang is the JSON package. This helps to encode/decode JSON. Let’s take an example of encoding/decoding some JSON:

encode

package main

 import (
     "encoding/json"
     "fmt"
 )

 func main() {
     mapA := map[string]int{"apple": 5, "lettuce": 7}
     mapB, _ := json.Marshal(mapA)
     fmt.Println(string(mapB))
 }
Copy the code

Decode

package main

 import (
     "encoding/json"
     "fmt"
 )

 type response struct {
     PageNumber int      json:"page"
     Fruits     []string json:"fruits"
 }

 func main() {
     str := {"page": 1, "fruits": ["apple"."peach"]}
     res := response{}
     json.Unmarshal([]byte(str), &res)
     fmt.Println(res.PageNumber)
 }

 //=> 1
Copy the code

When unmarshal decodes the JSON bytes, the first argument is the JSON byte and the second argument is the address of the response type struct that we want the JSON to map to. Note that the JSON: “Page” mapping page key is the PageNumber key in the structure.

Error handling

Bugs are unwanted and unintended consequences of a program. Suppose we are making an API call to an external service. This API call may or may not succeed. Errors in Golang programs can be identified when there are error types. Let’s take a look at this example:

resp, err := http.Get("http://example.com/")
Copy the code

Err here indicates that the API call may pass or may fail. We can check if the error is nil and handle the response accordingly:

 package main

 import (
     "fmt"
     "net/http"
 )

 func main() {
     resp, err := http.Get("http://example.com/")
     iferr ! = nil { fmt.Println(err)return
     }
     fmt.Println(resp)
 }
Copy the code

Function returns a custom error

When we write our own functions, there are situations where we encounter errors. Errors is used to return these errors:

  package main

 import (
     "errors"
     "fmt"
 )

 func Increment(n int) (int, error) {
     if n < 0 {
         // return error object
         return 0, errors.New("math: cannot process negative number")}return (n + 1), nil
 }

 func main() {
     num := 5
     ifinc, err := Increment(num); err ! = nil { fmt.Printf("Failed Number: %v, error message: %v", num, err)
     } else {
         fmt.Printf("Incremented Number: %v", inc)
     }
 }

 // => The person name is: Milap
Copy the code

Most packages built in Go or the external packages we use have an error handling mechanism. So any function we call can have an error. These errors should never be ignored and are always handled elegantly in what we call a function, as we did in the example above.

panic

Panic is an unhandled error that is encountered suddenly during program execution. In Go, Panic is not the ideal way to handle exceptions in a program. Error objects are recommended. Program execution stops when panic occurs. The thing that happened after Panic was defer.

package main

import "fmt"

func main(a) {
 f()
 fmt.Println("Returned normally from f.")}func f(a) {
 defer func(a) {
     if r := recover(a); r ! =nil {
         fmt.Println("Recovered in f", r)
     }
 }()
 fmt.Println("Calling g.")
 g(0)
 fmt.Println("Returned normally from g.")}func g(i int) {
 if i > 3 {
     fmt.Println("Panicking!")
     panic(fmt.Sprintf("%v", i))
 }
 defer fmt.Println("Defer in g", i)
 fmt.Println("Printing in g", i)
 g(i + 1)}Copy the code

defer

Defer is always executed at the end of the function.

In the example above, we use panic() to panic the program. As you have noticed, there is a delay statement that causes the program to execute the line at the end of the program execution. We can also use Defer when we need to do something at the end of a function, such as closing a file.

concurrent

Golang builds with concurrency in mind. Concurrency in Golang can be achieved through the Go routine of lightweight threads.

Go routine

A Goroutine is a function that can be run in parallel or at the same time as another function. Creating a Goroutine is simple. Simply by adding the keyword Go in front of the function, we can make it execute in parallel. Go coroutines are very lightweight, so we can create thousands of routines. Let’s look at a simple example:

package main

 import (
     "fmt"
     "time"
 )

 func main() {
     go c()
     fmt.Println("I am main")
     time.Sleep(time.Second * 2)
 }

 func c() {
     time.Sleep(time.Second * 2)
     fmt.Println("I am concurrent")
 }

 //=> I am main
 //=> I am concurrent
Copy the code

As you can see in the example above, function C is a Goroutine that executes in parallel with the main Go thread. Sometimes we want to share resources between multiple threads. Golang does not like sharing variables from one thread with another because it increases the possibility of deadlocks and resource waits. There is another way to share resources between Goroutines: Channels.

channel

We can use channels to pass data between two Goroutines. When creating a channel, you must specify the data type to be received by the channel. Let’s create a simple channel of type string as follows:

c := make(chan string)
Copy the code

Using this channel, we can send string data. We can all send and receive data in this channel:

package main

 import "fmt"

 func main() {
     c := make(chan string)
     go func() { c <- "hello" }()
     msg := <-c
     fmt.Println(msg)
 }

 //=>"hello"The receiver channel waits for the sender to send data to the channel.Copy the code

A one-way passage

In some cases, we want a Goroutine to receive data over a channel but not send it, and vice versa. To do this, we can also create one-way channels. Let’s look at a simple example:

 package main

 import (
     "fmt"
 )

 func main() {
     ch := make(chan string)
     go sc(ch)
     fmt.Println(<-ch)
 }

 func sc(ch chan<- string) {
     ch <- "hello"
 }
Copy the code

In the example above, the SC is a Goroutine that can only send messages to channels but not receive them.

Use SELECT to process multiple channels for Goroutine

There may be multiple channels waiting in a function. To do this, we can use the SELECT statement. Let’s look at a clearer example:

 package main

 import (
     "fmt"
     "time"
 )

 func main() {
     c1 := make(chan string)
     c2 := make(chan string)
     go speed1(c1)
     go speed2(c2)
     fmt.Println("The first to arrive is:")
     select {
     case s1 := <-c1:
         fmt.Println(s1)
     case s2 := <-c2:
         fmt.Println(s2)
     }
 }

 func speed1(ch chan string) {
     time.Sleep(2 * time.Second)
     ch <- "speed 1"
 }

 func speed2(ch chan string) {
     time.Sleep(1 * time.Second)
     ch <- "speed 2"
 }
Copy the code

In the example above, Main is waiting for channels C1 and C2. Use the SELECT Case statement to print the main function, and the message is sent from the channel, regardless of which it received first.

Buffer channel

You can create buffered channels in Golang. Use the buffered channel, which blocks messages sent to the channel if the buffer is full. Let’s take a look at this example:

package main

 import "fmt"

 func main() {
     ch := make(chan string, 2)
     ch <- "hello"
     ch <- "world"
     ch <- "!" // extra message in buffer
     fmt.Println(<-ch)
 }

 // => fatal error: all goroutines are asleep - deadlock!
Copy the code

Why did GOLANG succeed?

Simplicity… – Rob pike

Great!

We learned about some of Golang’s major components and capabilities.

  1. Variables, data types
  2. Array slicing and Map
  3. function
  4. Loop and conditional statements
  5. Pointer to the
  6. package
  7. Methods, structures, and interfaces
  8. Error handling
  9. Concurrency -Goroutines and channels

Congratulations, you now have a good idea about Go.

One of my most productive days was throwing away 1,000 lines of code. –Ken Thompson

Don’t stop here. Move on. Consider a small application and start building it.