Go hits the very sweet spot of performance and speedy development. It takes some elements from dynamic languages like Python and couples them with static typing at compile time. And according ZipRecruiter Golang Developer Annual Salary in US is $125,851.
Go is a general-purpose language designed with systems programming in mind. It was initially developed at Google in year 2007 by Robert Griesemer, Rob Pike, and Ken Thompson. It is strongly and statically typed, provides inbuilt support for garbage collection and supports concurrent programming. Programs are constructed using packages, for efficient management of dependencies. Go programming implementations use a traditional compile and link model to generate executable binaries.
A Go function can return multiple values.
Consider:
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("Mahesh", "Kumar")
fmt.Println(a, b)
}No, Go takes a different approach. For plain error handling, Go's multi-value returns make it easy to report an error without overloading the return value. Go code uses error values to indicate an abnormal state.
Consider:
func Open(name string) (file *File, err error)f, err := os.Open("filename.ext")
if err != nil {
log.Fatal(err)
}
// do something with the open *File fIn Go there are various ways to return a struct value or slice thereof. Could you explain the difference?
type MyStruct struct {
Val int
}
func myfunc() MyStruct {
return MyStruct{Val: 1}
}
func myfunc() *MyStruct {
return &MyStruct{}
}
func myfunc(s *MyStruct) {
s.Val = 1
}Shortly:
In Go, a string is a primitive type, which means it is read-only, and every manipulation of it will create a new string.
So if I want to concatenate strings many times without knowing the length of the resulting string, what's the best way to do it?
Beginning with Go 1.10 there is a strings.Builder. A Builder is used to efficiently build a string using Write methods. It minimizes memory copying. The zero value is ready to use.
package main
import (
"strings"
"fmt"
)
func main() {
var str strings.Builder
for i := 0; i < 1000; i++ {
str.WriteString("a")
}
fmt.Println(str.String())
}Goroutines are functions or methods that run concurrently with other functions or methods. Goroutines can be thought of as light weight threads. The cost of creating a Goroutine is tiny when compared to a thread. Its common for Go applications to have thousands of Goroutines running concurrently.
Go is an attempt to introduce a new, concurrent, garbage-collected language with fast compilation and the following benefits:
Following are the benefits of using Go programming:
x := 0 is valid declaration of a variable x of type int).A dynamic type variable declaration requires compiler to interpret the type of variable based on value passed to it. Compiler don't need a variable to have type statically as a necessary requirement.
Static type variable declaration provides assurance to the compiler that there is one variable existing with the given type and name so that compiler proceed for further compilation without needing complete detail about the variable. A variable declaration has its meaning at the time of compilation only, compiler needs actual variable declaration at the time of linking of the program.
A pointer variable can hold the address of a variable.
Consider:
var x = 5 var p *int p = &x
fmt.Printf("x = %d", *p)Here x can be accessed by *p.
Go is very strict about explicit typing. There is no automatic type promotion or conversion. Explicit type conversion is required to assign a variable of one type to another.
Consider:
i := 55 //int
j := 67.8 //float64
sum := i + int(j) //j is converted to intGo was born out of frustration with existing languages and environments for systems programming.
Go is an attempt to have:
To meet these goals required addressing a number of linguistic issues: an expressive but lightweight type system; concurrency and garbage collection; rigid dependency specification; and so on. These cannot be addressed well by libraries or tools so a new language was born.
Or can I just define two functions with the same name and a different number of arguments?
Go does not have optional parameters nor does it support method overloading:
Method dispatch is simplified if it doesn't need to do type matching as well. Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.
Tricky questions and the answer is no one worked. There is no Go version 2 available in 2018 but there are some movement toward it. Go 1 was released in 2012, and includes a language specification, standard libraries, and custom tools. It provides a stable foundation for creating reliable products, projects, and publications. The purpose of Go 1 is to provide long-term stability. There may well be a Go 2 one day, but not for a few years and it will be influenced by what we learn using Go 1 as it is today.
The possible goals and features of Go 2 are:
Two values are swapped as easy as this:
a, b = b, aTo swap three values, we would write:
a, b, c = b, c, aThe swap operation in Go is guaranteed from side effects. The values to be assigned are guaranteed to be stored in temporary variables before starting the actual assigning, so the order of assignment does not matter.
Map in Go?You copy a map by traversing its keys. Unfortunately, this is the simplest way to copy a map in Go:
a := map[string]bool{"A": true, "B": true}
b := make(map[string]bool)
for key, value := range a {
b[key] = value
}The new keyword can be used to create a new struct. It returns a pointer to the newly created struct.
var pa *Student // pa == nil
pa = new(Student) // pa == &Student{"", 0}
pa.Name = "Alice" // pa == &Student{"Alice", 0}You can also create and initialize a struct with a struct literal.
b := Student{ // b == Student{"Bob", 0}
Name: "Bob",
}
pb := &Student{ // pb == &Student{"Bob", 8}
Name: "Bob",
Age: 8,
}
c := Student{"Cecilia", 5} // c == Student{"Cecilia", 5}
d := Student{} // d == Student{"", 0}Map contains a key in Go?if val, ok := dict["foo"]; ok {
//do something here
}if statements in Go can include both a condition and an initialization statement. The example above uses both:
initializes two variables - val will receive either the value of "foo" from the map or a "zero value" (in this case the empty string) and ok will receive a bool that will be set to true if "foo" was actually present in the map
evaluates ok, which will be true if "foo" was in the map
If "foo" is indeed present in the map, the body of the if statement will be executed and val will be local to that scope.
func reverse(s []int) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
func main() {
a := []int{1, 2, 3}
reverse(a)
fmt.Println(a)
// Output: [3 2 1]
}Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. This is in contrast to most object-oriented languages like C++, Java, C#, Scala, and even dynamic languages like Python and Ruby.
Go Object-Oriented Language Features:
The Go way to implement:
Consider:
package main
import (
"fmt"
)
// interface declaration
type Income interface {
calculate() int
source() string
}
// struct declaration
type FixedBilling struct {
projectName string
biddedAmount int
}
type TimeAndMaterial struct {
projectName string
noOfHours int
hourlyRate int
}
// interface implementation for FixedBilling
func (fb FixedBilling) calculate() int {
return fb.biddedAmount
}
func (fb FixedBilling) source() string {
return fb.projectName
}
// interface implementation for TimeAndMaterial
func (tm TimeAndMaterial) calculate() int {
return tm.noOfHours * tm.hourlyRate
}
func (tm TimeAndMaterial) source() string {
return tm.projectName
}
// using Polymorphism for calculation based
// on the array of variables of interface type
func calculateNetIncome(ic []Income) {
var netincome int = 0
for _, income := range ic {
fmt.Printf("Income From %s = $%d\n", income.source(), income.calculate())
netincome += income.calculate()
}
fmt.Printf("Net income of organisation = $%d", netincome)
}
func main() {
project1 := FixedBilling{projectName: "Project 1", biddedAmount: 5000}
project2 := FixedBilling{projectName: "Project 2", biddedAmount: 10000}
project3 := TimeAndMaterial{projectName: "Project 3", noOfHours: 160, hourlyRate: 25}
incomeStreams := []Income{project1, project2, project3}
calculateNetIncome(incomeStreams)
}foreach construct in the Go language?A for statement with a range clause iterates through all entries of an array, slice, string or map, or values received on a channel. For each entry it assigns iteration values to corresponding iteration variables and then executes the block.
for index, element := range someSlice {
// index is the index where we are
// element is the element from someSlice for where we are
}If you don't care about the index, you can use _:
for _, element := range someSlice {
// element is the element from someSlice for where we are
}rune type in Go?There are many other symbols invented by humans other than the 'abcde..' symbols. And there are so many that we need 32 bit to encode them.
A rune is a builtin type in Go and it's the alias of int32. rune represents a Unicode CodePoint in Go. It does not matter how many bytes the code point occupies, it can be represented by a rune. For example the rule literal a is in reality the number 97.
A string is not necessarily a sequence of runes. We can convert between string and []rune, but they are different.
Constants in Go are special.
4.5 can be used anywhere a floating-point value is allowed. We can use untyped constants to temporarily escape from Go’s strong type system until their evaluation in a type-demanding expression.1 // untyped integer constant
const a = 1
var myFloat32 float32 = 4.5
var myComplex64 complex64 = 4.5const typedInt int = 1 Generally we should declare a type for a constant only if it’s absolutely necessary. Otherwise, just declare constants without a type.
= and := operator? In Go, := is for declaration + assignment, whereas = is for assignment only.
For example, var foo int = 10 is the same as foo := 10.
struct{}?You would use an empty struct when you would want to save some memory. Empty structs do not take any memory for its value.
a := struct{}{}
println(unsafe.Sizeof(a))
// Output: 0This saving is usually insignificant and is dependent on the size of the slice or a map. Although, more important use of an empty struct is to show a reader you do not need a value at all. Its purpose in most cases is mainly informational.
init() function run?Rust has been Stack Overflow’s most loved language for four years in a row and emerged as a compelling language choice for both backend and system developers, offering a unique combination of memory safety, performance, concurrency without Data races...
Clean Architecture provides a clear and modular structure for building software systems, separating business rules from implementation details. It promotes maintainability by allowing for easier updates and changes to specific components without affe...
Azure Service Bus is a crucial component for Azure cloud developers as it provides reliable and scalable messaging capabilities. It enables decoupled communication between different components of a distributed system, promoting flexibility and resili...