Example: "hello world" program.
package main
//import the format package
import "fmt"
func main() {
fmt.Println("Hello World")
}
The var statement declares a list of variables. In variable declaration the type name is specified last. This is good since the type is optional. A var statement can be at package or function level. So we can have global variables and local variables.
//variables.go
package main
import "fmt"
var i, j int = 1, 2
func main() {
var (
c = true;
p = false;
g = "no";
)
fmt.Println(i, j, c, p, g)
}
A var declaration can include one initializer for each variable. Initializer is usually a constant literal. If an initializer is present, the type can be omitted. The variable will take the type of the initializer. Read the example below to understand better this concept:
//file var_list.go
package main
import "fmt"
var i, j int = 1, 2
func main() {
var c , p, g = true, false, "no"
fmt.Println(i, j, c, p, g)
}
In Go it is good to use constants instead of regular variables to define numbers or other values that will not change during program execution.
//file pub_con.go
package main
import "fmt"
const Pi = 3.14
func main() {
const World = "世界"
fmt.Println("Hello", World)
fmt.Println("Happy", Pi, "Day")
const Truth = true
fmt.Println("Go rules?", Truth)
}
The following keywords are reserved and may not be used as identifiers.
break | default | func | else | select |
case | defer | go | map | struct |
chan | interface | goto | package | switch |
const | fallthrough | if | range | type |
for | continue | import | return | var |
The following character sequences represent operators (including assignment operators) and punctuation:
+ & += &= && == != ( )
- | -= |= || < <= [ ]
* ^ *= ^= <- > >= { }
/ << /= <<= ++ = := , ;
% >> %= >>= -- ! ... . :
&^ &^=
Every Go program is made up of packages. Programs start running in package "main". The main package also contains the function main(). Using the import statement one package can be used into another package. By convention, the package name is the same as the last element of the import path.
//file imp_pack.go
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}
In this instance, th package "math/rand" comprises files that begin with the statement "package rand".
This code groups the imports into a parenthesis, "factored" import statement.
You can also write multiple import statements, like:
import "fmt"
import "math"
But it is good style to use the factored import statement.
In Go, a name is exported automaticly if it begins with a capital letter. This is disruptive convention that makes Go different than Java. Where in Java class names start with capital letter, but Go do not have classes.
For example the "println()" function is using capital P so is fmt.Println() instead of fmt.println(). When the package "fmt" is imported only the capital letter functions and elements are accessible using dot notation.
Note: This convention is a bit strange but you get use to it.
Go is object oriented language and has support for creation of objects that have methods and properties. However Go do not have classes like Java does. It has only types like Ada language.
A method is a function with a special receiver argument. This argument has the role of "this" or "self" that you can use in Java or Python. The receiver appears in its own argument list between the func keyword and the method name.
You can define methods on user defined types by using receiver argument. Types with methods can be based on collections, structures or simple types. In this way a type becomes like class.
In next example, the Abs method has a receiver of type Vertex.The method Abs() can be called using dot notation with the type name used as a qualifier like this v.Abs().
//file class.go
package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs())
}
In Java we use keyword "new" to create an instance of a class. In Go we do not have keyword new and there are no classes, but there is instante of a type that is an object.
An interface is an abstract data type. It define of a set of methods that must be implemented for a type that implement the interface. A value of interface type can hold any value that implements those methods.
//file interface.go
package main
import (
"fmt"
"math"
)
//define an interface
type Abser interface {
Abs() float64
}
func main() {
var a Abser
//define a function f
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
a = f // a MyFloat implements Abser
a = &v // a *Vertex implements Abser
// In the following line, v is a Vertex (not *Vertex)
// therefore does NOT implement Abser.
a = v
fmt.Println(a.Abs())
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
Note: There is an error in the example code on line 22. Vertex (the value type) doesn't implement Abser because the Abs method is defined only on *Vertex (the pointer type).
The interface type that specifies zero methods is known as the empty interface: interface{}
An empty interface may hold values of any type. (Every type implements at least zero methods.)
Empty interfaces are used by code that handles values of unknown type. For example, fmt.Print takes any number of arguments of type interface{}.
//file empty_interface.go
package main
import "fmt"
func main() {
var i interface{}
describe(i)
i = 42
describe(i)
i = "hello"
describe(i)
}
func describe(i interface{}) {
fmt.Printf("(%v, %T)\n", i, i)
}
Under the covers, interface values can be thought of as a tuple of a value and a concrete type (value, type). An interface value holds a value of a specific underlying concrete type. Calling a method on an interface value executes the method of the same name on its underlying type.
package main
import (
"fmt"
"math"
)
type I interface {
M()
}
type T struct {
S string
}
func (t *T) M() {
fmt.Println(t.S)
}
type F float64
func (f F) M() {
fmt.Println(f)
}
func main() {
var i I
i = &T{"Hello"}
describe(i)
i.M()
i = F(math.Pi)
describe(i)
i.M()
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
Read next: Data Types