package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}
You can write two types of programs: executable programs and shared libraries. When you write
executable programs, you must give main as the package name to make the package an executable program. The executable programs in Go are often referred to as commands in the official Go documentation. The entry point of the executable program is the main function of the main package.
go run <codefile>
go build
go install
The following go get command fetches the third-part package negroni and installs it into the GOPATH location:
go get github.com/codegangsta/negroni
go fmt <code>
The Go tool provides the fmt command to format Go code. It is a good practice to format Go programs before committing source files into version control systems. The go fmt command applies predefined styles to the source code for format source files, which ensures the right placement of curly brackets, ensures the proper usage of tabs and spaces, and alphabetically sorts package imports. The go fmt command can be applied at the package level or on a specific source file.
godoc fmt
godoc fmt Println
If you want to get documentation for the fmt package, type the following command in
the terminal. The godoc tool also provides browsable documentation on a web interface. To access the documentation through a web-based interface, start the web server provided by the godoc tool. Type the following command in the terminal:
godoc -http=:3000
fmt to format and print data.
En una librería, pongamos “calc” añadimos el archivo calc_test.go con el siguiente contenido:
package calc
import "testing"
func TestAdd(t *testing.T) {
var result = Add(3, 4)
if result != 7 {
t.Error("Expected 7, got", result);
}
}
Para correr tests: go test.
// `var` declares 1 or more variables. var a string = "initial" var b, c int = 1, 2 // Go will infer the type of initialized variables. var d = true // Variables declared without a corresponding // initialization are _zero-valued_. For example, the // zero value for an `int` is `0`. var e int // The `:=` syntax is shorthand for declaring and // initializing a variable, e.g. for // `var f string = "short"` in this case. f := "short"
Go also has another shorthand when you need to define multiple variables:
var ( a = 5 b = 10 c = 15 )
Use the keyword var (or const ) followed by parentheses with each variable on its own line.
const n = 500000000 const d = 3e20 / n
import ( "fmt" "./calc" )
With package alias:
import ( mongo "lib/mongodb/db" mysql "lib/mysql/db" ) ... mongo.Get() //calling method of package "lib/mongodb/db" mysql.Get() //calling method of package "lib/mysql/db"
The idiomatic way to provide a package name is to give short and simple lowercase names without underscores or mixed capital letters. The package names of the standard library are a great reference for naming packages.
You may need to provide some initialization logic for the packages, such as initializing package variables, initializing database objects, and providing some bootstrapping logic for the packages. The init function, which helps provide initialization logic into packages, is executed at the beginning of the execution.
package db
import (
"gopkg.in/mgo.v2"
)
var Session *mgo.Session //Database Session object
func init() {
// initialization code here
Session, err := mgo.Dial("localhost")
}
func get() {
//logic for get that uses Session object
}
In some scenarios, you may need to reference a package to invoke only its init method to execute the initialization logic in the referenced package, but not to use other identifiers. Suppose that you want the init function of package db (refer to Listing 2-3) to be invoked from the package main, but not use other functions. Keep in mind that you can’t directly call the init function by explicitly referencing it. If you want to reference a package only for invoking its init method, you can use a blank identifier (_) as the package alias name.
import ( "fmt" _ "lib/mongodb/db" )
Go source files are organized into directories as packages that provide code reusability into other packages. If you want to reuse package code into other shared libraries and executable programs, you must import the packages into your programs.
When you import a package into a program, you can reuse all the exported identifiers of the referenced packages. If you want to export variables, constants, and functions to be used with other programs, the name of the identifier must start with an uppercase letter.
Declaring an Integer Array of Five Elements
var x [5]int
x[0] = 10
x[1] = 20
x[2] = 30
x[3] = 40
x[4] = 50
x := [5]int{10, 20, 30, 40, 50}
// Initializing Values for Specific Elements
x := [5]int{2: 10, 4: 40} // [0 0 10 0 40]
For example, while arr[0:5] returns [1,2,3,4,5] , arr[1:4] returns [2,3,4] . arr[0:] is the same as arr[0:len(arr)] , arr[:5] is the same as arr[0:5], and arr[:] is the same as arr[0:len(arr)] .
Slices are a data structure that is very similar to an array, but has no specified length. It is an abstraction built on top of an array type that provides a more convenient way of working with collections.
var x []int
The length of the slice is the number of elements referred to by the slice; the capacity is the number of elements in the underlying array. A slice can’t hold values beyond its capacity; if you try to add more elements, a runtime error will occur. A slice can be grown by using the append function.
When you declare a slice with the make function, you can explicitly specify the length and capacity of a slice. If the slice capacity is not specified, the capacity is the same as the length.
x := make([]int, 5,10)
x := []int{10,20,30}
y := append(x, 40, 50)
// y = [10 20 30 40 50]
x := []int{10, 20, 30}
y := make([]int, 2)
copy(y, x)
copy(y, x)
// y = [10 20]
dict := make(map[string]string)
dict["go"] = "Golang"
dict["cs"] = "CSharp"
for k, v := range dict {
fmt.Printf("Key: %s Value: %s\n", k, v)
}
lan, ok := dict["go"]
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
// You can have an `if` statement without an else.
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
// A statement can precede conditionals; any variables
// declared in this statement are available in all
// branches.
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")
}
if lan, ok := dict["go"]; ok {
fmt.Println(lan, ok)
}
i := 2
fmt.Print("Write ", i, " as ")
switch i {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
}
switch time.Now().Weekday() {
case time.Saturday, time.Sunday:
fmt.Println("It's the weekend")
default:
fmt.Println("It's a weekday")
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
whatAmI := func(i interface{}) {
switch t := i.(type) {
case bool:
fmt.Println("I'm a bool")
case int:
fmt.Println("I'm an int")
default:
fmt.Printf("Don't know type %T\n", t)
}
}
whatAmI(true)
whatAmI(1)
whatAmI("hey")
x := []int{10, 20, 30, 40, 50}
for k, v := range x {
fmt.Printf("Index: %d Value: %d\n", k, v)
}
i := 1
for i <= 3 {
fmt.Println(i)
i = i + 1
}
// A classic initial/condition/after `for` loop.
for j := 7; j <= 9; j++ {
fmt.Println(j)
}
// `for` without a condition will loop repeatedly
// until you `break` out of the loop or `return` from
// the enclosing function.
for {
fmt.Println("loop")
break
}
// You can also `continue` to the next iteration of
// the loop.
for n := 0; n <= 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
}
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
}
}
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
for k := range kvs {
fmt.Println("key:", k)
}
for i, c := range "go" {
fmt.Println(i, c)
}
func vals() (int, int) {
return 3, 7
}
func main() {
a, b := vals()
_, c := vals()
}
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
// Variadic functions can be called in the usual way
// with individual arguments.
sum(1, 2)
sum(1, 2, 3)
// If you already have multiple args in a slice,
// apply them to a variadic function using
// `func(slice...)` like this.
nums := []int{1, 2, 3, 4}
sum(nums...)
}
func intSeq() func() int {
i := 0
return func() int {
i += 1
return i
}
}
func main() {
nextInt := intSeq()
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
newInts := intSeq()
fmt.Println(newInts())
}
A defer statement pushes a function call (or a code statement) onto a list. The list of saved “function calls” is executed after the surrounding function returns. The last added functions are invoked first from the list of deferred functions. Using defer, you can implement cleanup code in Go, which is more efficient than using a finally block in other languages. Suppose you add function f1 first, then f2, and finally f3 onto the deferred list; the order of the execution will be f3, f2, and then f1. This code block creates a session object for a MongoDB database. In the next line, the code statement session.Close() is added onto the deferred list to clean up the resources of the database session object after returning the surrounding function. You can add any number of code statements and functions onto the deferred list.
session, err := mgo.Dial("localhost") //MongoDB Session object
defer session.Close()
c := session.DB("taskdb").C("categories")
//code statements using session object
The panic function is a built-in function that lets you stop the normal flow of control and panic a function. When you call panic from a function, it stops the execution of the function, any deferred functions are executed, and the caller function gets a panicking function. Keep in mind that all deferred functions are executed normally before the execution stops. When developing applications, you will rarely call the panic function because your responsibility is to provide proper error messages rather than stopping the normal control flow. But in some scenarios, you may need to call the panic function if there are no possibilities to continue the normal flow of control. For example, if you can’t connect to a database server, it doesn’t make any sense to continue executing the application.
session, err := mgo.Dial("localhost") // Create MongoDB Session object
if err != nil {
panic(err)
}
defer session.Close()
The recover function is a built-in function that is typically used inside deferred functions that regain control of a panicking function. The recover function is useful only inside deferred functions because the differing statements are the only way to execute something when a function is panicking.
func doPanic() {
defer func() {
if e := recover(); e != nil {
fmt.Println("Recover with: ", e)
}
}()
panic("Just panicking for the sake of demo")
fmt.Println("This will never be called")
}
func main() {
fmt.Println("Starting to panic")
doPanic()
fmt.Println("Program regains control after panic recover")
}
type Person struct {
FirstName, LastName string
Dob time.Time
Email, Location string
}
var p Person
p.FirstName="Shiju"
p.LastName="Varghese"
p.Dob= time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC)
p.Email= "shiju@email.com"
p.Location="Kochi"
p:= Person {
FirstName : "Shiju",
LastName : "Varghese",
Dob : time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
Email : "shiju@email.com",
Location : "Kochi",
}
p:= Person {
"Shiju",
"Varghese",
time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
"shiju@email.com",
"Kochi",
}
//A person method
func (p Person) PrintName() {
fmt.Printf("\n%s %s\n", p.FirstName, p.LastName)
}
p. PrintName()
If you want to modify the data of a receiver from the method, the receiver must be a pointer:
func (p *Person) ChangeLocation(newLocation string) {
p.Location= newLocation
}
Because you want to call a pointer receiver method, you can create the Person type instance by providing the ampersand (&) operator.
p := &Person{
"Shiju",
"Varghese",
time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
"shiju@email.com",
"Kochi",
}
p.ChangeLocation("Santa Clara")
p.PrintName()
Type Embedding for Composition. The Person type is embedded into Admin and Member types so that all Person fields and methods will be available in these new types.
type Admin struct {
Person //type embedding for composition
Roles []string
}
type Member struct {
Person //type embedding for composition
Skills []string
}
alex := Admin{
Person{
"Alex",
"John",
time.Date(1970, time.January, 10, 0, 0, 0, 0, time.UTC),
"alex@email.com",
"New York"
},
[]string{"Manage Team", "Manage Tasks"},
}
//A person method
func (p Person) PrintDetails() {
fmt.Printf("[Date of Birth: %s, Email: %s, Location: %s ]\n", p.Dob.String(), p.Email, p.Location)
}
func (a Admin) PrintDetails() {
a.Person.PrintDetails()
fmt.Println("Admin Roles:")
for _, v := range a.Roles {
fmt.Println(v)
}
}
func one(xPtr *int) {
*xPtr = 1
}
func main() {
xPtr := new(int)
one(xPtr)
fmt.Println(*xPtr) // x is 1
}
The interface is one of the greatest features of the Go language because it provides contracts to user-defined concrete types, which allows you to define behaviors for your objects.
type User interface {
PrintName()
PrintDetails()
}
type Person struct {
// ...
}
func (p Person) PrintName() {
// ...
}
func (p Person) PrintDetails() {
// ...
}
alex := Person{"Alex", "John", time.Date(1970, time.January, 10, 0, 0, 0, 0, time.UTC), "alex@email.com", "New York",}
shiju := Person{"Shiju", "Varghese", time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC), "shiju@email.com",
"Kochi",}
users := []User{alex, shiju}
type Team struct {
Name, Description string
Users []User
}
func (t Team) GetTeamDetails() {
fmt.Printf("Team: %s - %s\n", t.Name, t.Description)
fmt.Println("Details of the team members:")
for _, v := range t.Users {
v.PrintName()
v.PrintDetails()
}
}
In Go, a goroutine is the primary mechanism for running programs concurrently. When you create a function as a goroutine, it works as an independent task unit that runs concurrently with other goroutines. In short, a goroutine is a lightweight thread managed by the Go runtime, but not the OS resources. Go runtime has a powerful piece of software component called the scheduler that controls and manages everything related to the scheduling and running of goroutines.
To invoke a function as a goroutine, use the keyword go:
go function()
Ensure that all goroutines are getting executed before the main program is terminated. You can achieve this by using the WaitGroup type provided by the sync standard library package.
func printCounts(label string) {
// Schedule the call to WaitGroup's Done to tell we are done.
defer wg.Done()
for count := 1; count <= 10; count++ {
sleep := rand.Int63n(1000)
time.Sleep(time.Duration(sleep) * time.Millisecond)
fmt.Printf("Count: %d from %s\n", count, label)
}
}
var wg sync.WaitGroup
func main() {
wg.Add(2)
fmt.Println("Start Goroutines")
go printCounts("A")
go printCounts("B")
fmt.Println("Waiting To Finish")
// Wait for the goroutines to finish.
wg.Wait()
fmt.Println("\nTerminating Program")
}
The Done method of the WaitGroup type is scheduled to call to tell the main program that the goroutine has executed. The Done method of the WaitGroup type is scheduled to call using the keyword defer. This keyword allows you to schedule other functions to be called when the function returns. In this example, the Done method will be invoked when the goroutine is executed, which ensures that the value of WaitGroup is decremented so the main function can check whether any goroutine is yet to be executed. In the main function, the Wait method of WaitGroup is called, which will check the count of WaitGroup and will block the program until it becomes zero. When the Done method of WaitGroup is called, the count will be decremented by one. At the beginning of the execution, the count is added as 2. When Wait is called, it will wait for the count to turn zero, thereby ensuring that both the goroutines are executed before the program terminates. When the count becomes zero, the program terminates.
The Go runtime scheduler manages the goroutine execution by leveraging the number of OS threads to attempt goroutine executions simultaneously. The value for the OS threads is taken from the GOMAXPROCS environment variable. Prior to Go 1.5, the default setting of GOMAXPROCS was 1, meaning that goroutines were running on a single OS thread by default. (Keep in mind that Go runtime can execute thousands of goroutines on a single OS thread.) With Go 1.5, the default setting of GOMAXPROCS was changed to the number of CPUs available, as determined by the NumCPU function provided by the runtime package. This default behavior lets the Go programs leverage all available CPU cores for running goroutines in parallel. The value of the GOMAXPROCS can be set by explicitly using the GOMAXPROCS environment variable or by calling runtime.
You can control the GOMAXPROCS setting in your program based on the context of your applications. Listing 3-19 is a code block that modifies the GOMAXPROCS to one from its default setting:
import "runtime" runtime.GOMAXPROCS(1)
Sometimes there is a need for communication among goroutines for sending and receiving data, hence the need for synchronization among goroutines. In many programming environments, communication among concurrent programs is complex or limited with features. Go allows you to communicate among goroutines using channels that enable the synchronization of goroutine execution. The built-in make function is used to declare a channel with the help of the keyword chan, followed by the type for specifying the type of data you are using for exchanging data.
A channel of integer type is declared, so integer values will be passed into channels.
// Unbuffered channel of integers. count := make(chan int) // Buffered channel of integers for buffering up to 10 values. count:= make(chan int, 10)
When buffered channels are declared, the capacity of channels to hold the data must be specified. If you try to send more data than its capacity, you get an error.
Unbuffered channels provide synchronous communication among goroutines, which ensures message delivery among them. With unbuffered channels, message sending is permitted only if there is a corresponding receiver that is ready to receive the messages. In this case, both sides of the channel have to wait until the other side is ready for sending and receiving messages. With buffered channels, a limited number of messages can be sent into the channel without a corresponding concurrent receiver for receiving those messages. After the messages are sent into buffered channels, those messages from the channel are received. Unlike unbuffered channels, message delivery can’t be guaranteed with buffered channels.
// Buffered channel of strings. messages := make(chan string, 2) // Send a message into the channel. messages <- "Golang"
count := make(chan int)
wg.Add(2)
go printCounts("A", count)
go printCounts("B", count)
count <- 1
// ...
func printCounts(label string, count chan int) {
defer wg.Done()
for {
val, ok := <-count
if !ok {
fmt.Println("Channel was closed")
return
}
fmt.Printf("Count: %d received from %s \n", val, label)
if val == 10 {
fmt.Printf("Channel Closed from %s \n", label)
close(count)
return
}
val++
count <- val
}
}
func main() {
messages := make(chan string, 2)
messages <- "Golang"
messages <- "Gopher"
//Recieve value from buffered channel
fmt.Println(<-messages)
fmt.Println(<-messages)
}
It is a simple example program that demonstrates a buffer channel without having any goroutines. It creates a messages channel for buffering up to two string values. Values are sent into the channel until its capacity of two. Because this channel is buffered, values can be sent without depending on a receiver receiving them. If you try to add more values than its capacity, you will get an error. Once the values are sent into the buffered channel, they can be received from the channel.
time.Date(1970, time.January, 10, 0, 0, 0, 0, time.UTC)
time.Sleep(time.Duration(sleep) * time.Millisecond)
sleep := rand.Int63n(1000)
wget https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz sudo tar -xvf go1.9.2.linux-amd64.tar.gz sudo mv go /usr/local export GOROOT=/usr/local/go sudo ln -s /usr/local/go/bin/go /usr/bin/go sudo ln -s /usr/local/go/bin/godoc /usr/bin/godoc sudo ln -s /usr/local/go/bin/gofmt /usr/bin/gofmt
You will need to install the 'golang' package. Also, when it is enabled, let it install the other tools.
If you wanted to debug you should change into the configuration the next variable (specially if only had a main.go file):
"program": "${workspaceRoot}",
A full example is:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceRoot}",
"env": {},
"args": [],
"showLog": true
}
]
}
package main
import (
"net/http"
)
func main() {
mux := http.NewServeMux()
fs := http.FileServer(http.Dir("public"))
mux.Handle("/", fs)
http.ListenAndServe(":8080", mux)
}
go get -u github.com/jinzhu/gormgo get -u github.com/go-sql-driver/mysqlpackage main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"fmt"
)
type Person struct {
ID uint `json:"id""`
FirstName string `json:"firstname"`
LastName string `json:"lastname""`
}
func main() {
db, err := gorm.Open("mysql", "root:pass@/test?charset=utf8&parseTime=True&loc=Local")
if err != nil {
fmt.Println(err)
}
defer db.Close()
db.AutoMigrate(&Person{})
p1 := Person{FirstName: "John", LastName: "Doe"}
p2 := Person{FirstName: "Jane", LastName: "Smith"}
db.Create(&p1)
db.Create(&p2)
var p3 Person
db.First(&p3)
fmt.Println(p1.LastName)
fmt.Println(p2.LastName)
fmt.Println(p3.LastName)
}
go get github.com/gin-gonic/ginpackage main
import (
"github.com/gin-gonic/gin"
"fmt"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello World",
})
})
r.Run()
}